Project import generated by Copybara.

NOKEYCHECK=True
GitOrigin-RevId: d3c032d9650cd8d3d570f345069990c652057293
diff --git a/wl/components/shared/devctrl_if/phyioctl_defs.h b/wl/components/shared/devctrl_if/phyioctl_defs.h
new file mode 100644
index 0000000..01132ab
--- /dev/null
+++ b/wl/components/shared/devctrl_if/phyioctl_defs.h
@@ -0,0 +1,47 @@
+/*
+ * PHY firmware debug interface.
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 2017, Broadcom. 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$
+ */
+
+#ifndef _phyioctl_defs_h_
+#define _phyioctl_defs_h_
+
+/* Debug message levels */
+#define PHYHAL_ERROR		0x0001
+#define PHYHAL_TRACE		0x0002
+#define PHYHAL_INFORM		0x0004
+#define PHYHAL_TMP		0x0008
+#define PHYHAL_TXPWR		0x0010
+#define PHYHAL_CAL		0x0020
+#define PHYHAL_ACI		0x0040
+#define PHYHAL_RADAR		0x0080
+#define PHYHAL_THERMAL		0x0100
+#define PHYHAL_PAPD		0x0200
+#define PHYHAL_FCBS		0x0400
+#define PHYHAL_RXIQ		0x0800
+#define PHYHAL_WD		0x1000
+#define PHYHAL_CHANLOG		0x2000
+
+#define PHYHAL_TIMESTAMP	0x8000
+
+#endif /* _phyioctl_defs_h_ */
diff --git a/wl/components/shared/devctrl_if/wlioctl.h b/wl/components/shared/devctrl_if/wlioctl.h
new file mode 100644
index 0000000..c4a0203
--- /dev/null
+++ b/wl/components/shared/devctrl_if/wlioctl.h
@@ -0,0 +1,13014 @@
+/*
+ * Custom OID/ioctl definitions for
+ *
+ *
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 2017, Broadcom. 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: wlioctl.h 663420 2017-01-04 06:58:04Z $
+ */
+
+#ifndef _wlioctl_h_
+#define	_wlioctl_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+#include <proto/bcmip.h>
+#include <proto/bcmeth.h>
+#include <proto/bcmip.h>
+#include <proto/bcmipv6.h>
+#include <proto/bcmevent.h>
+#include <proto/802.11.h>
+#ifdef WLMESH
+#include <proto/802.11s.h>
+#endif
+#include <proto/802.1d.h>
+#include <bcmwifi_channels.h>
+#include <bcmwifi_rates.h>
+#include <devctrl_if/wlioctl_defs.h>
+#include <proto/bcmipv6.h>
+
+#include <bcm_mpool_pub.h>
+#include <bcmcdc.h>
+
+
+typedef struct {
+	uint32 num;
+	chanspec_t list[1];
+} chanspec_list_t;
+
+#define RSN_KCK_LENGTH	16
+#define RSN_KEK_LENGTH	16
+#define TPK_FTM_LEN		16
+#ifndef INTF_NAME_SIZ
+#define INTF_NAME_SIZ	16
+#endif
+
+/**Used to send ioctls over the transport pipe */
+typedef struct remote_ioctl {
+	cdc_ioctl_t	msg;
+	uint32		data_len;
+	char           intf_name[INTF_NAME_SIZ];
+} rem_ioctl_t;
+#define REMOTE_SIZE	sizeof(rem_ioctl_t)
+
+#define MAX_NUM_D11CORES 2
+
+/**DFS Forced param */
+typedef struct wl_dfs_forced_params {
+	chanspec_t chspec;
+	uint16 version;
+	chanspec_list_t chspec_list;
+} wl_dfs_forced_t;
+
+#define DFS_PREFCHANLIST_VER 0x01
+#define WL_CHSPEC_LIST_FIXED_SIZE	OFFSETOF(chanspec_list_t, list)
+/* size of dfs forced param size given n channels are in the list */
+#define WL_DFS_FORCED_PARAMS_SIZE(n) \
+	(sizeof(wl_dfs_forced_t) + (((n) < 1) ? (0) : (((n) - 1)* sizeof(chanspec_t))))
+#define WL_DFS_FORCED_PARAMS_FIXED_SIZE \
+	(WL_CHSPEC_LIST_FIXED_SIZE + OFFSETOF(wl_dfs_forced_t, chspec_list))
+#define WL_DFS_FORCED_PARAMS_MAX_SIZE \
+	WL_DFS_FORCED_PARAMS_FIXED_SIZE + (WL_NUMCHANNELS * sizeof(chanspec_t))
+
+/**association decision information */
+typedef struct {
+	uint8		assoc_approved;		/**< (re)association approved */
+	uint8		pad;
+	uint16		reject_reason;		/**< reason code for rejecting association */
+	struct		ether_addr   da;
+	uint8		pad1[6];
+#if 0 && (NDISVER >= 0x0620)
+	LARGE_INTEGER	sys_time;		/**< current system time */
+#else
+	int64		sys_time;		/**< current system time */
+#endif
+} assoc_decision_t;
+
+#define DFS_SCAN_S_IDLE		-1
+#define DFS_SCAN_S_RADAR_FREE 0
+#define DFS_SCAN_S_RADAR_FOUND 1
+#define DFS_SCAN_S_INPROGESS 2
+#define DFS_SCAN_S_SCAN_ABORTED 3
+#define DFS_SCAN_S_SCAN_MODESW_INPROGRESS 4
+#define DFS_SCAN_S_MAX 5
+
+
+#define ACTION_FRAME_SIZE 1800
+
+typedef struct wl_action_frame {
+	struct ether_addr 	da;
+	uint16 			len;
+	uint32 			packetId;
+	uint8			data[ACTION_FRAME_SIZE];
+} wl_action_frame_t;
+
+#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame)
+
+typedef struct ssid_info
+{
+	uint8		ssid_len;	/**< the length of SSID */
+	uint8		ssid[32];	/**< SSID string */
+} ssid_info_t;
+
+typedef struct wl_af_params {
+	uint32			channel;
+	int32			dwell_time;
+	struct ether_addr	BSSID;
+	wl_action_frame_t	action_frame;
+} wl_af_params_t;
+
+#define WL_WIFI_AF_PARAMS_SIZE sizeof(struct wl_af_params)
+
+#define MFP_TEST_FLAG_NORMAL	0
+#define MFP_TEST_FLAG_ANY_KEY	1
+typedef struct wl_sa_query {
+	uint32 flag;
+	uint8  action;
+	uint16 id;
+	struct ether_addr da;
+} wl_sa_query_t;
+
+/* EXT_STA */
+/**association information */
+typedef struct {
+	uint32		assoc_req;	/**< offset to association request frame */
+	uint32		assoc_req_len;	/**< association request frame length */
+	uint32		assoc_rsp;	/**< offset to association response frame */
+	uint32		assoc_rsp_len;	/**< association response frame length */
+	uint32		bcn;		/**< offset to AP beacon */
+	uint32		bcn_len;	/**< AP beacon length */
+	uint32		wsec;		/**< ucast security algo */
+	uint32		wpaie;		/**< offset to WPA ie */
+	uint8		auth_alg;	/**< 802.11 authentication mode */
+	uint8		WPA_auth;	/**< WPA: authenticated key management */
+	uint8		ewc_cap;	/**< EWC (MIMO) capable */
+	uint8		ofdm;		/**< OFDM */
+} assoc_info_t;
+/* defined(EXT_STA) */
+
+/* Flags for OBSS IOVAR Parameters */
+#define WL_OBSS_DYN_BWSW_FLAG_ACTIVITY_PERIOD        (0x01)
+#define WL_OBSS_DYN_BWSW_FLAG_NOACTIVITY_PERIOD      (0x02)
+#define WL_OBSS_DYN_BWSW_FLAG_NOACTIVITY_INCR_PERIOD (0x04)
+#define WL_OBSS_DYN_BWSW_FLAG_PSEUDO_SENSE_PERIOD    (0x08)
+#define WL_OBSS_DYN_BWSW_FLAG_RX_CRS_PERIOD          (0x10)
+#define WL_OBSS_DYN_BWSW_FLAG_DUR_THRESHOLD          (0x20)
+#define WL_OBSS_DYN_BWSW_FLAG_TXOP_PERIOD            (0x40)
+
+/* OBSS IOVAR Version information */
+#define WL_PROT_OBSS_CONFIG_PARAMS_VERSION 1
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint8 obss_bwsw_activity_cfm_count_cfg; /**< configurable count in
+		* seconds before we confirm that OBSS is present and
+		* dynamically activate dynamic bwswitch.
+		*/
+	uint8 obss_bwsw_no_activity_cfm_count_cfg; /**< configurable count in
+		* seconds before we confirm that OBSS is GONE and
+		* dynamically start pseudo upgrade. If in pseudo sense time, we
+		* will see OBSS, [means that, we false detected that OBSS-is-gone
+		* in watchdog] this count will be incremented in steps of
+		* obss_bwsw_no_activity_cfm_count_incr_cfg for confirming OBSS
+		* detection again. Note that, at present, max 30seconds is
+		* allowed like this. [OBSS_BWSW_NO_ACTIVITY_MAX_INCR_DEFAULT]
+		*/
+	uint8 obss_bwsw_no_activity_cfm_count_incr_cfg; /* see above
+		*/
+	uint16 obss_bwsw_pseudo_sense_count_cfg; /**< number of msecs/cnt to be in
+		* pseudo state. This is used to sense/measure the stats from lq.
+		*/
+	uint8 obss_bwsw_rx_crs_threshold_cfg; /**< RX CRS default threshold */
+	uint8 obss_bwsw_dur_thres; /**< OBSS dyn bwsw trigger/RX CRS Sec */
+	uint8 obss_bwsw_txop_threshold_cfg; /**< TXOP default threshold */
+} BWL_POST_PACKED_STRUCT wlc_obss_dynbwsw_config_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 version;	/**< version field */
+	uint32 config_mask;
+	uint32 reset_mask;
+	wlc_obss_dynbwsw_config_t config_params;
+} BWL_POST_PACKED_STRUCT obss_config_params_t;
+#include <packed_section_end.h>
+
+/**bsscfg type */
+typedef enum bsscfg_type {
+	BSSCFG_TYPE_GENERIC = 0,	/**< Generic AP/STA/IBSS BSS */
+	BSSCFG_TYPE_P2P = 1,		/**< P2P BSS */
+	/* index 2 earlier used for BTAMP */
+	BSSCFG_TYPE_PSTA = 3,
+	BSSCFG_TYPE_TDLS = 4,
+	BSSCFG_TYPE_SLOTTED_BSS = 5,
+	BSSCFG_TYPE_PROXD = 6,
+	BSSCFG_TYPE_NAN = 7,
+	BSSCFG_TYPE_MESH = 8,
+	BSSCFG_TYPE_AIBSS = 9
+} bsscfg_type_t;
+
+/* bsscfg subtype */
+typedef enum bsscfg_subtype {
+	BSSCFG_SUBTYPE_NONE = 0,
+	BSSCFG_GENERIC_STA = 1,		/* GENERIC */
+	BSSCFG_GENERIC_AP = 2,
+	BSSCFG_GENERIC_IBSS = 6,
+	BSSCFG_P2P_GC = 3,		/* P2P */
+	BSSCFG_P2P_GO = 4,
+	BSSCFG_P2P_DISC = 5,
+	/* Index 7 & 8 earlier used for BTAMP */
+	BSSCFG_SUBTYPE_AWDL = 9, /* SLOTTED_BSS_TYPE */
+	BSSCFG_SUBTYPE_NAN_MGMT = 10,
+	BSSCFG_SUBTYPE_NAN_DATA = 11,
+	BSSCFG_SUBTYPE_NAN_MGMT_DATA = 12
+} bsscfg_subtype_t;
+
+typedef struct wlc_bsscfg_info {
+	uint32 type;
+	uint32 subtype;
+} wlc_bsscfg_info_t;
+
+/* ULP SHM Offsets info */
+typedef struct ulp_shm_info {
+	uint32 m_ulp_ctrl_sdio;
+	uint32 m_ulp_wakeevt_ind;
+	uint32 m_ulp_wakeind;
+} ulp_shm_info_t;
+
+
+/* Legacy structure to help keep backward compatible wl tool and tray app */
+
+#define	LEGACY_WL_BSS_INFO_VERSION	107	/**< older version of wl_bss_info struct */
+
+typedef struct wl_bss_info_107 {
+	uint32		version;		/**< version field */
+	uint32		length;			/**< byte length of data in this record,
+						 * starting at version and including IEs
+						 */
+	struct ether_addr BSSID;
+	uint16		beacon_period;		/**< units are Kusec */
+	uint16		capability;		/**< Capability information */
+	uint8		SSID_len;
+	uint8		SSID[32];
+	struct {
+		uint32	count;			/**< # rates in this set */
+		uint8	rates[16];		/**< rates in 500kbps units w/hi bit set if basic */
+	} rateset;				/**< supported rates */
+	uint8		channel;		/**< Channel no. */
+	uint16		atim_window;		/**< units are Kusec */
+	uint8		dtim_period;		/**< DTIM period */
+	int16		RSSI;			/**< receive signal strength (in dBm) */
+	int8		phy_noise;		/**< noise (in dBm) */
+	uint32		ie_length;		/**< byte length of Information Elements */
+	/* variable length Information Elements */
+} wl_bss_info_107_t;
+
+/*
+ * Per-BSS information structure.
+ */
+
+#define	LEGACY2_WL_BSS_INFO_VERSION	108		/**< old version of wl_bss_info struct */
+
+/**
+ * BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in wl_scan_results_t)
+ */
+typedef struct wl_bss_info_108 {
+	uint32		version;		/**< version field */
+	uint32		length;			/**< byte length of data in this record,
+						 * starting at version and including IEs
+						 */
+	struct ether_addr BSSID;
+	uint16		beacon_period;		/**< units are Kusec */
+	uint16		capability;		/**< Capability information */
+	uint8		SSID_len;
+	uint8		SSID[32];
+	struct {
+		uint32	count;			/**< # rates in this set */
+		uint8	rates[16];		/**< rates in 500kbps units w/hi bit set if basic */
+	} rateset;				/**< supported rates */
+	chanspec_t	chanspec;		/**< chanspec for bss */
+	uint16		atim_window;		/**< units are Kusec */
+	uint8		dtim_period;		/**< DTIM period */
+	int16		RSSI;			/**< receive signal strength (in dBm) */
+	int8		phy_noise;		/**< noise (in dBm) */
+
+	uint8		n_cap;			/**< BSS is 802.11N Capable */
+	uint32		nbss_cap;		/**< 802.11N BSS Capabilities (based on HT_CAP_*) */
+	uint8		ctl_ch;			/**< 802.11N BSS control channel number */
+	uint32		reserved32[1];		/**< Reserved for expansion of BSS properties */
+	uint8		flags;			/**< flags */
+	uint8		reserved[3];		/**< Reserved for expansion of BSS properties */
+	uint8		basic_mcs[MCSSET_LEN];	/**< 802.11N BSS required MCS set */
+
+	uint16		ie_offset;		/**< offset at which IEs start, from beginning */
+	uint32		ie_length;		/**< byte length of Information Elements */
+	/* Add new fields here */
+	/* variable length Information Elements */
+} wl_bss_info_108_t;
+
+
+#define	WL_BSS_INFO_VERSION	109		/**< current version of wl_bss_info struct */
+
+/**
+ * BSS info structure
+ * Applications MUST CHECK ie_offset field and length field to access IEs and
+ * next bss_info structure in a vector (in wl_scan_results_t)
+ */
+typedef struct wl_bss_info {
+	uint32		version;		/**< version field */
+	uint32		length;			/**< byte length of data in this record,
+						 * starting at version and including IEs
+						 */
+	struct ether_addr BSSID;
+	uint16		beacon_period;		/**< units are Kusec */
+	uint16		capability;		/**< Capability information */
+	uint8		SSID_len;
+	uint8		SSID[32];
+	uint8		bcnflags;		/* additional flags w.r.t. beacon */
+	struct {
+		uint32	count;			/**< # rates in this set */
+		uint8	rates[16];		/**< rates in 500kbps units w/hi bit set if basic */
+	} rateset;				/**< supported rates */
+	chanspec_t	chanspec;		/**< chanspec for bss */
+	uint16		atim_window;		/**< units are Kusec */
+	uint8		dtim_period;		/**< DTIM period */
+	uint8		accessnet;		/* from beacon interwork IE (if bcnflags) */
+	int16		RSSI;			/**< receive signal strength (in dBm) */
+	int8		phy_noise;		/**< noise (in dBm) */
+	uint8		n_cap;			/**< BSS is 802.11N Capable */
+	uint16		freespace1;		/* make implicit padding explicit */
+	uint32		nbss_cap;		/**< 802.11N+AC BSS Capabilities */
+	uint8		ctl_ch;			/**< 802.11N BSS control channel number */
+	uint8		padding1[3];		/**< explicit struct alignment padding */
+	uint16		vht_rxmcsmap;	/**< VHT rx mcs map (802.11ac IE, VHT_CAP_MCS_MAP_*) */
+	uint16		vht_txmcsmap;	/**< VHT tx mcs map (802.11ac IE, VHT_CAP_MCS_MAP_*) */
+	uint8		flags;			/**< flags */
+	uint8		vht_cap;		/**< BSS is vht capable */
+	uint8		reserved[2];		/**< Reserved for expansion of BSS properties */
+	uint8		basic_mcs[MCSSET_LEN];	/**< 802.11N BSS required MCS set */
+
+	uint16		ie_offset;		/**< offset at which IEs start, from beginning */
+	uint16		freespace2;		/* making implicit padding explicit */
+	uint32		ie_length;		/**< byte length of Information Elements */
+	int16		SNR;			/**< average SNR of during frame reception */
+	uint16		vht_mcsmap;		/**< STA's Associated vhtmcsmap */
+	uint16		vht_mcsmap_prop;	/**< STA's Associated prop vhtmcsmap */
+	uint16		vht_txmcsmap_prop;	/**< prop VHT tx mcs prop */
+	/* Add new fields here */
+	/* variable length Information Elements */
+} wl_bss_info_t;
+
+#define	WL_GSCAN_FULL_RESULT_VERSION	2	/* current version of wl_gscan_result_t struct */
+#define WL_GSCAN_INFO_FIXED_FIELD_SIZE   (sizeof(wl_gscan_bss_info_t) - sizeof(wl_bss_info_t))
+
+typedef struct wl_gscan_bss_info {
+	uint32      timestamp[2];
+	wl_bss_info_t info;
+	/* Do not add any more members below, fixed  */
+	/* and variable length Information Elements to follow */
+} wl_gscan_bss_info_t;
+
+
+typedef struct wl_bsscfg {
+	uint32  bsscfg_idx;
+	uint32  wsec;
+	uint32  WPA_auth;
+	uint32  wsec_index;
+	uint32  associated;
+	uint32  BSS;
+	uint32  phytest_on;
+	struct ether_addr   prev_BSSID;
+	struct ether_addr   BSSID;
+	uint32  targetbss_wpa2_flags;
+	uint32 assoc_type;
+	uint32 assoc_state;
+} wl_bsscfg_t;
+
+typedef struct wl_if_add {
+	uint32  bsscfg_flags;
+	uint32  if_flags;
+	uint32  ap;
+	struct ether_addr   mac_addr;
+	uint32  wlc_index;
+} wl_if_add_t;
+
+typedef struct wl_bss_config {
+	uint32	atim_window;
+	uint32	beacon_period;
+	uint32	chanspec;
+} wl_bss_config_t;
+
+#define WL_BSS_USER_RADAR_CHAN_SELECT	0x1	/**< User application will randomly select
+						 * radar channel.
+						 */
+
+#define DLOAD_HANDLER_VER		1	/**< Downloader version */
+#define DLOAD_FLAG_VER_MASK		0xf000	/**< Downloader version mask */
+#define DLOAD_FLAG_VER_SHIFT		12	/**< Downloader version shift */
+
+#define DL_CRC_NOT_INUSE	0x0001
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define DL_BEGIN		0x0002
+#define DL_END			0x0004
+
+/* Flags for Major/Minor/Date number shift and mask */
+#define EPI_VER_SHIFT     16
+#define EPI_VER_MASK      0xFFFF
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/** generic download types & flags */
+enum {
+	DL_TYPE_UCODE = 1,
+	DL_TYPE_CLM = 2
+};
+
+/** ucode type values */
+enum {
+	UCODE_FW,
+	INIT_VALS,
+	BS_INIT_VALS
+};
+
+struct wl_dload_data {
+	uint16 flag;
+	uint16 dload_type;
+	uint32 len;
+	uint32 crc;
+	uint8  data[1];
+};
+typedef struct wl_dload_data wl_dload_data_t;
+
+struct wl_ucode_info {
+	uint32 ucode_type;
+	uint32 num_chunks;
+	uint32 chunk_len;
+	uint32 chunk_num;
+	uint8  data_chunk[1];
+};
+typedef struct wl_ucode_info wl_ucode_info_t;
+
+struct wl_clm_dload_info {
+	uint32 ds_id;
+	uint32 clm_total_len;
+	uint32 num_chunks;
+	uint32 chunk_len;
+	uint32 chunk_offset;
+	uint8  data_chunk[1];
+};
+typedef struct wl_clm_dload_info wl_clm_dload_info_t;
+
+
+typedef struct wlc_ssid {
+	uint32		SSID_len;
+	uint8		SSID[DOT11_MAX_SSID_LEN];
+} wlc_ssid_t;
+
+typedef struct wlc_ssid_ext {
+	uint8       hidden;
+	uint16     flags;
+	uint8	   SSID_len;
+	int8	   rssi_thresh;
+	uint8		SSID[DOT11_MAX_SSID_LEN];
+} wlc_ssid_ext_t;
+
+#define MAX_PREFERRED_AP_NUM     5
+typedef struct wlc_fastssidinfo {
+	uint32			SSID_channel[MAX_PREFERRED_AP_NUM];
+	wlc_ssid_t		SSID_info[MAX_PREFERRED_AP_NUM];
+} wlc_fastssidinfo_t;
+
+typedef struct wnm_url {
+	uint8   len;
+	uint8   data[1];
+} wnm_url_t;
+
+typedef struct chan_scandata {
+	uint8		txpower;
+	uint8		pad;
+	chanspec_t	channel;		/**< Channel num, bw, ctrl_sb and band */
+	uint32		channel_mintime;
+	uint32		channel_maxtime;
+} chan_scandata_t;
+
+typedef enum wl_scan_type {
+	EXTDSCAN_FOREGROUND_SCAN,
+	EXTDSCAN_BACKGROUND_SCAN,
+	EXTDSCAN_FORCEDBACKGROUND_SCAN
+} wl_scan_type_t;
+
+#define WLC_EXTDSCAN_MAX_SSID		5
+
+typedef struct wl_extdscan_params {
+	int8 		nprobes;		/**< 0, passive, otherwise active */
+	int8    	split_scan;		/**< split scan */
+	int8		band;			/**< band */
+	int8		pad;
+	wlc_ssid_t 	ssid[WLC_EXTDSCAN_MAX_SSID]; /**< ssid list */
+	uint32		tx_rate;		/**< in 500ksec units */
+	wl_scan_type_t	scan_type;		/**< enum */
+	int32 		channel_num;
+	chan_scandata_t channel_list[1];	/**< list of chandata structs */
+} wl_extdscan_params_t;
+
+#define WL_EXTDSCAN_PARAMS_FIXED_SIZE 	(sizeof(wl_extdscan_params_t) - sizeof(chan_scandata_t))
+
+#define WL_SCAN_PARAMS_SSID_MAX 	10
+
+typedef struct wl_scan_params {
+	wlc_ssid_t ssid;		/**< default: {0, ""} */
+	struct ether_addr bssid;	/**< default: bcast */
+	int8 bss_type;			/**< default: any,
+					 * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
+					 */
+	uint8 scan_type;		/**< flags, 0 use default */
+	int32 nprobes;			/**< -1 use default, number of probes per channel */
+	int32 active_time;		/**< -1 use default, dwell time per channel for
+					 * active scanning
+					 */
+	int32 passive_time;		/**< -1 use default, dwell time per channel
+					 * for passive scanning
+					 */
+	int32 home_time;		/**< -1 use default, dwell time for the home channel
+					 * between channel scans
+					 */
+	int32 channel_num;		/**< count of channels and ssids that follow
+					 *
+					 * low half is count of channels in channel_list, 0
+					 * means default (use all available channels)
+					 *
+					 * high half is entries in wlc_ssid_t array that
+					 * follows channel_list, aligned for int32 (4 bytes)
+					 * meaning an odd channel count implies a 2-byte pad
+					 * between end of channel_list and first ssid
+					 *
+					 * if ssid count is zero, single ssid in the fixed
+					 * parameter portion is assumed, otherwise ssid in
+					 * the fixed portion is ignored
+					 */
+	uint16 channel_list[1];		/**< list of chanspecs */
+} wl_scan_params_t;
+
+/** size of wl_scan_params not including variable length array */
+#define WL_SCAN_PARAMS_FIXED_SIZE 64
+#define WL_MAX_ROAMSCAN_DATSZ	(WL_SCAN_PARAMS_FIXED_SIZE + (WL_NUMCHANNELS * sizeof(uint16)))
+
+#define ISCAN_REQ_VERSION 1
+
+/** incremental scan struct */
+typedef struct wl_iscan_params {
+	uint32 version;
+	uint16 action;
+	uint16 scan_duration;
+	wl_scan_params_t params;
+} wl_iscan_params_t;
+
+/** 3 fields + size of wl_scan_params, not including variable length array */
+#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(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;
+
+/** size of wl_scan_results not including variable length array */
+#define WL_SCAN_RESULTS_FIXED_SIZE (sizeof(wl_scan_results_t) - sizeof(wl_bss_info_t))
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#if defined(SIMPLE_ISCAN)
+/** the buf lengh can be WLC_IOCTL_MAXLEN (8K) to reduce iteration */
+#define WLC_IW_ISCAN_MAXLEN   2048
+typedef struct iscan_buf {
+	struct iscan_buf * next;
+	int8   iscan_buf[WLC_IW_ISCAN_MAXLEN];
+} iscan_buf_t;
+#endif /* SIMPLE_ISCAN */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define ESCAN_REQ_VERSION 1
+
+/** event scan reduces amount of SOC memory needed to store scan results */
+typedef struct wl_escan_params {
+	uint32 version;
+	uint16 action;
+	uint16 sync_id;
+	wl_scan_params_t params;
+} wl_escan_params_t;
+
+#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t))
+
+/** event scan reduces amount of SOC memory needed to store scan results */
+typedef struct wl_escan_result {
+	uint32 buflen;
+	uint32 version;
+	uint16 sync_id;
+	uint16 bss_count;
+	wl_bss_info_t bss_info[1];
+} wl_escan_result_t;
+
+#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t))
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+typedef struct wl_gscan_result {
+	uint32 buflen;
+	uint32 version;
+	uint32 scan_ch_bucket;
+	wl_gscan_bss_info_t bss_info[1];
+} wl_gscan_result_t;
+
+#define WL_GSCAN_RESULTS_FIXED_SIZE (sizeof(wl_gscan_result_t) - sizeof(wl_gscan_bss_info_t))
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/** incremental scan results struct */
+typedef struct wl_iscan_results {
+	uint32 status;
+	wl_scan_results_t results;
+} wl_iscan_results_t;
+
+/** size of wl_iscan_results not including variable length array */
+#define WL_ISCAN_RESULTS_FIXED_SIZE \
+	(WL_SCAN_RESULTS_FIXED_SIZE + OFFSETOF(wl_iscan_results_t, results))
+
+typedef struct wl_probe_params {
+	wlc_ssid_t ssid;
+	struct ether_addr bssid;
+	struct ether_addr mac;
+} wl_probe_params_t;
+
+#define WL_MAXRATES_IN_SET		16	/**< max # of rates in a rateset */
+typedef struct wl_rateset {
+	uint32	count;				/**< # rates in this set */
+	uint8	rates[WL_MAXRATES_IN_SET];	/**< rates in 500kbps units w/hi bit set if basic */
+} wl_rateset_t;
+
+typedef struct wl_rateset_args {
+	uint32	count;				/**< # rates in this set */
+	uint8	rates[WL_MAXRATES_IN_SET];	/**< rates in 500kbps units w/hi bit set if basic */
+	uint8   mcs[MCSSET_LEN];        	/**< supported mcs index bit map */
+	uint16 vht_mcs[VHT_CAP_MCS_MAP_NSS_MAX]; /**< supported mcs index bit map per nss */
+} 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];	/**< one for each stream */
+	uint8	txbf_rate_mcs_bcm[TXBF_RATE_MCS_ALL];	/**< one for each stream */
+	uint16	txbf_rate_vht[TXBF_RATE_VHT_ALL];	/**< one for each stream */
+	uint16	txbf_rate_vht_bcm[TXBF_RATE_VHT_ALL];	/**< one for each stream */
+	uint8	txbf_rate_ofdm[TXBF_RATE_OFDM_ALL]; /**< bitmap of ofdm rates that enables txbf */
+	uint8	txbf_rate_ofdm_bcm[TXBF_RATE_OFDM_ALL]; /* bitmap of ofdm rates that enables txbf */
+	uint8	txbf_rate_ofdm_cnt;
+	uint8	txbf_rate_ofdm_cnt_bcm;
+} wl_txbf_rateset_t;
+
+#define NUM_BFGAIN_ARRAY_1RX	2
+#define NUM_BFGAIN_ARRAY_2RX	3
+#define NUM_BFGAIN_ARRAY_3RX	4
+#define NUM_BFGAIN_ARRAY_4RX	5
+
+typedef struct wl_txbf_expgainset {
+	/* bitmap for each element: B[4:0]=>c0, B[9:5]=>c1, B[14:10]=>c2, B[19:15]=>c[3-7]
+	 * B[24:20]=>c[8-9], B[29:25]=>c[10-11]
+	 */
+	uint32	bfgain_2x1[NUM_BFGAIN_ARRAY_1RX]; /* exp     1ss, imp 1ss */
+	uint32	bfgain_2x2[NUM_BFGAIN_ARRAY_2RX]; /* exp [1-2]ss, imp 1ss */
+	uint32	bfgain_3x1[NUM_BFGAIN_ARRAY_1RX];
+	uint32	bfgain_3x2[NUM_BFGAIN_ARRAY_2RX];
+	uint32	bfgain_3x3[NUM_BFGAIN_ARRAY_3RX]; /* exp [1-3]ss, imp 1ss */
+	uint32	bfgain_4x1[NUM_BFGAIN_ARRAY_1RX];
+	uint32	bfgain_4x2[NUM_BFGAIN_ARRAY_2RX];
+	uint32	bfgain_4x3[NUM_BFGAIN_ARRAY_3RX];
+	uint32	bfgain_4x4[NUM_BFGAIN_ARRAY_4RX]; /* exp [1-4]ss, imp 1ss */
+} wl_txbf_expgainset_t;
+
+#define OFDM_RATE_MASK			0x0000007f
+typedef uint8 ofdm_rates_t;
+
+typedef struct wl_rates_info {
+	wl_rateset_t rs_tgt;
+	uint32 phy_type;
+	int32 bandtype;
+	uint8 cck_only;
+	uint8 rate_mask;
+	uint8 mcsallow;
+	uint8 bw;
+	uint8 txstreams;
+} wl_rates_info_t;
+
+/**uint32 list */
+typedef struct wl_uint32_list {
+	/** in - # of elements, out - # of entries */
+	uint32 count;
+	/** variable length uint32 list */
+	uint32 element[1];
+} wl_uint32_list_t;
+
+/* WLC_SET_ALLOW_MODE values */
+#define ALLOW_MODE_ANY_BSSID		0
+#define ALLOW_MODE_ONLY_DESIRED_BSSID	1
+#define ALLOW_MODE_NO_BSSID		2
+
+/** used for association with a specific BSSID and chanspec list */
+typedef struct wl_assoc_params {
+	struct ether_addr bssid;	/**< 00:00:00:00:00:00: broadcast scan */
+	uint16 bssid_cnt;		/**< 0: use chanspec_num, and the single bssid,
+					* otherwise count of chanspecs in chanspec_list
+					* AND paired bssids following chanspec_list
+					* also, chanspec_num has to be set to zero
+					* for bssid list to be used
+					*/
+	int32 chanspec_num;		/**< 0: all available channels,
+					* otherwise count of chanspecs in chanspec_list
+					*/
+	chanspec_t chanspec_list[1];	/**< list of chanspecs */
+} wl_assoc_params_t;
+
+#define WL_ASSOC_PARAMS_FIXED_SIZE 	OFFSETOF(wl_assoc_params_t, chanspec_list)
+
+/** used for reassociation/roam to a specific BSSID and channel */
+typedef wl_assoc_params_t wl_reassoc_params_t;
+#define WL_REASSOC_PARAMS_FIXED_SIZE	WL_ASSOC_PARAMS_FIXED_SIZE
+
+/** used for association to a specific BSSID and channel */
+typedef wl_assoc_params_t wl_join_assoc_params_t;
+#define WL_JOIN_ASSOC_PARAMS_FIXED_SIZE	WL_ASSOC_PARAMS_FIXED_SIZE
+
+/** used for join with or without a specific bssid and channel list */
+typedef struct wl_join_params {
+	wlc_ssid_t ssid;
+	wl_assoc_params_t params;	/**< optional field, but it must include the fixed portion
+					 * of the wl_assoc_params_t struct when it does present.
+					 */
+} wl_join_params_t;
+
+#define WL_JOIN_PARAMS_FIXED_SIZE 	(OFFSETOF(wl_join_params_t, params) + \
+					 WL_ASSOC_PARAMS_FIXED_SIZE)
+/** scan params for extended join */
+typedef struct wl_join_scan_params {
+	uint8 scan_type;		/**< 0 use default, active or passive scan */
+	int32 nprobes;			/**< -1 use default, number of probes per channel */
+	int32 active_time;		/**< -1 use default, dwell time per channel for
+					 * active scanning
+					 */
+	int32 passive_time;		/**< -1 use default, dwell time per channel
+					 * for passive scanning
+					 */
+	int32 home_time;		/**< -1 use default, dwell time for the home channel
+					 * between channel scans
+					 */
+} wl_join_scan_params_t;
+
+/** extended join params */
+typedef struct wl_extjoin_params {
+	wlc_ssid_t ssid;		/**< {0, ""}: wildcard scan */
+	wl_join_scan_params_t scan;
+	wl_join_assoc_params_t assoc;	/**< optional field, but it must include the fixed portion
+					 * of the wl_join_assoc_params_t struct when it does
+					 * present.
+					 */
+} wl_extjoin_params_t;
+#define WL_EXTJOIN_PARAMS_FIXED_SIZE 	(OFFSETOF(wl_extjoin_params_t, assoc) + \
+					 WL_JOIN_ASSOC_PARAMS_FIXED_SIZE)
+
+#define ANT_SELCFG_MAX		4	/**< max number of antenna configurations */
+#define MAX_STREAMS_SUPPORTED	4	/**< max number of streams supported */
+typedef struct {
+	uint8 ant_config[ANT_SELCFG_MAX];	/**< antenna configuration */
+	uint8 num_antcfg;			/**< number of available antenna configurations */
+} wlc_antselcfg_t;
+
+typedef struct {
+	uint32 duration;	/**< millisecs spent sampling this channel */
+	uint32 congest_ibss;	/**< millisecs in our bss (presumably this traffic will */
+				/**<  move if cur bss moves channels) */
+	uint32 congest_obss;	/**< traffic not in our bss */
+	uint32 interference;	/**< millisecs detecting a non 802.11 interferer. */
+	uint32 timestamp;	/**< second timestamp */
+} cca_congest_t;
+
+typedef struct {
+	chanspec_t chanspec;	/**< Which channel? */
+	uint16 num_secs;	/**< How many secs worth of data */
+	cca_congest_t  secs[1];	/**< Data */
+} cca_congest_channel_req_t;
+#ifndef  LINUX_POSTMOGRIFY_REMOVAL
+typedef struct {
+	uint32 duration;	/**< millisecs spent sampling this channel */
+	uint32 congest;		/**< millisecs detecting busy CCA */
+	uint32 timestamp;	/**< second timestamp */
+} cca_congest_simple_t;
+
+typedef struct {
+	uint16 status;
+	uint16 id;
+	chanspec_t chanspec;			/**< Which channel? */
+	uint16 len;
+	union {
+		cca_congest_simple_t  cca_busy;	/**< CCA busy */
+		int32 noise;			/**< noise floor */
+	};
+} cca_chan_qual_event_t;
+
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+typedef struct {
+	uint32 msrmnt_time;	/**< Time for Measurement (msec) */
+	uint32 msrmnt_done;	/**< flag set when measurement complete */
+	char buf[1];
+} cca_stats_n_flags;
+
+typedef struct {
+	uint32 msrmnt_query;    /* host to driver query for measurement done */
+	uint32 time_req;        /* time required for measurement */
+	uint8 report_opt;       /* option to print different stats in report */
+} cca_msrmnt_query;
+#endif
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* interference sources */
+enum interference_source {
+	ITFR_NONE = 0,			/**< interference */
+	ITFR_PHONE,			/**< wireless phone */
+	ITFR_VIDEO_CAMERA,		/**< wireless video camera */
+	ITFR_MICROWAVE_OVEN,		/**< microwave oven */
+	ITFR_BABY_MONITOR,		/**< wireless baby monitor */
+	ITFR_BLUETOOTH,			/**< bluetooth */
+	ITFR_VIDEO_CAMERA_OR_BABY_MONITOR,	/**< wireless camera or baby monitor */
+	ITFR_BLUETOOTH_OR_BABY_MONITOR,	/**< bluetooth or baby monitor */
+	ITFR_VIDEO_CAMERA_OR_PHONE,	/**< video camera or phone */
+	ITFR_UNIDENTIFIED		/**< interference from unidentified source */
+};
+
+/** structure for interference source report */
+typedef struct {
+	uint32 flags;		/**< flags.  bit definitions below */
+	uint32 source;		/**< last detected interference source */
+	uint32 timestamp;	/**< second timestamp on interferenced flag change */
+} interference_source_rep_t;
+
+#define WLC_CNTRY_BUF_SZ	4		/**< Country string is 3 bytes + NUL */
+
+typedef struct wl_country {
+	char country_abbrev[WLC_CNTRY_BUF_SZ];	/**< nul-terminated country code used in
+						 * the Country IE
+						 */
+	int32 rev;				/**< revision specifier for ccode
+						 * on set, -1 indicates unspecified.
+						 * on get, rev >= 0
+						 */
+	char ccode[WLC_CNTRY_BUF_SZ];		/**< nul-terminated built-in country code.
+						 * variable length, but fixed size in
+						 * struct allows simple allocation for
+						 * expected country strings <= 3 chars.
+						 */
+} wl_country_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+#define CCODE_INFO_VERSION 1
+
+typedef enum wl_ccode_role {
+	WLC_CCODE_ROLE_ACTIVE = 0,
+	WLC_CCODE_ROLE_HOST,
+	WLC_CCODE_ROLE_80211D_ASSOC,
+	WLC_CCODE_ROLE_80211D_SCAN,
+	WLC_CCODE_ROLE_DEFAULT,
+	WLC_CCODE_LAST
+} wl_ccode_role_t;
+#define WLC_NUM_CCODE_INFO WLC_CCODE_LAST
+
+typedef struct wl_ccode_entry {
+	uint16 reserved;
+	uint8 band;
+	uint8 role;
+	char	ccode[WLC_CNTRY_BUF_SZ];
+} wl_ccode_entry_t;
+
+typedef struct wl_ccode_info {
+	uint16 version;
+	uint16 count;   /**< Number of ccodes entries in the set */
+	wl_ccode_entry_t ccodelist[1];
+} wl_ccode_info_t;
+#define WL_CCODE_INFO_FIXED_LEN	OFFSETOF(wl_ccode_info_t, ccodelist)
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+typedef struct wl_channels_in_country {
+	uint32 buflen;
+	uint32 band;
+	char country_abbrev[WLC_CNTRY_BUF_SZ];
+	uint32 count;
+	uint32 channel[1];
+} wl_channels_in_country_t;
+
+typedef struct wl_country_list {
+	uint32 buflen;
+	uint32 band_set;
+	uint32 band;
+	uint32 count;
+	char country_abbrev[1];
+} wl_country_list_t;
+
+typedef struct wl_rm_req_elt {
+	int8	type;
+	int8	flags;
+	chanspec_t	chanspec;
+	uint32	token;		/**< token for this measurement */
+	uint32	tsf_h;		/**< TSF high 32-bits of Measurement start time */
+	uint32	tsf_l;		/**< TSF low 32-bits */
+	uint32	dur;		/**< TUs */
+} wl_rm_req_elt_t;
+
+typedef struct wl_rm_req {
+	uint32	token;		/**< overall measurement set token */
+	uint32	count;		/**< number of measurement requests */
+	void	*cb;		/**< completion callback function: may be NULL */
+	void	*cb_arg;	/**< arg to completion callback function */
+	wl_rm_req_elt_t	req[1];	/**< variable length block of requests */
+} wl_rm_req_t;
+#define WL_RM_REQ_FIXED_LEN	OFFSETOF(wl_rm_req_t, req)
+
+typedef struct wl_rm_rep_elt {
+	int8	type;
+	int8	flags;
+	chanspec_t	chanspec;
+	uint32	token;		/**< token for this measurement */
+	uint32	tsf_h;		/**< TSF high 32-bits of Measurement start time */
+	uint32	tsf_l;		/**< TSF low 32-bits */
+	uint32	dur;		/**< TUs */
+	uint32	len;		/**< byte length of data block */
+	uint8	data[1];	/**< variable length data block */
+} wl_rm_rep_elt_t;
+#define WL_RM_REP_ELT_FIXED_LEN	24	/**< length excluding data block */
+
+#define WL_RPI_REP_BIN_NUM 8
+typedef struct wl_rm_rpi_rep {
+	uint8	rpi[WL_RPI_REP_BIN_NUM];
+	int8	rpi_max[WL_RPI_REP_BIN_NUM];
+} wl_rm_rpi_rep_t;
+
+typedef struct wl_rm_rep {
+	uint32	token;		/**< overall measurement set token */
+	uint32	len;		/**< length of measurement report block */
+	wl_rm_rep_elt_t	rep[1];	/**< variable length block of reports */
+} wl_rm_rep_t;
+#define WL_RM_REP_FIXED_LEN	8
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#if defined(BCMSUP_PSK) || defined(BCMDONGLEHOST) || defined(GTKOE)
+typedef enum sup_auth_status {
+	/* Basic supplicant authentication states */
+	WLC_SUP_DISCONNECTED = 0,
+	WLC_SUP_CONNECTING,
+	WLC_SUP_IDREQUIRED,
+	WLC_SUP_AUTHENTICATING,
+	WLC_SUP_AUTHENTICATED,
+	WLC_SUP_KEYXCHANGE,
+	WLC_SUP_KEYED,
+	WLC_SUP_TIMEOUT,
+	WLC_SUP_LAST_BASIC_STATE,
+
+	/* Extended supplicant authentication states */
+	/** Waiting to receive handshake msg M1 */
+	WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED,
+	/** Preparing to send handshake msg M2 */
+	WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE,
+	/* Waiting to receive handshake msg M3 */
+	WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE,
+	WLC_SUP_KEYXCHANGE_PREP_M4,	/**< Preparing to send handshake msg M4 */
+	WLC_SUP_KEYXCHANGE_WAIT_G1,	/**< Waiting to receive handshake msg G1 */
+	WLC_SUP_KEYXCHANGE_PREP_G2	/**< Preparing to send handshake msg G2 */
+} sup_auth_status_t;
+#endif 
+
+typedef struct wl_wsec_key {
+	uint32		index;		/**< key index */
+	uint32		len;		/**< key length */
+	uint8		data[DOT11_MAX_KEY_SIZE];	/**< key data */
+	uint32		pad_1[18];
+	uint32		algo;		/**< CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+	uint32		flags;		/**< misc flags */
+	uint32		pad_2[2];
+	int32		pad_3;
+	int32		iv_initialized;	/**< has IV been initialized already? */
+	int32		pad_4;
+	/* Rx IV */
+	struct {
+		uint32	hi;		/**< upper 32 bits of IV */
+		uint16	lo;		/**< lower 16 bits of IV */
+	} rxiv;
+	uint32		pad_5[2];
+	struct ether_addr ea;		/**< per station */
+} wl_wsec_key_t;
+
+#define WSEC_MIN_PSK_LEN	8
+#define WSEC_MAX_PSK_LEN	64
+
+/** Flag for key material needing passhash'ing */
+#define WSEC_PASSPHRASE		(1<<0)
+
+/**receptacle for WLC_SET_WSEC_PMK parameter */
+typedef struct wsec_pmk {
+	ushort	key_len;		/**< octets in key material */
+	ushort	flags;			/**< key handling qualification */
+	uint8	key[WSEC_MAX_PSK_LEN];	/**< PMK material */
+} wsec_pmk_t;
+
+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;
+
+#define WL_STA_ANT_MAX		4	/**< max possible rx antennas */
+
+typedef struct wl_assoc_info {
+	uint32		req_len;
+	uint32		resp_len;
+	uint32		flags;
+	struct dot11_assoc_req req;
+	struct ether_addr reassoc_bssid; /**< used in reassoc's */
+	struct dot11_assoc_resp resp;
+} wl_assoc_info_t;
+
+typedef struct wl_led_info {
+	uint32      index;      /**< led index */
+	uint32      behavior;
+	uint8       activehi;
+} wl_led_info_t;
+
+
+/** srom read/write struct passed through ioctl */
+typedef struct {
+	uint32	byteoff;	/**< byte offset */
+	uint32	nbytes;		/**< number of bytes */
+	uint16	buf[1];
+} srom_rw_t;
+
+#define CISH_FLAG_PCIECIS	(1 << 15)	/**< write CIS format bit for PCIe CIS */
+
+/** similar cis (srom or otp) struct [iovar: may not be aligned] */
+typedef struct {
+	uint16	source;		/**< cis source */
+	uint16	flags;		/**< flags */
+	uint32	byteoff;	/**< byte offset */
+	uint32	nbytes;		/**< number of bytes */
+	/* data follows here */
+} cis_rw_t;
+
+/** R_REG and W_REG struct passed through ioctl */
+typedef struct {
+	uint32	byteoff;	/**< byte offset of the field in d11regs_t */
+	uint32	val;		/**< read/write value of the field */
+	uint32	size;		/**< sizeof the field */
+	uint32	band;		/**< band (optional) */
+} rw_reg_t;
+
+/**
+ * Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band
+ * PCL - Power Control Loop
+ */
+typedef struct {
+	uint16	auto_ctrl;	/**< WL_ATTEN_XX */
+	uint16	bb;		/**< Baseband attenuation */
+	uint16	radio;		/**< Radio attenuation */
+	uint16	txctl1;		/**< Radio TX_CTL1 value */
+} atten_t;
+
+/** Per-AC retry parameters */
+struct wme_tx_params_s {
+	uint8  short_retry;
+	uint8  short_fallback;
+	uint8  long_retry;
+	uint8  long_fallback;
+	uint16 max_rate;  /**< In units of 512 Kbps */
+};
+
+typedef struct wme_tx_params_s wme_tx_params_t;
+
+#define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT)
+
+/**Used to get specific link/ac parameters */
+typedef struct {
+	int32 ac;
+	uint8 val;
+	struct ether_addr ea;
+} link_val_t;
+
+
+#define WL_PM_MUTE_TX_VER 1
+
+typedef struct wl_pm_mute_tx {
+	uint16 version;		/**< version */
+	uint16 len;		/**< length */
+	uint16 deadline;	/**< deadline timer (in milliseconds) */
+	uint8  enable;		/**< set to 1 to enable mode; set to 0 to disable it */
+} wl_pm_mute_tx_t;
+
+
+/* sta_info_t version 4 */
+typedef struct {
+	uint16			ver;		/**< version of this struct */
+	uint16			len;		/**< length in bytes of this structure */
+	uint16			cap;		/**< sta's advertised capabilities */
+	uint32			flags;		/**< flags defined below */
+	uint32			idle;		/**< time since data pkt rx'd from sta */
+	struct ether_addr	ea;		/**< Station address */
+	wl_rateset_t		rateset;	/**< rateset in use */
+	uint32			in;		/**< seconds elapsed since associated */
+	uint32			listen_interval_inms; /**< Min Listen interval in ms for this STA */
+	uint32			tx_pkts;	/**< # of user packets transmitted (unicast) */
+	uint32			tx_failures;	/**< # of user packets failed */
+	uint32			rx_ucast_pkts;	/**< # of unicast packets received */
+	uint32			rx_mcast_pkts;	/**< # of multicast packets received */
+	uint32			tx_rate;	/**< Rate used by last tx frame */
+	uint32			rx_rate;	/**< Rate of last successful rx frame */
+	uint32			rx_decrypt_succeeds;	/**< # of packet decrypted successfully */
+	uint32			rx_decrypt_failures;	/**< # of packet decrypted unsuccessfully */
+	uint32			tx_tot_pkts;	/**< # of user tx pkts (ucast + mcast) */
+	uint32			rx_tot_pkts;	/**< # of data packets recvd (uni + mcast) */
+	uint32			tx_mcast_pkts;	/**< # of mcast pkts txed */
+	uint64			tx_tot_bytes;	/**< data bytes txed (ucast + mcast) */
+	uint64			rx_tot_bytes;	/**< data bytes recvd (ucast + mcast) */
+	uint64			tx_ucast_bytes;	/**< data bytes txed (ucast) */
+	uint64			tx_mcast_bytes;	/**< # data bytes txed (mcast) */
+	uint64			rx_ucast_bytes;	/**< data bytes recvd (ucast) */
+	uint64			rx_mcast_bytes;	/**< data bytes recvd (mcast) */
+	int8			rssi[WL_STA_ANT_MAX]; /**< average rssi per antenna
+							* of data frames
+							*/
+	int8			nf[WL_STA_ANT_MAX];	/**< per antenna noise floor */
+	uint16			aid;			/**< association ID */
+	uint16			ht_capabilities;	/**< advertised ht caps */
+	uint16			vht_flags;		/**< converted vht flags */
+	uint32			tx_pkts_retried;	/**< # of frames where a retry was
+							 * necessary
+							 */
+	uint32			tx_pkts_retry_exhausted; /**< # of user frames where a retry
+							  * was exhausted
+							  */
+	int8			rx_lastpkt_rssi[WL_STA_ANT_MAX]; /**< Per antenna RSSI of last
+								  * received data frame.
+								  */
+	/* TX WLAN retry/failure statistics:
+	 * Separated for host requested frames and WLAN locally generated frames.
+	 * Include unicast frame only where the retries/failures can be counted.
+	 */
+	uint32			tx_pkts_total;		/**< # user frames sent successfully */
+	uint32			tx_pkts_retries;	/**< # user frames retries */
+	uint32			tx_pkts_fw_total;	/**< # FW generated sent successfully */
+	uint32			tx_pkts_fw_retries;	/**< # retries for FW generated frames */
+	uint32			tx_pkts_fw_retry_exhausted;	/**< # FW generated where a retry
+								 * was exhausted
+								 */
+	uint32			rx_pkts_retried;	/**< # rx with retry bit set */
+	uint32			tx_rate_fallback;	/**< lowest fallback TX rate */
+	/* Fields above this line are common to sta_info_t versions 4 and 5 */
+
+	uint32			rx_dur_total;	/* total user RX duration (estimated) */
+
+	chanspec_t		chanspec;       /** chanspec this sta is on */
+	wl_rateset_args_t	rateset_adv;	/* rateset along with mcs index bitmap */
+} sta_info_v4_t;
+
+/* Note: Version 4 is the latest version of sta_info_t.  Version 5 is abandoned.
+ * Please add new fields to version 4, not version 5.
+ */
+/* sta_info_t version 5 */
+typedef struct {
+	uint16			ver;		/**< version of this struct */
+	uint16			len;		/**< length in bytes of this structure */
+	uint16			cap;		/**< sta's advertised capabilities */
+	uint32			flags;		/**< flags defined below */
+	uint32			idle;		/**< time since data pkt rx'd from sta */
+	struct ether_addr	ea;		/**< Station address */
+	wl_rateset_t		rateset;	/**< rateset in use */
+	uint32			in;		/**< seconds elapsed since associated */
+	uint32			listen_interval_inms; /**< Min Listen interval in ms for this STA */
+	uint32			tx_pkts;	/**< # of user packets transmitted (unicast) */
+	uint32			tx_failures;	/**< # of user packets failed */
+	uint32			rx_ucast_pkts;	/**< # of unicast packets received */
+	uint32			rx_mcast_pkts;	/**< # of multicast packets received */
+	uint32			tx_rate;	/**< Rate used by last tx frame */
+	uint32			rx_rate;	/**< Rate of last successful rx frame */
+	uint32			rx_decrypt_succeeds;	/**< # of packet decrypted successfully */
+	uint32			rx_decrypt_failures;	/**< # of packet decrypted unsuccessfully */
+	uint32			tx_tot_pkts;	/**< # of user tx pkts (ucast + mcast) */
+	uint32			rx_tot_pkts;	/**< # of data packets recvd (uni + mcast) */
+	uint32			tx_mcast_pkts;	/**< # of mcast pkts txed */
+	uint64			tx_tot_bytes;	/**< data bytes txed (ucast + mcast) */
+	uint64			rx_tot_bytes;	/**< data bytes recvd (ucast + mcast) */
+	uint64			tx_ucast_bytes;	/**< data bytes txed (ucast) */
+	uint64			tx_mcast_bytes;	/**< # data bytes txed (mcast) */
+	uint64			rx_ucast_bytes;	/**< data bytes recvd (ucast) */
+	uint64			rx_mcast_bytes;	/**< data bytes recvd (mcast) */
+	int8			rssi[WL_STA_ANT_MAX]; /**< average rssi per antenna
+							* of data frames
+							*/
+	int8			nf[WL_STA_ANT_MAX];	/**< per antenna noise floor */
+	uint16			aid;			/**< association ID */
+	uint16			ht_capabilities;	/**< advertised ht caps */
+	uint16			vht_flags;		/**< converted vht flags */
+	uint32			tx_pkts_retried;	/**< # of frames where a retry was
+							 * necessary
+							 */
+	uint32			tx_pkts_retry_exhausted; /**< # of user frames where a retry
+							  * was exhausted
+							  */
+	int8			rx_lastpkt_rssi[WL_STA_ANT_MAX]; /**< Per antenna RSSI of last
+								  * received data frame.
+								  */
+	/* TX WLAN retry/failure statistics:
+	 * Separated for host requested frames and WLAN locally generated frames.
+	 * Include unicast frame only where the retries/failures can be counted.
+	 */
+	uint32			tx_pkts_total;		/**< # user frames sent successfully */
+	uint32			tx_pkts_retries;	/**< # user frames retries */
+	uint32			tx_pkts_fw_total;	/**< # FW generated sent successfully */
+	uint32			tx_pkts_fw_retries;	/**< # retries for FW generated frames */
+	uint32			tx_pkts_fw_retry_exhausted;	/**< # FW generated where a retry
+								 * was exhausted
+								 */
+	uint32			rx_pkts_retried;	/**< # rx with retry bit set */
+	uint32			tx_rate_fallback;	/**< lowest fallback TX rate */
+	/* Fields above this line are common to sta_info_t versions 4 and 5 */
+
+	chanspec_t		chanspec;       /** chanspec this sta is on */
+	wl_rateset_args_t	rateset_adv;	/* rateset along with mcs index bitmap */
+} sta_info_v5_t;
+
+#define WL_OLD_STAINFO_SIZE	OFFSETOF(sta_info_t, tx_tot_pkts)
+
+#define WL_STA_VER_4		4
+#define WL_STA_VER_5		5
+#define WL_STA_VER		WL_STA_VER_4
+
+#define SWDIV_STATS_VERSION_2 2
+#define SWDIV_STATS_CURRENT_VERSION SWDIV_STATS_VERSION_2
+
+struct wlc_swdiv_stats_v1 {
+	uint32 auto_en;
+	uint32 active_ant;
+	uint32 rxcount;
+	int32 avg_snr_per_ant0;
+	int32 avg_snr_per_ant1;
+	int32 avg_snr_per_ant2;
+	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;
+	uint32 tx_auto_en;
+	uint32 tx_active_ant;
+	uint32 rx_policy;
+	uint32 tx_policy;
+	uint32 cell_policy;
+	uint32 swap_snrdrop0;
+	uint32 swap_snrdrop1;
+	uint32 mws_antsel_ovr_tx;
+	uint32 mws_antsel_ovr_rx;
+	uint8 swap_trig_event_id;
+};
+
+struct wlc_swdiv_stats_v2 {
+	uint16	version;	/* version of the structure
+						* as defined by SWDIV_STATS_CURRENT_VERSION
+						*/
+	uint16	length;		/* length of the entire structure */
+	uint32 auto_en;
+	uint32 active_ant;
+	uint32 rxcount;
+	int32 avg_snr_per_ant0;
+	int32 avg_snr_per_ant1;
+	int32 avg_snr_per_ant2;
+	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;
+	uint32 tx_auto_en;
+	uint32 tx_active_ant;
+	uint32 rx_policy;
+	uint32 tx_policy;
+	uint32 cell_policy;
+	uint32 swap_snrdrop0;
+	uint32 swap_snrdrop1;
+	uint32 mws_antsel_ovr_tx;
+	uint32 mws_antsel_ovr_rx;
+	uint32 swap_trig_event_id;
+};
+
+#define	WLC_NUMRATES	16	/**< max # of rates in a rateset */
+
+typedef struct wlc_rateset {
+	uint32	count;			/**< number of rates in rates[] */
+	uint8	rates[WLC_NUMRATES];	/**< rates in 500kbps units w/hi bit set if basic */
+	uint8	htphy_membership;	/**< HT PHY Membership */
+	uint8	mcs[MCSSET_LEN];	/**< supported mcs index bit map */
+	uint16  vht_mcsmap;		/**< supported vht mcs nss bit map */
+	uint16  vht_mcsmap_prop;	/**< supported prop vht mcs nss bit map */
+} wlc_rateset_t;
+
+/**Used to get specific STA parameters */
+typedef struct {
+	uint32	val;
+	struct ether_addr ea;
+} scb_val_t;
+
+/**Used by iovar versions of some ioctls, i.e. WLC_SCB_AUTHORIZE et al */
+typedef struct {
+	uint32 code;
+	scb_val_t ioctl_args;
+} authops_t;
+
+/** channel encoding */
+typedef struct channel_info {
+	int32 hw_channel;
+	int32 target_channel;
+	int32 scan_channel;
+} channel_info_t;
+
+/** For ioctls that take a list of MAC addresses */
+typedef struct maclist {
+	uint32 count;			/**< number of MAC addresses */
+	struct ether_addr ea[1];	/**< variable length array of MAC addresses */
+} maclist_t;
+
+/**get pkt count struct passed through ioctl */
+typedef struct get_pktcnt {
+	uint32 rx_good_pkt;
+	uint32 rx_bad_pkt;
+	uint32 tx_good_pkt;
+	uint32 tx_bad_pkt;
+	uint32 rx_ocast_good_pkt; /**< unicast packets destined for others */
+} get_pktcnt_t;
+
+/* NINTENDO2 */
+#define LQ_IDX_MIN              0
+#define LQ_IDX_MAX              1
+#define LQ_IDX_AVG              2
+#define LQ_IDX_SUM              2
+#define LQ_IDX_LAST             3
+#define LQ_STOP_MONITOR         0
+#define LQ_START_MONITOR        1
+
+/** Get averages RSSI, Rx PHY rate and SNR values */
+typedef struct {
+	int32 rssi[LQ_IDX_LAST];  /**< Array to keep min, max, avg rssi */
+	int32 snr[LQ_IDX_LAST];   /**< Array to keep min, max, avg snr */
+	int32 isvalid;            /**< Flag indicating whether above data is valid */
+} wl_lq_t; /* Link Quality */
+
+typedef enum wl_wakeup_reason_type {
+	LCD_ON = 1,
+	LCD_OFF,
+	DRC1_WAKE,
+	DRC2_WAKE,
+	REASON_LAST
+} wl_wr_type_t;
+
+typedef struct {
+	/** Unique filter id */
+	uint32	id;
+	/** stores the reason for the last wake up */
+	uint8	reason;
+} wl_wr_t;
+
+/** Get MAC specific rate histogram command */
+typedef struct {
+	struct	ether_addr ea;	/**< MAC Address */
+	uint8	ac_cat;	/**< Access Category */
+	uint8	num_pkts;	/**< Number of packet entries to be averaged */
+} wl_mac_ratehisto_cmd_t;	/**< MAC Specific Rate Histogram command */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/** Get MAC rate histogram response */
+typedef struct {
+	uint32	rate[DOT11_RATE_MAX + 1];	/**< Rates */
+	uint32	mcs[WL_RATESET_SZ_HT_IOCTL * WL_TX_CHAINS_MAX];	/**< MCS counts */
+	uint32	vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX];	/**< VHT counts */
+	uint32	tsf_timer[2][2];	/**< Start and End time for 8bytes value */
+	uint32	prop11n_mcs[WLC_11N_LAST_PROP_MCS - WLC_11N_FIRST_PROP_MCS + 1]; /** MCS counts */
+} wl_mac_ratehisto_res_t;	/**< MAC Specific Rate Histogram Response */
+
+/* sta_info ecounters */
+typedef struct {
+	struct ether_addr   ea;				/* Station MAC addr */
+	struct ether_addr   BSSID;			/* BSSID of the BSS */
+	uint32              tx_pkts_fw_total;		/* # FW generated sent successfully */
+	uint32              tx_pkts_fw_retries;		/* # retries for FW generated frames */
+	uint32              tx_pkts_fw_retry_exhausted;	/* # FW generated which
+							 * failed after retry
+							 */
+} sta_info_ecounters_t;
+
+#define STAMON_MODULE_VER		1
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/**Linux network driver ioctl encoding */
+typedef struct wl_ioctl {
+	uint32 cmd;	/**< common ioctl definition */
+	void *buf;	/**< pointer to user buffer */
+	uint32 len;	/**< length of user buffer */
+	uint8 set;		/**< 1=set IOCTL; 0=query IOCTL */
+	uint32 used;	/**< bytes read or written (optional) */
+	uint32 needed;	/**< bytes needed (optional) */
+} wl_ioctl_t;
+
+#ifdef CONFIG_COMPAT
+typedef struct compat_wl_ioctl {
+	uint32 cmd;	/**< common ioctl definition */
+	uint32 buf;	/**< pointer to user buffer */
+	uint32 len;	/**< length of user buffer */
+	uint8 set;		/**< 1=set IOCTL; 0=query IOCTL */
+	uint32 used;	/**< bytes read or written (optional) */
+	uint32 needed;	/**< bytes needed (optional) */
+} compat_wl_ioctl_t;
+#endif /* CONFIG_COMPAT */
+
+#define WL_NUM_RATES_CCK		4 /**< 1, 2, 5.5, 11 Mbps */
+#define WL_NUM_RATES_OFDM		8 /**< 6, 9, 12, 18, 24, 36, 48, 54 Mbps SISO/CDD */
+#define WL_NUM_RATES_MCS_1STREAM	8 /**< MCS 0-7 1-stream rates - SISO/CDD/STBC/MCS */
+#define WL_NUM_RATES_EXTRA_VHT		2 /**< Additional VHT 11AC rates */
+#define WL_NUM_RATES_VHT		10
+#define WL_NUM_RATES_MCS32		1
+
+
+/*
+ * Structure for passing hardware and software
+ * revision info up from the driver.
+ */
+typedef struct wlc_rev_info {
+	uint32		vendorid;	/**< PCI vendor id */
+	uint32		deviceid;	/**< device id of chip */
+	uint32		radiorev;	/**< radio revision */
+	uint32		chiprev;	/**< chip revision */
+	uint32		corerev;	/**< core revision */
+	uint32		boardid;	/**< board identifier (usu. PCI sub-device id) */
+	uint32		boardvendor;	/**< board vendor (usu. PCI sub-vendor id) */
+	uint32		boardrev;	/**< board revision */
+	uint32		driverrev;	/**< driver version */
+	uint32		ucoderev;	/**< microcode version */
+	uint32		bus;		/**< bus type */
+	uint32		chipnum;	/**< chip number */
+	uint32		phytype;	/**< phy type */
+	uint32		phyrev;		/**< phy revision */
+	uint32		anarev;		/**< anacore rev */
+	uint32		chippkg;	/**< chip package info */
+	uint32		nvramrev;	/**< nvram revision number */
+	uint32		phyminorrev;	/**< phy minor rev */
+	uint32		coreminorrev;	/**< core minor rev */
+	uint32		drvrev_major;	/**< driver version: major */
+	uint32		drvrev_minor;	/**< driver version: minor */
+	uint32		drvrev_rc;	/**< driver version: rc */
+	uint32		drvrev_rc_inc;	/**< driver version: rc incremental */
+} wlc_rev_info_t;
+
+#define WL_REV_INFO_LEGACY_LENGTH	48
+
+#define WL_BRAND_MAX 10
+typedef struct wl_instance_info {
+	uint32 instance;
+	int8 brand[WL_BRAND_MAX];
+} wl_instance_info_t;
+
+/** structure to change size of tx fifo */
+typedef struct wl_txfifo_sz {
+	uint16	magic;
+	uint16	fifo;
+	uint16	size;
+} wl_txfifo_sz_t;
+
+/* Transfer info about an IOVar from the driver */
+/**Max supported IOV name size in bytes, + 1 for nul termination */
+#define WLC_IOV_NAME_LEN	(32 + 1)
+
+typedef struct wlc_iov_trx_s {
+	uint8 module;
+	uint8 type;
+	char name[WLC_IOV_NAME_LEN];
+} wlc_iov_trx_t;
+
+/** bump this number if you change the ioctl interface */
+#define WLC_IOCTL_VERSION	2
+#define WLC_IOCTL_VERSION_LEGACY_IOTYPES	1
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#ifdef CONFIG_USBRNDIS_RETAIL
+/** struct passed in for WLC_NDCONFIG_ITEM */
+typedef struct {
+	char *name;
+	void *param;
+} ndconfig_item_t;
+#endif
+
+/* ifdef EXT_STA */
+typedef struct _wl_assoc_result {
+	ulong associated;
+	ulong NDIS_auth;
+	ulong NDIS_infra;
+} wl_assoc_result_t;
+/* EXT_STA */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#define WL_PHY_PAVARS_LEN	32	/**< Phytype, Bandrange, chain, a[0], b[0], c[0], d[0] .. */
+
+
+#define WL_PHY_PAVAR_VER	1	/**< pavars version */
+#define WL_PHY_PAVARS2_NUM	3	/**< a1, b0, b1 */
+typedef struct wl_pavars2 {
+	uint16 ver;		/**< version of this struct */
+	uint16 len;		/**< len of this structure */
+	uint16 inuse;		/**< driver return 1 for a1,b0,b1 in current band range */
+	uint16 phy_type;	/**< phy type */
+	uint16 bandrange;
+	uint16 chain;
+	uint16 inpa[WL_PHY_PAVARS2_NUM];	/**< phy pavars for one band range */
+} wl_pavars2_t;
+
+typedef struct wl_po {
+	uint16	phy_type;	/**< Phy type */
+	uint16	band;
+	uint16	cckpo;
+	uint32	ofdmpo;
+	uint16	mcspo[8];
+} wl_po_t;
+
+#define WL_NUM_RPCALVARS 5	/**< number of rpcal vars */
+
+typedef struct wl_rpcal {
+	uint16 value;
+	uint16 update;
+} wl_rpcal_t;
+
+#define WL_NUM_RPCALPHASEVARS 5	/* number of rpcal phase vars */
+
+typedef struct wl_rpcal_phase {
+	uint16 value;
+	uint16 update;
+} wl_rpcal_phase_t;
+
+typedef struct wl_aci_args {
+	int32 enter_aci_thresh; /* Trigger level to start detecting ACI */
+	int32 exit_aci_thresh; /* Trigger level to exit ACI mode */
+	int32 usec_spin; /* microsecs to delay between rssi samples */
+	int32 glitch_delay; /* interval between ACI scans when glitch count is consistently high */
+	uint16 nphy_adcpwr_enter_thresh;	/**< ADC power to enter ACI mitigation mode */
+	uint16 nphy_adcpwr_exit_thresh;	/**< ADC power to exit ACI mitigation mode */
+	uint16 nphy_repeat_ctr;		/**< Number of tries per channel to compute power */
+	uint16 nphy_num_samples;	/**< Number of samples to compute power on one channel */
+	uint16 nphy_undetect_window_sz;	/**< num of undetects to exit ACI Mitigation mode */
+	uint16 nphy_b_energy_lo_aci;	/**< low ACI power energy threshold for bphy */
+	uint16 nphy_b_energy_md_aci;	/**< mid ACI power energy threshold for bphy */
+	uint16 nphy_b_energy_hi_aci;	/**< high ACI power energy threshold for bphy */
+	uint16 nphy_noise_noassoc_glitch_th_up; /**< wl interference 4 */
+	uint16 nphy_noise_noassoc_glitch_th_dn;
+	uint16 nphy_noise_assoc_glitch_th_up;
+	uint16 nphy_noise_assoc_glitch_th_dn;
+	uint16 nphy_noise_assoc_aci_glitch_th_up;
+	uint16 nphy_noise_assoc_aci_glitch_th_dn;
+	uint16 nphy_noise_assoc_enter_th;
+	uint16 nphy_noise_noassoc_enter_th;
+	uint16 nphy_noise_assoc_rx_glitch_badplcp_enter_th;
+	uint16 nphy_noise_noassoc_crsidx_incr;
+	uint16 nphy_noise_assoc_crsidx_incr;
+	uint16 nphy_noise_crsidx_decr;
+} wl_aci_args_t;
+
+#define WL_ACI_ARGS_LEGACY_LENGTH	16	/**< bytes of pre NPHY aci args */
+#define	WL_SAMPLECOLLECT_T_VERSION	2	/**< version of wl_samplecollect_args_t struct */
+typedef struct wl_samplecollect_args {
+	/* version 0 fields */
+	uint8 coll_us;
+	int32 cores;
+	/* add'l version 1 fields */
+	uint16 version;     /**< see definition of WL_SAMPLECOLLECT_T_VERSION */
+	uint16 length;      /**< length of entire structure */
+	int8 trigger;
+	uint16 timeout;
+	uint16 mode;
+	uint32 pre_dur;
+	uint32 post_dur;
+	uint8 gpio_sel;
+	uint8 downsamp;
+	uint8 be_deaf;
+	uint8 agc;		/**< loop from init gain and going down */
+	uint8 filter;		/**< override high pass corners to lowest */
+	/* add'l version 2 fields */
+	uint8 trigger_state;
+	uint8 module_sel1;
+	uint8 module_sel2;
+	uint16 nsamps;
+	int32 bitStart;
+	uint32 gpioCapMask;
+	uint8 gpio_collection;
+} wl_samplecollect_args_t;
+
+#define	WL_SAMPLEDATA_T_VERSION		1	/**< version of wl_samplecollect_args_t struct */
+/* version for unpacked sample data, int16 {(I,Q),Core(0..N)} */
+#define	WL_SAMPLEDATA_T_VERSION_SPEC_AN 2
+
+typedef struct wl_sampledata {
+	uint16 version;	/**< structure version */
+	uint16 size;	/**< size of structure */
+	uint16 tag;	/**< Header/Data */
+	uint16 length;	/**< data length */
+	uint32 flag;	/**< bit def */
+} wl_sampledata_t;
+
+
+/* WL_OTA START */
+/* OTA Test Status */
+enum {
+	WL_OTA_TEST_IDLE = 0,		/**< Default Idle state */
+	WL_OTA_TEST_ACTIVE = 1,		/**< Test Running */
+	WL_OTA_TEST_SUCCESS = 2,	/**< Successfully Finished Test */
+	WL_OTA_TEST_FAIL = 3		/**< Test Failed in the Middle */
+};
+
+/* OTA SYNC Status */
+enum {
+	WL_OTA_SYNC_IDLE = 0,	/**< Idle state */
+	WL_OTA_SYNC_ACTIVE = 1,	/**< Waiting for Sync */
+	WL_OTA_SYNC_FAIL = 2	/**< Sync pkt not recieved */
+};
+
+/* Various error states dut can get stuck during test */
+enum {
+	WL_OTA_SKIP_TEST_CAL_FAIL = 1,		/**< Phy calibration failed */
+	WL_OTA_SKIP_TEST_SYNCH_FAIL = 2,	/**< Sync Packet not recieved */
+	WL_OTA_SKIP_TEST_FILE_DWNLD_FAIL = 3,	/**< Cmd flow file download failed */
+	WL_OTA_SKIP_TEST_NO_TEST_FOUND = 4,	/**< No test found in Flow file */
+	WL_OTA_SKIP_TEST_WL_NOT_UP = 5,		/**< WL UP failed */
+	WL_OTA_SKIP_TEST_UNKNOWN_CALL		/**< Unintentional scheduling on ota test */
+};
+
+/* Differentiator for ota_tx and ota_rx */
+enum {
+	WL_OTA_TEST_TX = 0,		/**< ota_tx */
+	WL_OTA_TEST_RX = 1,		/**< ota_rx */
+};
+
+/* Catch 3 modes of operation: 20Mhz, 40Mhz, 20 in 40 Mhz */
+enum {
+	WL_OTA_TEST_BW_20_IN_40MHZ = 0,		/**< 20 in 40 operation */
+	WL_OTA_TEST_BW_20MHZ = 1,		/**< 20 Mhz operation */
+	WL_OTA_TEST_BW_40MHZ = 2,		/**< full 40Mhz operation */
+	WL_OTA_TEST_BW_80MHZ = 3		/* full 80Mhz operation */
+};
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define HT_MCS_INUSE	0x00000080	/* HT MCS in use,indicates b0-6 holds an mcs */
+#define VHT_MCS_INUSE	0x00000100	/* VHT MCS in use,indicates b0-6 holds an mcs */
+#define OTA_RATE_MASK 0x0000007f	/* rate/mcs value */
+#define OTA_STF_SISO	0
+#define OTA_STF_CDD		1
+#define OTA_STF_STBC	2
+#define OTA_STF_SDM		3
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+typedef struct ota_rate_info {
+	uint8 rate_cnt;					/**< Total number of rates */
+	uint16 rate_val_mbps[WL_OTA_TEST_MAX_NUM_RATE];	/**< array of rates from 1mbps to 130mbps */
+							/**< for legacy rates : ratein mbps * 2 */
+							/**< for HT rates : mcs index */
+} ota_rate_info_t;
+
+typedef struct ota_power_info {
+	int8 pwr_ctrl_on;	/**< power control on/off */
+	int8 start_pwr;		/**< starting power/index */
+	int8 delta_pwr;		/**< delta power/index */
+	int8 end_pwr;		/**< end power/index */
+} ota_power_info_t;
+
+typedef struct ota_packetengine {
+	uint16 delay;           /**< Inter-packet delay */
+				/**< for ota_tx, delay is tx ifs in micro seconds */
+				/* for ota_rx, delay is wait time in milliseconds */
+	uint16 nframes;         /**< Number of frames */
+	uint16 length;          /**< Packet length */
+} ota_packetengine_t;
+
+/*
+ * OTA txant/rxant parameter
+ *    bit7-4: 4 bits swdiv_tx/rx_policy bitmask, specify antenna-policy for SW diversity
+ *    bit3-0: 4 bits TxCore bitmask, specify cores used for transmit frames
+ *            (maximum spatial expansion)
+ */
+#define WL_OTA_TEST_ANT_MASK	0xF0
+#define WL_OTA_TEST_CORE_MASK	0x0F
+
+/* OTA txant/rxant 'ant_mask' field; map to Tx/Rx antenna policy for SW diversity */
+enum {
+	WL_OTA_TEST_FORCE_ANT0 = 0x10,	/* force antenna to Ant 0 */
+	WL_OTA_TEST_FORCE_ANT1 = 0x20,	/* force antenna to Ant 1 */
+};
+
+/* antenna/core fields access */
+#define WL_OTA_TEST_GET_ANT(_txant) ((_txant) & WL_OTA_TEST_ANT_MASK)
+#define WL_OTA_TEST_GET_CORE(_txant) ((_txant) & WL_OTA_TEST_CORE_MASK)
+
+/** Test info vector */
+typedef struct wl_ota_test_args {
+	uint8 cur_test;			/**< test phase */
+	uint8 chan;			/**< channel */
+	uint8 bw;			/**< bandwidth */
+	uint8 control_band;		/**< control band */
+	uint8 stf_mode;			/**< stf mode */
+	ota_rate_info_t rt_info;	/**< Rate info */
+	ota_packetengine_t pkteng;	/**< packeteng info */
+	uint8 txant;			/**< tx antenna */
+	uint8 rxant;			/**< rx antenna */
+	ota_power_info_t pwr_info;	/**< power sweep info */
+	uint8 wait_for_sync;		/**< wait for sync or not */
+	uint8 ldpc;
+	uint8 sgi;
+	/* Update WL_OTA_TESTVEC_T_VERSION for adding new members to this structure */
+} wl_ota_test_args_t;
+
+#define WL_OTA_TESTVEC_T_VERSION		1	/* version of wl_ota_test_vector_t struct */
+typedef struct wl_ota_test_vector {
+	uint16 version;
+	wl_ota_test_args_t test_arg[WL_OTA_TEST_MAX_NUM_SEQ];	/**< Test argument struct */
+	uint16 test_cnt;					/**< Total no of test */
+	uint8 file_dwnld_valid;					/**< File successfully downloaded */
+	uint8 sync_timeout;					/**< sync packet timeout */
+	int8 sync_fail_action;					/**< sync fail action */
+	struct ether_addr sync_mac;				/**< macaddress for sync pkt */
+	struct ether_addr tx_mac;				/**< macaddress for tx */
+	struct ether_addr rx_mac;				/**< macaddress for rx */
+	int8 loop_test;					/**< dbg feature to loop the test */
+	uint16 test_rxcnt;
+	/* Update WL_OTA_TESTVEC_T_VERSION for adding new members to this structure */
+} wl_ota_test_vector_t;
+
+
+/** struct copied back form dongle to host to query the status */
+typedef struct wl_ota_test_status {
+	int16 cur_test_cnt;		/**< test phase */
+	int8 skip_test_reason;		/**< skip test reasoin */
+	wl_ota_test_args_t test_arg;	/**< cur test arg details */
+	uint16 test_cnt;		/**< total no of test downloaded */
+	uint8 file_dwnld_valid;		/**< file successfully downloaded ? */
+	uint8 sync_timeout;		/**< sync timeout */
+	int8 sync_fail_action;		/**< sync fail action */
+	struct ether_addr sync_mac;	/**< macaddress for sync pkt */
+	struct ether_addr tx_mac;	/**< tx mac address */
+	struct ether_addr rx_mac;	/**< rx mac address */
+	uint8  test_stage;		/**< check the test status */
+	int8 loop_test;			/**< Debug feature to puts test enfine in a loop */
+	uint8 sync_status;		/**< sync status */
+} wl_ota_test_status_t;
+
+/* FOR ioctl that take the sta monitor information */
+typedef struct stamon_data {
+	struct ether_addr  ea;
+	int32 rssi;
+} stamon_data_t;
+
+typedef struct stamon_info {
+	int32 version;
+	uint32 count;
+	stamon_data_t sta_data[1];
+} stamon_info_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+typedef struct wl_ota_rx_rssi {
+	uint16	pktcnt;		/* Pkt count used for this rx test */
+	chanspec_t chanspec;	/* Channel info on which the packets are received */
+	int16	rssi;		/* Average RSSI of the first 50% packets received */
+} wl_ota_rx_rssi_t;
+
+#define	WL_OTARSSI_T_VERSION		1	/* version of wl_ota_test_rssi_t struct */
+#define WL_OTA_TEST_RSSI_FIXED_SIZE	OFFSETOF(wl_ota_test_rssi_t, rx_rssi)
+
+typedef struct wl_ota_test_rssi {
+	uint8 version;
+	uint8	testcnt;		/* total measured RSSI values, valid on output only */
+	wl_ota_rx_rssi_t rx_rssi[1]; /* Variable length array of wl_ota_rx_rssi_t */
+} wl_ota_test_rssi_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* WL_OTA END */
+
+/**wl_radar_args_t */
+typedef struct {
+	int32 npulses;	/**< required number of pulses at n * t_int */
+	int32 ncontig;	/**< required number of pulses at t_int */
+	int32 min_pw;	/**< minimum pulse width (20 MHz clocks) */
+	int32 max_pw;	/**< maximum pulse width (20 MHz clocks) */
+	uint16 thresh0;	/**< Radar detection, thresh 0 */
+	uint16 thresh1;	/**< Radar detection, thresh 1 */
+	uint16 blank;	/**< Radar detection, blank control */
+	uint16 fmdemodcfg;	/**< Radar detection, fmdemod config */
+	int32 npulses_lp;  /**< Radar detection, minimum long pulses */
+	int32 min_pw_lp; /**< Minimum pulsewidth for long pulses */
+	int32 max_pw_lp; /**< Maximum pulsewidth for long pulses */
+	int32 min_fm_lp; /**< Minimum fm for long pulses */
+	int32 max_span_lp;  /**< Maximum deltat for long pulses */
+	int32 min_deltat; /**< Minimum spacing between pulses */
+	int32 max_deltat; /**< Maximum spacing between pulses */
+	uint16 autocorr;	/**< Radar detection, autocorr on or off */
+	uint16 st_level_time;	/**< Radar detection, start_timing level */
+	uint16 t2_min; /**< minimum clocks needed to remain in state 2 */
+	uint32 version; /**< version */
+	uint32 fra_pulse_err;	/**< sample error margin for detecting French radar pulsed */
+	int32 npulses_fra;  /**< Radar detection, minimum French pulses set */
+	int32 npulses_stg2;  /**< Radar detection, minimum staggered-2 pulses set */
+	int32 npulses_stg3;  /**< Radar detection, minimum staggered-3 pulses set */
+	uint16 percal_mask;	/**< defines which period cal is masked from radar detection */
+	int32 quant;	/**< quantization resolution to pulse positions */
+	uint32 min_burst_intv_lp;	/**< minimum burst to burst interval for bin3 radar */
+	uint32 max_burst_intv_lp;	/**< maximum burst to burst interval for bin3 radar */
+	int32 nskip_rst_lp;	/**< number of skipped pulses before resetting lp buffer */
+	int32 max_pw_tol; /* maximum tolerance allowd in detected pulse width for radar detection */
+	uint16 feature_mask; /**< 16-bit mask to specify enabled features */
+	uint16 thresh0_sc;	/**< Radar detection, thresh 0 */
+	uint16 thresh1_sc;	/**< Radar detection, thresh 1 */
+} wl_radar_args_t;
+
+#define WL_RADAR_ARGS_VERSION 2
+
+typedef struct {
+	uint32 version; /**< version */
+	uint16 thresh0_20_lo;	/**< Radar detection, thresh 0 (range 5250-5350MHz) for BW 20MHz */
+	uint16 thresh1_20_lo;	/**< Radar detection, thresh 1 (range 5250-5350MHz) for BW 20MHz */
+	uint16 thresh0_40_lo;	/**< Radar detection, thresh 0 (range 5250-5350MHz) for BW 40MHz */
+	uint16 thresh1_40_lo;	/**< Radar detection, thresh 1 (range 5250-5350MHz) for BW 40MHz */
+	uint16 thresh0_80_lo;	/**< Radar detection, thresh 0 (range 5250-5350MHz) for BW 80MHz */
+	uint16 thresh1_80_lo;	/**< Radar detection, thresh 1 (range 5250-5350MHz) for BW 80MHz */
+	uint16 thresh0_20_hi;	/**< Radar detection, thresh 0 (range 5470-5725MHz) for BW 20MHz */
+	uint16 thresh1_20_hi;	/**< Radar detection, thresh 1 (range 5470-5725MHz) for BW 20MHz */
+	uint16 thresh0_40_hi;	/**< Radar detection, thresh 0 (range 5470-5725MHz) for BW 40MHz */
+	uint16 thresh1_40_hi;	/**< Radar detection, thresh 1 (range 5470-5725MHz) for BW 40MHz */
+	uint16 thresh0_80_hi;	/**< Radar detection, thresh 0 (range 5470-5725MHz) for BW 80MHz */
+	uint16 thresh1_80_hi;	/**< Radar detection, thresh 1 (range 5470-5725MHz) for BW 80MHz */
+	uint16 thresh0_160_lo;	/**< Radar detection, thresh 0 (range 5250-5350MHz) for BW 160MHz */
+	uint16 thresh1_160_lo;	/**< Radar detection, thresh 1 (range 5250-5350MHz) for BW 160MHz */
+	uint16 thresh0_160_hi;	/**< Radar detection, thresh 0 (range 5470-5725MHz) for BW 160MHz */
+	uint16 thresh1_160_hi;	/**< Radar detection, thresh 1 (range 5470-5725MHz) for BW 160MHz */
+} wl_radar_thr_t;
+
+typedef struct {
+	uint32 version; /* version */
+	uint16 thresh0_sc_20_lo;
+	uint16 thresh1_sc_20_lo;
+	uint16 thresh0_sc_40_lo;
+	uint16 thresh1_sc_40_lo;
+	uint16 thresh0_sc_80_lo;
+	uint16 thresh1_sc_80_lo;
+	uint16 thresh0_sc_20_hi;
+	uint16 thresh1_sc_20_hi;
+	uint16 thresh0_sc_40_hi;
+	uint16 thresh1_sc_40_hi;
+	uint16 thresh0_sc_80_hi;
+	uint16 thresh1_sc_80_hi;
+	uint16 fc_varth_sb;
+	uint16 fc_varth_bin5_sb;
+	uint16 notradar_enb;
+	uint16 max_notradar_lp;
+	uint16 max_notradar;
+	uint16 max_notradar_lp_sc;
+	uint16 max_notradar_sc;
+	uint16 highpow_war_enb;
+	uint16 highpow_sp_ratio;	//unit is 0.5
+
+} wl_radar_thr2_t;
+
+#define WL_RADAR_THR_VERSION	2
+
+typedef struct {
+	uint32 ver;
+	uint32 len;
+	int32  rssi_th[3];
+	uint8  rssi_gain_80[4];
+	uint8  rssi_gain_160[4];
+} wl_dyn_switch_th_t;
+
+#define WL_PHY_DYN_SWITCH_TH_VERSION	1
+
+/** RSSI per antenna */
+typedef struct {
+	uint32	version;		/**< version field */
+	uint32	count;			/**< number of valid antenna rssi */
+	int8 rssi_ant[WL_RSSI_ANT_MAX];	/**< rssi per antenna */
+} wl_rssi_ant_t;
+
+/* SNR per antenna */
+typedef struct {
+	uint32  version;				/* version field */
+	uint32  count;					/* number of valid antenna snr */
+	int8 snr_ant[WL_RSSI_ANT_MAX];	/* snr per antenna */
+} wl_snr_ant_t;
+
+
+/** data structure used in 'dfs_status' wl interface, which is used to query dfs status */
+typedef struct {
+	uint32 state;		/**< noted by WL_DFS_CACSTATE_XX. */
+	uint32 duration;		/**< time spent in ms in state. */
+	/**
+	 * as dfs enters ISM state, it removes the operational channel from quiet channel
+	 * list and notes the channel in channel_cleared. set to 0 if no channel is cleared
+	 */
+	chanspec_t chanspec_cleared;
+	/** chanspec cleared used to be a uint32, add another to uint16 to maintain size */
+	uint16 pad;
+} wl_dfs_status_t;
+
+typedef struct {
+	uint32 state;		/* noted by WL_DFS_CACSTATE_XX */
+	uint32 duration;		/* time spent in ms in state */
+	chanspec_t chanspec;	/* chanspec of this core */
+	chanspec_t chanspec_last_cleared; /* chanspec last cleared for operation by scanning */
+	uint16 sub_type;	/* currently just the index of the core or the respective PLL */
+	uint16 pad;
+} wl_dfs_sub_status_t;
+
+#define WL_DFS_STATUS_ALL_VERSION	(1)
+typedef struct {
+	uint16 version;		/* version field; current max version 1 */
+	uint16 num_sub_status;
+	wl_dfs_sub_status_t  dfs_sub_status[1]; /* struct array of length num_sub_status */
+} wl_dfs_status_all_t;
+
+#define WL_DFS_AP_MOVE_VERSION	(1)
+
+struct wl_dfs_ap_move_status_v1 {
+	int16 dfs_status;	/* DFS scan status */
+	chanspec_t chanspec;	/* New AP Chanspec */
+	wl_dfs_status_t cac_status;	/* CAC status */
+};
+
+struct wl_dfs_ap_move_status_v2 {
+	int8 version;            /* version field; current max version 1 */
+	int8 move_status;        /* DFS move status */
+	chanspec_t chanspec;     /* New AP Chanspec */
+	wl_dfs_status_all_t scan_status; /* status; see dfs_status_all for wl_dfs_status_all_t */
+};
+
+#define WL_DFS_AP_MOVE_ABORT -1		/* Abort any dfs_ap_move in progress immediately */
+#define WL_DFS_AP_MOVE_STUNT -2		/* Stunt move but continue background CSA if in progress */
+
+
+/** data structure used in 'radar_status' wl interface, which is use to query radar det status */
+typedef struct {
+	uint8 detected;
+	int32 count;
+	uint8 pretended;
+	uint32 radartype;
+	uint32 timenow;
+	uint32 timefromL;
+	int32  lp_csect_single;
+	int32  detected_pulse_index;
+	int32  nconsecq_pulses;
+	chanspec_t ch;
+	int32  pw[10];
+	int32  intv[10];
+	int32  fm[10];
+} wl_radar_status_t;
+
+#define NUM_PWRCTRL_RATES 12
+
+typedef struct {
+	uint8 txpwr_band_max[NUM_PWRCTRL_RATES];	/**< User set target */
+	uint8 txpwr_limit[NUM_PWRCTRL_RATES];		/**< reg and local power limit */
+	uint8 txpwr_local_max;				/**< local max according to the AP */
+	uint8 txpwr_local_constraint;			/**< local constraint according to the AP */
+	uint8 txpwr_chan_reg_max;			/**< Regulatory max for this channel */
+	uint8 txpwr_target[2][NUM_PWRCTRL_RATES];	/**< Latest target for 2.4 and 5 Ghz */
+	uint8 txpwr_est_Pout[2];			/**< Latest estimate for 2.4 and 5 Ghz */
+	uint8 txpwr_opo[NUM_PWRCTRL_RATES];		/**< On G phy, OFDM power offset */
+	uint8 txpwr_bphy_cck_max[NUM_PWRCTRL_RATES];	/**< Max CCK power for this band (SROM) */
+	uint8 txpwr_bphy_ofdm_max;			/**< Max OFDM power for this band (SROM) */
+	uint8 txpwr_aphy_max[NUM_PWRCTRL_RATES];	/**< Max power for A band (SROM) */
+	int8  txpwr_antgain[2];				/**< Ant gain for each band - from SROM */
+	uint8 txpwr_est_Pout_gofdm;			/**< Pwr estimate for 2.4 OFDM */
+} tx_power_legacy_t;
+
+#define WL_TX_POWER_RATES_LEGACY    45
+#define WL_TX_POWER_MCS20_FIRST         12
+#define WL_TX_POWER_MCS20_NUM           16
+#define WL_TX_POWER_MCS40_FIRST         28
+#define WL_TX_POWER_MCS40_NUM           17
+
+typedef struct {
+	uint32 flags;
+	chanspec_t chanspec;                 /**< txpwr report for this channel */
+	chanspec_t local_chanspec;           /**< channel on which we are associated */
+	uint8 local_max;                 /**< local max according to the AP */
+	uint8 local_constraint;              /**< local constraint according to the AP */
+	int8  antgain[2];                /**< Ant gain for each band - from SROM */
+	uint8 rf_cores;                  /**< count of RF Cores being reported */
+	uint8 est_Pout[4];                           /**< Latest tx power out estimate per RF
+							  * chain without adjustment
+							  */
+	uint8 est_Pout_cck;                          /**< Latest CCK tx power out estimate */
+	uint8 user_limit[WL_TX_POWER_RATES_LEGACY];  /**< User limit */
+	uint8 reg_limit[WL_TX_POWER_RATES_LEGACY];   /**< Regulatory power limit */
+	uint8 board_limit[WL_TX_POWER_RATES_LEGACY]; /**< Max power board can support (SROM) */
+	uint8 target[WL_TX_POWER_RATES_LEGACY];      /**< Latest target power */
+} tx_power_legacy2_t;
+
+#define WL_NUM_2x2_ELEMENTS		4
+#define WL_NUM_3x3_ELEMENTS		6
+#define WL_NUM_4x4_ELEMENTS		10
+
+typedef struct {
+	uint16 ver;				/**< version of this struct */
+	uint16 len;				/**< length in bytes of this structure */
+	uint32 flags;
+	chanspec_t chanspec;			/**< txpwr report for this channel */
+	chanspec_t local_chanspec;		/**< channel on which we are associated */
+	uint32     buflen;			/**< ppr buffer length */
+	uint8      pprbuf[1];			/**< Latest target power buffer */
+} wl_txppr_t;
+
+#define WL_TXPPR_VERSION	1
+#define WL_TXPPR_LENGTH	(sizeof(wl_txppr_t))
+#define TX_POWER_T_VERSION	45
+/** number of ppr serialization buffers, it should be reg, board and target */
+#define WL_TXPPR_SER_BUF_NUM	(3)
+
+typedef struct chanspec_txpwr_max {
+	chanspec_t chanspec;   /**< chanspec */
+	uint8 txpwr_max;       /**< max txpwr in all the rates */
+	uint8 padding;
+} chanspec_txpwr_max_t;
+
+typedef struct  wl_chanspec_txpwr_max {
+	uint16 ver;			/**< version of this struct */
+	uint16 len;			/**< length in bytes of this structure */
+	uint32 count;		/**< number of elements of (chanspec, txpwr_max) pair */
+	chanspec_txpwr_max_t txpwr[1];	/**< array of (chanspec, max_txpwr) pair */
+} wl_chanspec_txpwr_max_t;
+
+#define WL_CHANSPEC_TXPWR_MAX_VER	1
+#define WL_CHANSPEC_TXPWR_MAX_LEN	(sizeof(wl_chanspec_txpwr_max_t))
+
+typedef struct tx_inst_power {
+	uint8 txpwr_est_Pout[2];			/**< Latest estimate for 2.4 and 5 Ghz */
+	uint8 txpwr_est_Pout_gofdm;			/**< Pwr estimate for 2.4 OFDM */
+} tx_inst_power_t;
+
+#define WL_NUM_TXCHAIN_MAX	4
+typedef struct wl_txchain_pwr_offsets {
+	int8 offset[WL_NUM_TXCHAIN_MAX];	/**< quarter dBm signed offset for each chain */
+} wl_txchain_pwr_offsets_t;
+
+/** maximum channels returned by the get valid channels iovar */
+#define WL_NUMCHANNELS		64
+#define WL_NUMCHANNELS_MANY_CHAN 10
+#define WL_ITER_LIMIT_MANY_CHAN 5
+
+#define WL_MIMO_PS_CFG_VERSION_1 1
+
+typedef struct wl_mimops_cfg {
+	uint8 version;
+	/* active_chains: 0 for all, 1 for 1 chain. */
+	uint8 active_chains;
+	/* static (0) or dynamic (1).or disabled (3) Mode applies only when active_chains = 0. */
+	uint8 mode;
+	/* bandwidth = Full (0), 20M (1), 40M (2), 80M (3). */
+	uint8 bandwidth;
+	uint8 applychangesafterlearning;
+	uint8 pad[3];
+} wl_mimops_cfg_t;
+
+/* This event is for tracing MIMO PS metrics snapshot calls.
+ * It is helpful to debug out-of-sync issue between
+ * ucode SHM values and FW snapshot calculation.
+ * It is part of the EVENT_LOG_TAG_MIMO_PS_TRACE.
+ */
+#define WL_MIMO_PS_METRICS_SNAPSHOT_TRACE_TYPE	0
+typedef struct wl_mimo_ps_metrics_snapshot_trace {
+	/* type field for this TLV: */
+	uint16  type;
+	/* length field for this TLV */
+	uint16  len;
+	uint32  idle_slotcnt_mimo;	/* MIMO idle slotcnt raw SHM value */
+	uint32  last_idle_slotcnt_mimo;	/* stored value snapshot */
+	uint32  idle_slotcnt_siso;	/* SISO idle slotcnt raw SHM value */
+	uint32  last_idle_slotcnt_siso;	/* stored value snapshot */
+	uint32	rx_time_mimo;		/* Rx MIMO raw SHM value */
+	uint32	last_rx_time_mimo;	/* stored value snapshot */
+	uint32	rx_time_siso;		/* RX SISO raw SHM value */
+	uint32	last_rx_time_siso;	/* stored value snapshot */
+	uint32  tx_time_1chain;		/* Tx 1-chain raw SHM value */
+	uint32  last_tx_time_1chain;	/* stored value snapshot */
+	uint32	tx_time_2chain;		/* Tx 2-chain raw SHM value */
+	uint32	last_tx_time_2chain;	/* stored value snapshot */
+	uint32  tx_time_3chain;		/* Tx 3-chain raw SHM value */
+	uint32  last_tx_time_3chain;	/* stored value snapshot */
+	uint16	reason;			/* reason for snapshot call, see below */
+	/* Does the call reset last values after delta calculation */
+	uint16	reset_last;
+} wl_mimo_ps_metrics_snapshot_trace_t;
+/* reason codes for mimo ps metrics snapshot function calls */
+#define WL_MIMOPS_METRICS_SNAPSHOT_REPORT		1
+#define WL_MIMOPS_METRICS_SNAPSHOT_RXCHAIN_SET		2
+#define WL_MIMOPS_METRICS_SNAPSHOT_ARBI			3
+#define WL_MIMOPS_METRICS_SNAPSHOT_SLOTUPD		4
+#define WL_MIMOPS_METRICS_SNAPSHOT_PMBCNRX		5
+#define WL_MIMOPS_METRICS_SNAPSHOT_BMACINIT		6
+#define WL_MIMOPS_METRICS_SNAPSHOT_HT_COMPLETE		7
+#define WL_MIMOPS_METRICS_SNAPSHOT_OCL                  8
+
+#define WL_MIMO_PS_STATUS_VERSION_2	2
+typedef struct wl_mimo_ps_status {
+	uint8 version;
+	uint8 ap_cap;			/* The associated AP's capability (BW, MIMO/SISO). */
+	uint8 association_status;	/* How we are associated to the AP (MIMO/SISO). */
+	uint8 mimo_ps_state;		/* mimo_ps_cfg states: [0-5]. See below for values */
+	uint8 mrc_state;		/* MRC state: NONE (0), ACTIVE(1) */
+	uint8 bss_rxchain;		/* bss rxchain bitmask */
+	uint8 bss_txchain;		/* bss txchain bitmask */
+	uint8 bss_bw;			/* bandwidth: Full (0), 20M (1), 40M (2), 80M (3), etc */
+	uint16 hw_state;		/* bitmask of hw state. See below for values */
+	uint8 hw_rxchain;		/* actual HW rxchain bitmask */
+	uint8 hw_txchain;		/* actual HW txchain bitmask */
+	uint8 hw_bw;			/* bandwidth: Full (0), 20M (1), 40M (2), 80M (3), etc */
+	uint8 pm_bcnrx_state;		/* actual state of ucode flag */
+	uint8 basic_rates_present;	/* internal flag to trigger siso bcmc rx */
+	uint8 siso_bcmc_rx_state;	/* actual state of ucode flag */
+} wl_mimo_ps_status_t;
+
+#define WL_MIMO_PS_STATUS_VERSION_1	1
+typedef struct wl_mimo_ps_status_v1 {
+	uint8 version;
+	uint8 ap_cap;			/* The associated AP's capability (BW, MIMO/SISO). */
+	uint8 association_status;	/* How we are associated to the AP (MIMO/SISO). */
+	uint8 mimo_ps_state;		/* mimo_ps_cfg states: [0-5]. See below for values */
+	uint8 mrc_state;		/* MRC state: NONE (0), ACTIVE(1) */
+	uint8 bss_rxchain;		/* bss rxchain bitmask */
+	uint8 bss_txchain;		/* bss txchain bitmask */
+	uint8 bss_bw;			/* bandwidth: Full (0), 20M (1), 40M (2), 80M (3), etc */
+	uint16 hw_state;		/* bitmask of hw state. See below for values */
+	uint8 hw_rxchain;		/* actual HW rxchain bitmask */
+	uint8 hw_txchain;		/* actual HW txchain bitmask */
+	uint8 hw_bw;			/* bandwidth: Full (0), 20M (1), 40M (2), 80M (3), etc */
+	uint8 pad[3];
+} wl_mimo_ps_status_v1_t;
+
+#define WL_MIMO_PS_STATUS_AP_CAP(ap_cap)	(ap_cap & 0x0F)
+#define WL_MIMO_PS_STATUS_AP_CAP_BW(ap_cap)	(ap_cap >> 4)
+#define WL_MIMO_PS_STATUS_ASSOC_BW_SHIFT 4
+
+/* version 3: assoc status: low nibble is status enum, high other flags */
+#define WL_MIMO_PS_STATUS_VERSION_3			3
+#define WL_MIMO_PS_STATUS_ASSOC_STATUS_MASK		0x0F
+#define WL_MIMO_PS_STATUS_ASSOC_STATUS_VHT_WITHOUT_OMN	0x80
+
+/* mimo_ps_status: ap_cap/association status */
+enum {
+	WL_MIMO_PS_STATUS_ASSOC_NONE	= 0,
+	WL_MIMO_PS_STATUS_ASSOC_SISO	= 1,
+	WL_MIMO_PS_STATUS_ASSOC_MIMO	= 2,
+	WL_MIMO_PS_STATUS_ASSOC_LEGACY	= 3
+};
+
+/* mimo_ps_status: mimo_ps_cfg states */
+enum {
+	WL_MIMO_PS_CFG_STATE_NONE			= 0,
+	WL_MIMO_PS_CFG_STATE_INFORM_AP_INPROGRESS	= 1,
+	WL_MIMO_PS_CFG_STATE_INFORM_AP_DONE		= 2,
+	WL_MIMO_PS_CFG_STATE_LEARNING			= 3,
+	WL_MIMO_PS_CFG_STATE_HW_CONFIGURE		= 4,
+	WL_MIMO_PS_CFG_STATE_INFORM_AP_PENDING		= 5
+};
+
+/* mimo_ps_status: hw_state values */
+#define WL_MIMO_PS_STATUS_HW_STATE_NONE			0
+#define WL_MIMO_PS_STATUS_HW_STATE_LTECOEX		(0x1 << 0)
+#define WL_MIMO_PS_STATUS_HW_STATE_MIMOPS_BSS		(0x1 << 1)
+#define WL_MIMO_PS_STATUS_HW_STATE_AWDL_BSS		(0x1 << 2)
+#define WL_MIMO_PS_STATUS_HW_STATE_SCAN			(0x1 << 3)
+#define WL_MIMO_PS_STATUS_HW_STATE_TXPPR		(0x1 << 4)
+#define WL_MIMO_PS_STATUS_HW_STATE_PWRTHOTTLE		(0x1 << 5)
+#define WL_MIMO_PS_STATUS_HW_STATE_TMPSENSE		(0x1 << 6)
+#define WL_MIMO_PS_STATUS_HW_STATE_IOVAR		(0x1 << 7)
+#define WL_MIMO_PS_STATUS_HW_STATE_AP_BSS		(0x1 << 8)
+
+/* mimo_ps_status: mrc states */
+#define WL_MIMO_PS_STATUS_MRC_NONE	0
+#define WL_MIMO_PS_STATUS_MRC_ACTIVE	1
+
+/* mimo_ps_status: core flag states for single-core beacon and siso-bcmc rx */
+#define WL_MIMO_PS_STATUS_MHF_FLAG_NONE		0
+#define WL_MIMO_PS_STATUS_MHF_FLAG_ACTIVE	1
+#define WL_MIMO_PS_STATUS_MHF_FLAG_COREDOWN	2
+#define WL_MIMO_PS_STATUS_MHF_FLAG_INVALID	3
+
+/* Type values for the REASON */
+#define WL_MIMO_PS_PS_LEARNING_ABORTED          (1 << 0)
+#define WL_MIMO_PS_PS_LEARNING_COMPLETED        (1 << 1)
+#define WL_MIMO_PS_PS_LEARNING_ONGOING          (1 << 2)
+
+typedef struct wl_mimo_ps_learning_event_data {
+	uint32 startTimeStamp;
+	uint32 endTimeStamp;
+	uint16 reason;
+	struct ether_addr BSSID;
+	uint32 totalSISO_below_rssi_threshold;
+	uint32 totalMIMO_below_rssi_threshold;
+	uint32 totalSISO_above_rssi_threshold;
+	uint32 totalMIMO_above_rssi_threshold;
+} wl_mimo_ps_learning_event_data_t;
+
+#define WL_MIMO_PS_PS_LEARNING_CFG_ABORT	(1 << 0)
+#define WL_MIMO_PS_PS_LEARNING_CFG_STATUS	(1 << 1)
+#define WL_MIMO_PS_PS_LEARNING_CFG_CONFIG	(1 << 2)
+
+#define WL_MIMO_PS_PS_LEARNING_CFG_V1 1
+
+typedef struct wl_mimops_learning_cfg {
+	/* flag:  bit 0 for abort */
+	/* flag:  bit 1 for status */
+	/* flag:  bit 2 for configuring no of packets and rssi */
+	uint8                  flag;
+	/* mimo ps learning version, compatible version is 0 */
+	uint8                  version;
+	/* if version is 0 or rssi is 0, ignored */
+	int8                   learning_rssi_threshold;
+	uint8                  reserved;
+	uint32                 no_of_packets_for_learning;
+	wl_mimo_ps_learning_event_data_t mimops_learning_data;
+} wl_mimops_learning_cfg_t;
+
+
+#define WL_OCL_STATUS_VERSION 1
+typedef struct ocl_status_info {
+	uint8  version;
+	uint8  len;
+	uint16 fw_status;     /* Bits representing FW disable reasons */
+	uint8  hw_status;     /* Bits for actual HW config and SISO/MIMO coremask */
+	uint8  coremask;      /* The ocl core mask (indicating listening core) */
+} ocl_status_info_t;
+
+/* MWS OCL map */
+#define WL_MWS_OCL_OVERRIDE_VERSION 1
+typedef struct wl_mws_ocl_override {
+	uint16  version;    /* Structure version */
+	uint16	bitmap_2g; /* bitmap for 2.4G channels bits 1-13 */
+	uint16	bitmap_5g_lo;  /* bitmap for 5G low channels by 2:
+				*34-48, 52-56, 60-64, 100-102
+				*/
+	uint16	bitmap_5g_mid; /* bitmap for 5G mid channels by 2:
+				* 104, 108-112, 116-120, 124-128,
+				* 132-136, 140, 149-151
+				*/
+	uint16	bitmap_5g_high; /* bitmap for 5G high channels by 2
+				* 153, 157-161, 165
+				*/
+} wl_mws_ocl_override_t;
+
+/* Bits for fw_status */
+#define OCL_DISABLED_HOST		0x01   /* Host has disabled through ocl_enable */
+#define OCL_DISABLED_RSSI		0x02   /* Disabled because of ocl_rssi_threshold */
+#define OCL_DISABLED_LTEC		0x04   /* Disabled due to LTE Coex activity */
+#define OCL_DISABLED_SISO		0x08   /* Disabled while in SISO mode */
+#define OCL_DISABLED_CAL		0x10   /* Disabled during active calibration */
+#define OCL_DISABLED_CHANSWITCH		0x20   /* Disabled during active channel switch */
+#define OCL_DISABLED_ASPEND     0x40   /* Disabled due to assoc pending */
+
+/* Bits for hw_status */
+#define OCL_HWCFG			0x01   /* State of OCL config bit in phy HW */
+#define OCL_HWMIMO			0x02   /* Set if current coremask is > 1 bit */
+#define OCL_COREDOWN			0x80   /* Set if core is currently down */
+
+
+/*
+ * Join preference iovar value is an array of tuples. Each tuple has a one-byte type,
+ * a one-byte length, and a variable length value.  RSSI type tuple must be present
+ * in the array.
+ *
+ * Types are defined in "join preference types" section.
+ *
+ * Length is the value size in octets. It is reserved for WL_JOIN_PREF_WPA type tuple
+ * and must be set to zero.
+ *
+ * Values are defined below.
+ *
+ * 1. RSSI - 2 octets
+ * offset 0: reserved
+ * offset 1: reserved
+ *
+ * 2. WPA - 2 + 12 * n octets (n is # tuples defined below)
+ * offset 0: reserved
+ * offset 1: # of tuples
+ * offset 2: tuple 1
+ * offset 14: tuple 2
+ * ...
+ * offset 2 + 12 * (n - 1) octets: tuple n
+ *
+ * struct wpa_cfg_tuple {
+ *   uint8 akm[DOT11_OUI_LEN+1];     akm suite
+ *   uint8 ucipher[DOT11_OUI_LEN+1]; unicast cipher suite
+ *   uint8 mcipher[DOT11_OUI_LEN+1]; multicast cipher suite
+ * };
+ *
+ * multicast cipher suite can be specified as a specific cipher suite or WL_WPA_ACP_MCS_ANY.
+ *
+ * 3. BAND - 2 octets
+ * offset 0: reserved
+ * offset 1: see "band preference" and "band types"
+ *
+ * 4. BAND RSSI - 2 octets
+ * offset 0: band types
+ * offset 1: +ve RSSI boost value in dB
+ */
+
+struct tsinfo_arg {
+	uint8 octets[3];
+};
+
+#define RATE_CCK_1MBPS 0
+#define RATE_CCK_2MBPS 1
+#define RATE_CCK_5_5MBPS 2
+#define RATE_CCK_11MBPS 3
+
+#define RATE_LEGACY_OFDM_6MBPS 0
+#define RATE_LEGACY_OFDM_9MBPS 1
+#define RATE_LEGACY_OFDM_12MBPS 2
+#define RATE_LEGACY_OFDM_18MBPS 3
+#define RATE_LEGACY_OFDM_24MBPS 4
+#define RATE_LEGACY_OFDM_36MBPS 5
+#define RATE_LEGACY_OFDM_48MBPS 6
+#define RATE_LEGACY_OFDM_54MBPS 7
+
+#define WL_BSSTRANS_RSSI_RATE_MAP_VERSION 1
+
+typedef struct wl_bsstrans_rssi {
+	int8 rssi_2g;	/**< RSSI in dbm for 2.4 G */
+	int8 rssi_5g;	/**< RSSI in dbm for 5G, unused for cck */
+} wl_bsstrans_rssi_t;
+
+#define RSSI_RATE_MAP_MAX_STREAMS 4	/**< max streams supported */
+
+/** RSSI to rate mapping, all 20Mhz, no SGI */
+typedef struct wl_bsstrans_rssi_rate_map {
+	uint16 ver;
+	uint16 len; /**< length of entire structure */
+	wl_bsstrans_rssi_t cck[WL_NUM_RATES_CCK]; /**< 2.4G only */
+	wl_bsstrans_rssi_t ofdm[WL_NUM_RATES_OFDM]; /**< 6 to 54mbps */
+	wl_bsstrans_rssi_t phy_n[RSSI_RATE_MAP_MAX_STREAMS][WL_NUM_RATES_MCS_1STREAM]; /* MCS0-7 */
+	wl_bsstrans_rssi_t phy_ac[RSSI_RATE_MAP_MAX_STREAMS][WL_NUM_RATES_VHT]; /**< MCS0-9 */
+} wl_bsstrans_rssi_rate_map_t;
+
+#define WL_BSSTRANS_ROAMTHROTTLE_VERSION 1
+
+/** Configure number of scans allowed per throttle period */
+typedef struct wl_bsstrans_roamthrottle {
+	uint16 ver;
+	uint16 period;
+	uint16 scans_allowed;
+} wl_bsstrans_roamthrottle_t;
+
+#define	NFIFO			6	/**< # tx/rx fifopairs */
+
+#if defined(BCM_DMA_CT) && !defined(BCM_DMA_CT_DISABLED)
+#define NFIFO_EXT		32		/* 6 traditional FIFOs + 2 rsvd + 24 MU FIFOs */
+#elif defined(WL11AX) && defined(WL11AX_TRIGGERQ_ENABLED)
+#define NFIFO_EXT		10
+#else
+#define NFIFO_EXT		NFIFO
+#endif
+
+/* Reinit reason codes */
+enum {
+	WL_REINIT_RC_NONE             = 0,
+	WL_REINIT_RC_PS_SYNC          = 1,
+	WL_REINIT_RC_PSM_WD           = 2,
+	WL_REINIT_RC_MAC_WAKE         = 3,
+	WL_REINIT_RC_MAC_SUSPEND      = 4,
+	WL_REINIT_RC_MAC_SPIN_WAIT    = 5,
+	WL_REINIT_RC_AXI_BUS_ERROR    = 6,
+	WL_REINIT_RC_DEVICE_REMOVED   = 7,
+	WL_REINIT_RC_PCIE_FATAL_ERROR = 8,
+	WL_REINIT_RC_OL_FW_TRAP       = 9,
+	WL_REINIT_RC_FIFO_ERR         = 10,
+	WL_REINIT_RC_INV_TX_STATUS    = 11,
+	WL_REINIT_RC_MQ_ERROR         = 12,
+	WL_REINIT_RC_PHYTXERR_THRESH  = 13,
+	WL_REINIT_RC_USER_FORCED      = 14,
+	WL_REINIT_RC_FULL_RESET       = 15,
+	WL_REINIT_RC_AP_BEACON        = 16,
+	WL_REINIT_RC_PM_EXCESSED      = 17,
+	WL_REINIT_RC_NO_CLK           = 18,
+	WL_REINIT_RC_SW_ASSERT        = 19,
+	WL_REINIT_RC_PSM_JMP0         = 20,
+	WL_REINIT_RC_PSM_RUN          = 21,
+	WL_REINIT_RC_ENABLE_MAC       = 22,
+	WL_REINIT_RC_SCAN_TIMEOUT     = 23,
+	WL_REINIT_RC_JOIN_TIMEOUT     = 24,
+	/* Below error codes are generated during D3 exit validation */
+	WL_REINIT_RC_LINK_NOT_ACTIVE  = 25,
+	WL_REINIT_RC_PCI_CFG_RD_FAIL  = 26,
+	WL_REINIT_RC_INV_VEN_ID       = 27,
+	WL_REINIT_RC_INV_DEV_ID       = 28,
+	WL_REINIT_RC_INV_BAR0         = 29,
+	WL_REINIT_RC_INV_BAR2         = 30,
+	WL_REINIT_RC_AER_UC_FATAL     = 31,
+	WL_REINIT_RC_AER_UC_NON_FATAL = 32,
+	WL_REINIT_RC_AER_CORR         = 33,
+	WL_REINIT_RC_AER_DEV_STS      = 34,
+	WL_REINIT_RC_PCIe_STS         = 35,
+	WL_REINIT_RC_MMIO_RD_FAIL     = 36,
+	WL_REINIT_RC_MMIO_RD_INVAL    = 37,
+	WL_REINIT_RC_MMIO_ARM_MEM_RD_FAIL = 38,
+	WL_REINIT_RC_MMIO_ARM_MEM_INVAL   = 39,
+	WL_REINIT_RC_SROM_LOAD_FAILED     = 40,
+	WL_REINIT_RC_PHY_CRASH            = 41,
+	WL_REINIT_TX_STALL                = 42,
+	WL_REINIT_RC_TX_FLOW_CONTROL_BLOCKED	= 43,
+	WL_REINIT_RC_RX_HC_FAIL           = 44,
+	WL_REINIT_RC_RX_DMA_STALL         = 45,
+	WL_REINIT_UTRACE_BUF_OVERLAP_SR	  = 46,
+	WL_REINIT_UTRACE_TPL_OUT_BOUNDS   = 47,
+	WL_REINIT_UTRACE_TPL_OSET_STRT0   = 48,
+	WL_REINIT_RC_PHYTXERR             = 49,
+	WL_REINIT_RC_PSM_FATAL_SUSP       = 50,
+	WL_REINIT_RC_TX_FIFO_SUSP         = 51,
+	WL_REINIT_RC_MAC_ENABLE		  = 52,
+	WL_REINIT_RC_LAST	/* This must be the last entry */
+};
+
+#define NREINITREASONCOUNT	8
+
+#define REINITRSNIDX(_x)	(((_x) < WL_REINIT_RC_LAST) ? (_x) : 0)
+
+#define	WL_CNT_T_VERSION	30	/**< current version of wl_cnt_t struct */
+#define WL_CNT_VERSION_6	6
+#define WL_CNT_VERSION_7	7
+/* version 7001 wl_cnt_t is same as version 7 with exception of phywatchdog is
+ * replaced with rxbcnlossmbss */
+#define	WL_CNT_VERSION_7001	7001	/* version 7001 of wl_cnt_t struct */
+#define WL_CNT_VERSION_11	11
+#define WL_CNT_VERSION_XTLV	30
+
+#define WL_COUNTERS_IOV_VERSION_1	1
+#define WL_SUBCNTR_IOV_VER		WL_COUNTERS_IOV_VERSION_1
+/* First two uint16 are version and lenght fields. So offset of the first counter will be 4 */
+#define FIRST_COUNTER_OFFSET		0x04
+
+#define WLC_WITH_XTLV_CNT
+
+/**
+ * tlv IDs uniquely identifies counter component
+ * packed into wl_cmd_t container
+ */
+enum wl_cnt_xtlv_id {
+	WL_CNT_XTLV_WLC = 0x100,		/**< WLC layer counters */
+	WL_CNT_XTLV_WLC_RINIT_RSN = 0x101,	/**< WLC layer reinitreason extension */
+	WL_CNT_XTLV_CNTV_LE10_UCODE = 0x200,	/**< wl counter ver < 11 UCODE MACSTAT */
+	WL_CNT_XTLV_LT40_UCODE_V1 = 0x300,	/**< corerev < 40 UCODE MACSTAT */
+	WL_CNT_XTLV_GE40_UCODE_V1 = 0x400,	/**< corerev >= 40 UCODE MACSTAT */
+	WL_CNT_XTLV_GE64_UCODEX_V1 = 0x800	/* corerev >= 64 UCODEX MACSTAT */
+};
+
+/**
+ * The number of variables in wl macstat cnt struct.
+ * (wl_cnt_ge40mcst_v1_t, wl_cnt_lt40mcst_v1_t, wl_cnt_v_le10_mcst_t)
+ */
+#define WL_CNT_MCST_VAR_NUM 64
+/* sizeof(wl_cnt_ge40mcst_v1_t), sizeof(wl_cnt_lt40mcst_v1_t), and sizeof(wl_cnt_v_le10_mcst_t) */
+#define WL_CNT_MCST_STRUCT_SZ ((uint32)sizeof(uint32) * WL_CNT_MCST_VAR_NUM)
+
+#define WL_CNT_MCXST_STRUCT_SZ ((uint32)sizeof(wl_cnt_ge64mcxst_v1_t))
+#define INVALID_CNT_VAL (uint32)(-1)
+
+#define WL_XTLV_CNTBUF_MAX_SIZE ((uint32)(OFFSETOF(wl_cnt_info_t, data)) +	\
+		(uint32)BCM_XTLV_HDR_SIZE + (uint32)sizeof(wl_cnt_wlc_t) +		\
+		(uint32)BCM_XTLV_HDR_SIZE + WL_CNT_MCST_STRUCT_SZ +              \
+		(uint32)BCM_XTLV_HDR_SIZE + WL_CNT_MCXST_STRUCT_SZ)
+
+#define WL_CNTBUF_MAX_SIZE MAX(WL_XTLV_CNTBUF_MAX_SIZE, (uint32)sizeof(wl_cnt_ver_11_t))
+
+
+/** Top structure of counters IOVar buffer */
+typedef struct {
+	uint16	version;	/**< see definition of WL_CNT_T_VERSION */
+	uint16	datalen;	/**< length of data including all paddings. */
+	uint8   data [1];	/**< variable length payload:
+				 * 1 or more bcm_xtlv_t type of tuples.
+				 * each tuple is padded to multiple of 4 bytes.
+				 * 'datalen' field of this structure includes all paddings.
+				 */
+} wl_cnt_info_t;
+
+/* Top structure of subcounters IOVar buffer
+ * Whenever we make any change in this structure
+ * WL_SUBCNTR_IOV_VER should be updated accordingly
+ * The structure definition should remain consistant b/w
+ * FW and wl/WLM app.
+ */
+typedef struct {
+	uint16	version;	  /* Version of IOVAR structure. Used for backward
+				   * compatibility in future. Whenever we make any
+				   * changes to this structure then value of WL_SUBCNTR_IOV_VER
+				   * needs to be updated properly.
+				   */
+	uint16	length;		  /* length in bytes of this structure */
+	uint16	counters_version; /* see definition of WL_CNT_T_VERSION
+				   * wl app will send the version of counters
+				   * which is used to calculate the offset of counters.
+				   * It must match the version of counters FW is using
+				   * else FW will return error with his version of counters
+				   * set in this field.
+				   */
+	uint16	num_subcounters;  /* Number of counter offset passed by wl app to FW. */
+	uint32	data[1];	  /* variable length payload:
+				   * Offsets to the counters will be passed to FW
+				   * throught this data field. FW will return the value of counters
+				   * at the offsets passed by wl app in this fiels itself.
+				   */
+} wl_subcnt_info_t;
+
+/** wlc layer counters */
+typedef struct {
+	/* transmit stat counters */
+	uint32	txframe;	/**< tx data frames */
+	uint32	txbyte;		/**< tx data bytes */
+	uint32	txretrans;	/**< tx mac retransmits */
+	uint32	txerror;	/**< tx data errors (derived: sum of others) */
+	uint32	txctl;		/**< tx management frames */
+	uint32	txprshort;	/**< tx short preamble frames */
+	uint32	txserr;		/**< tx status errors */
+	uint32	txnobuf;	/**< tx out of buffers errors */
+	uint32	txnoassoc;	/**< tx discard because we're not associated */
+	uint32	txrunt;		/**< tx runt frames */
+	uint32	txchit;		/**< tx header cache hit (fastpath) */
+	uint32	txcmiss;	/**< tx header cache miss (slowpath) */
+
+	/* transmit chip error counters */
+	uint32	txuflo;		/**< tx fifo underflows */
+	uint32	txphyerr;	/**< tx phy errors (indicated in tx status) */
+	uint32	txphycrs;
+
+	/* receive stat counters */
+	uint32	rxframe;	/**< rx data frames */
+	uint32	rxbyte;		/**< rx data bytes */
+	uint32	rxerror;	/**< rx data errors (derived: sum of others) */
+	uint32	rxctl;		/**< rx management frames */
+	uint32	rxnobuf;	/**< rx out of buffers errors */
+	uint32	rxnondata;	/**< rx non data frames in the data channel errors */
+	uint32	rxbadds;	/**< rx bad DS errors */
+	uint32	rxbadcm;	/**< rx bad control or management frames */
+	uint32	rxfragerr;	/**< rx fragmentation errors */
+	uint32	rxrunt;		/**< rx runt frames */
+	uint32	rxgiant;	/**< rx giant frames */
+	uint32	rxnoscb;	/**< rx no scb error */
+	uint32	rxbadproto;	/**< rx invalid frames */
+	uint32	rxbadsrcmac;	/**< rx frames with Invalid Src Mac */
+	uint32	rxbadda;	/**< rx frames tossed for invalid da */
+	uint32	rxfilter;	/**< rx frames filtered out */
+
+	/* receive chip error counters */
+	uint32	rxoflo;		/**< rx fifo overflow errors */
+	uint32	rxuflo[NFIFO];	/**< rx dma descriptor underflow errors */
+
+	uint32	d11cnt_txrts_off;	/**< d11cnt txrts value when reset d11cnt */
+	uint32	d11cnt_rxcrc_off;	/**< d11cnt rxcrc value when reset d11cnt */
+	uint32	d11cnt_txnocts_off;	/**< d11cnt txnocts value when reset d11cnt */
+
+	/* misc counters */
+	uint32	dmade;		/**< tx/rx dma descriptor errors */
+	uint32	dmada;		/**< tx/rx dma data errors */
+	uint32	dmape;		/**< tx/rx dma descriptor protocol errors */
+	uint32	reset;		/**< reset count */
+	uint32	tbtt;		/**< cnts the TBTT int's */
+	uint32	txdmawar;
+	uint32	pkt_callback_reg_fail;	/**< callbacks register failure */
+
+	/* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
+	uint32	txfrag;		/**< dot11TransmittedFragmentCount */
+	uint32	txmulti;	/**< dot11MulticastTransmittedFrameCount */
+	uint32	txfail;		/**< dot11FailedCount */
+	uint32	txretry;	/**< dot11RetryCount */
+	uint32	txretrie;	/**< dot11MultipleRetryCount */
+	uint32	rxdup;		/**< dot11FrameduplicateCount */
+	uint32	txrts;		/**< dot11RTSSuccessCount */
+	uint32	txnocts;	/**< dot11RTSFailureCount */
+	uint32	txnoack;	/**< dot11ACKFailureCount */
+	uint32	rxfrag;		/**< dot11ReceivedFragmentCount */
+	uint32	rxmulti;	/**< dot11MulticastReceivedFrameCount */
+	uint32	rxcrc;		/**< dot11FCSErrorCount */
+	uint32	txfrmsnt;	/**< dot11TransmittedFrameCount (bogus MIB?) */
+	uint32	rxundec;	/**< dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32	tkipmicfaill;	/**< TKIPLocalMICFailures */
+	uint32	tkipcntrmsr;	/**< TKIPCounterMeasuresInvoked */
+	uint32	tkipreplay;	/**< TKIPReplays */
+	uint32	ccmpfmterr;	/**< CCMPFormatErrors */
+	uint32	ccmpreplay;	/**< CCMPReplays */
+	uint32	ccmpundec;	/**< CCMPDecryptErrors */
+	uint32	fourwayfail;	/**< FourWayHandshakeFailures */
+	uint32	wepundec;	/**< dot11WEPUndecryptableCount */
+	uint32	wepicverr;	/**< dot11WEPICVErrorCount */
+	uint32	decsuccess;	/**< DecryptSuccessCount */
+	uint32	tkipicverr;	/**< TKIPICVErrorCount */
+	uint32	wepexcluded;	/**< dot11WEPExcludedCount */
+
+	uint32	txchanrej;	/**< Tx frames suppressed due to channel rejection */
+	uint32	psmwds;		/**< Count PSM watchdogs */
+	uint32	phywatchdog;	/**< Count Phy watchdogs (triggered by ucode) */
+
+	/* MBSS counters, AP only */
+	uint32	prq_entries_handled;	/**< PRQ entries read in */
+	uint32	prq_undirected_entries;	/**<    which were bcast bss & ssid */
+	uint32	prq_bad_entries;	/**<    which could not be translated to info */
+	uint32	atim_suppress_count;	/**< TX suppressions on ATIM fifo */
+	uint32	bcn_template_not_ready;	/**< Template marked in use on send bcn ... */
+	uint32	bcn_template_not_ready_done; /**< ...but "DMA done" interrupt rcvd */
+	uint32	late_tbtt_dpc;	/**< TBTT DPC did not happen in time */
+
+	/* per-rate receive stat counters */
+	uint32  rx1mbps;	/**< packets rx at 1Mbps */
+	uint32  rx2mbps;	/**< packets rx at 2Mbps */
+	uint32  rx5mbps5;	/**< packets rx at 5.5Mbps */
+	uint32  rx6mbps;	/**< packets rx at 6Mbps */
+	uint32  rx9mbps;	/**< packets rx at 9Mbps */
+	uint32  rx11mbps;	/**< packets rx at 11Mbps */
+	uint32  rx12mbps;	/**< packets rx at 12Mbps */
+	uint32  rx18mbps;	/**< packets rx at 18Mbps */
+	uint32  rx24mbps;	/**< packets rx at 24Mbps */
+	uint32  rx36mbps;	/**< packets rx at 36Mbps */
+	uint32  rx48mbps;	/**< packets rx at 48Mbps */
+	uint32  rx54mbps;	/**< packets rx at 54Mbps */
+	uint32  rx108mbps;	/**< packets rx at 108mbps */
+	uint32  rx162mbps;	/**< packets rx at 162mbps */
+	uint32  rx216mbps;	/**< packets rx at 216 mbps */
+	uint32  rx270mbps;	/**< packets rx at 270 mbps */
+	uint32  rx324mbps;	/**< packets rx at 324 mbps */
+	uint32  rx378mbps;	/**< packets rx at 378 mbps */
+	uint32  rx432mbps;	/**< packets rx at 432 mbps */
+	uint32  rx486mbps;	/**< packets rx at 486 mbps */
+	uint32  rx540mbps;	/**< packets rx at 540 mbps */
+
+	uint32	rfdisable;	/**< count of radio disables */
+
+	uint32	txexptime;	/**< Tx frames suppressed due to timer expiration */
+
+	uint32	txmpdu_sgi;	/**< count for sgi transmit */
+	uint32	rxmpdu_sgi;	/**< count for sgi received */
+	uint32	txmpdu_stbc;	/**< count for stbc transmit */
+	uint32	rxmpdu_stbc;	/**< count for stbc received */
+
+	uint32	rxundec_mcst;	/**< dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32	tkipmicfaill_mcst;	/**< TKIPLocalMICFailures */
+	uint32	tkipcntrmsr_mcst;	/**< TKIPCounterMeasuresInvoked */
+	uint32	tkipreplay_mcst;	/**< TKIPReplays */
+	uint32	ccmpfmterr_mcst;	/**< CCMPFormatErrors */
+	uint32	ccmpreplay_mcst;	/**< CCMPReplays */
+	uint32	ccmpundec_mcst;	/**< CCMPDecryptErrors */
+	uint32	fourwayfail_mcst;	/**< FourWayHandshakeFailures */
+	uint32	wepundec_mcst;	/**< dot11WEPUndecryptableCount */
+	uint32	wepicverr_mcst;	/**< dot11WEPICVErrorCount */
+	uint32	decsuccess_mcst;	/**< DecryptSuccessCount */
+	uint32	tkipicverr_mcst;	/**< TKIPICVErrorCount */
+	uint32	wepexcluded_mcst;	/**< dot11WEPExcludedCount */
+
+	uint32	dma_hang;	/**< count for dma hang */
+	uint32	reinit;		/**< count for reinit */
+
+	uint32  pstatxucast;	/**< count of ucast frames xmitted on all psta assoc */
+	uint32  pstatxnoassoc;	/**< count of txnoassoc frames xmitted on all psta assoc */
+	uint32  pstarxucast;	/**< count of ucast frames received on all psta assoc */
+	uint32  pstarxbcmc;	/**< count of bcmc frames received on all psta */
+	uint32  pstatxbcmc;	/**< count of bcmc frames transmitted on all psta */
+
+	uint32  cso_passthrough; /**< hw cso required but passthrough */
+	uint32	cso_normal;	/**< hw cso hdr for normal process */
+	uint32	chained;	/**< number of frames chained */
+	uint32	chainedsz1;	/**< number of chain size 1 frames */
+	uint32	unchained;	/**< number of frames not chained */
+	uint32	maxchainsz;	/**< max chain size so far */
+	uint32	currchainsz;	/**< current chain size */
+	uint32	pciereset;	/**< Secondary Bus Reset issued by driver */
+	uint32	cfgrestore;	/**< configspace restore by driver */
+	uint32	reinitreason[NREINITREASONCOUNT]; /**< reinitreason counters; 0: Unknown reason */
+	uint32	rxrtry;
+	uint32  rxmpdu_mu;      /**< Number of MU MPDUs received */
+
+	/* detailed control/management frames */
+	uint32	txbar;		/**< Number of TX BAR */
+	uint32	rxbar;		/**< Number of RX BAR */
+	uint32	txpspoll;	/**< Number of TX PS-poll */
+	uint32	rxpspoll;	/**< Number of RX PS-poll */
+	uint32	txnull;		/**< Number of TX NULL_DATA */
+	uint32	rxnull;		/**< Number of RX NULL_DATA */
+	uint32	txqosnull;	/**< Number of TX NULL_QoSDATA */
+	uint32	rxqosnull;	/**< Number of RX NULL_QoSDATA */
+	uint32	txassocreq;	/**< Number of TX ASSOC request */
+	uint32	rxassocreq;	/**< Number of RX ASSOC request */
+	uint32	txreassocreq;	/**< Number of TX REASSOC request */
+	uint32	rxreassocreq;	/**< Number of RX REASSOC request */
+	uint32	txdisassoc;	/**< Number of TX DISASSOC */
+	uint32	rxdisassoc;	/**< Number of RX DISASSOC */
+	uint32	txassocrsp;	/**< Number of TX ASSOC response */
+	uint32	rxassocrsp;	/**< Number of RX ASSOC response */
+	uint32	txreassocrsp;	/**< Number of TX REASSOC response */
+	uint32	rxreassocrsp;	/**< Number of RX REASSOC response */
+	uint32	txauth;		/**< Number of TX AUTH */
+	uint32	rxauth;		/**< Number of RX AUTH */
+	uint32	txdeauth;	/**< Number of TX DEAUTH */
+	uint32	rxdeauth;	/**< Number of RX DEAUTH */
+	uint32	txprobereq;	/**< Number of TX probe request */
+	uint32	rxprobereq;	/**< Number of RX probe request */
+	uint32	txprobersp;	/**< Number of TX probe response */
+	uint32	rxprobersp;	/**< Number of RX probe response */
+	uint32	txaction;	/**< Number of TX action frame */
+	uint32	rxaction;	/**< Number of RX action frame */
+	uint32  ampdu_wds;	/**< Number of AMPDU watchdogs */
+	uint32  txlost;		/**< Number of lost packets reported in txs */
+	uint32	txdatamcast;	/**< Number of TX multicast data packets */
+	uint32	txdatabcast;	/**< Number of TX broadcast data packets */
+	uint32	psmxwds;	/**< Number of PSMx watchdogs */
+	uint32  rxback;
+	uint32  txback;
+	uint32  p2p_tbtt;	/**< Number of P2P TBTT Events */
+	uint32  p2p_tbtt_miss;	/**< Number of P2P TBTT Events Miss */
+	uint32	txqueue_start;
+	uint32	txqueue_end;
+} wl_cnt_wlc_t;
+
+/* Reinit reasons - do not put anything else other than reinit reasons here */
+typedef struct {
+	uint32 rsn[WL_REINIT_RC_LAST];
+} reinit_rsns_t;
+
+/* MACXSTAT counters for ucodex (corerev >= 64) */
+typedef struct {
+	uint32 macxsusp;
+	uint32 m2vmsg;
+	uint32 v2mmsg;
+	uint32 mboxout;
+	uint32 musnd;
+	uint32 sfb2v;
+} wl_cnt_ge64mcxst_v1_t;
+
+/** MACSTAT counters for ucode (corerev >= 40) */
+typedef struct {
+	/* MAC counters: 32-bit version of d11.h's macstat_t */
+	uint32	txallfrm;	/**< total number of frames sent, incl. Data, ACK, RTS, CTS,
+				 * Control Management (includes retransmissions)
+				 */
+	uint32	txrtsfrm;	/**< number of RTS sent out by the MAC */
+	uint32	txctsfrm;	/**< number of CTS sent out by the MAC */
+	uint32	txackfrm;	/**< number of ACK frames sent out */
+	uint32	txdnlfrm;	/**< number of Null-Data transmission generated from template  */
+	uint32	txbcnfrm;	/**< beacons transmitted */
+	uint32	txfunfl[6];	/**< per-fifo tx underflows */
+	uint32	txampdu;	/**< number of AMPDUs transmitted */
+	uint32	txmpdu;		/**< number of MPDUs transmitted */
+	uint32	txtplunfl;	/**< Template underflows (mac was too slow to transmit ACK/CTS
+				 * or BCN)
+				 */
+	uint32	txphyerror;	/**< Transmit phy error, type of error is reported in tx-status for
+				 * driver enqueued frames
+				 */
+	uint32  pktengrxducast; /**< unicast frames rxed by the pkteng code */
+	uint32  pktengrxdmcast; /**< multicast frames rxed by the pkteng code */
+	uint32	rxfrmtoolong;	/**< Received frame longer than legal limit (2346 bytes) */
+	uint32	rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */
+	uint32	rxanyerr;	/**< Any RX error that is not counted by other counters. */
+	uint32	rxbadfcs;	/**< number of frames for which the CRC check failed in the MAC */
+	uint32	rxbadplcp;	/**< parity check of the PLCP header failed */
+	uint32	rxcrsglitch;	/**< PHY was able to correlate the preamble but not the header */
+	uint32	rxstrt;		/**< Number of received frames with a good PLCP
+				 * (i.e. passing parity check)
+				 */
+	uint32	rxdtucastmbss; /**< number of received DATA frames with good FCS and matching RA */
+	uint32	rxmgucastmbss; /**< number of received mgmt frames with good FCS and matching RA */
+	uint32	rxctlucast; /**< number of received CNTRL frames with good FCS and matching RA */
+	uint32	rxrtsucast;	/**< number of unicast RTS addressed to the MAC (good FCS) */
+	uint32	rxctsucast;	/**< number of unicast CTS addressed to the MAC (good FCS) */
+	uint32	rxackucast;	/**< number of ucast ACKS received (good FCS) */
+	uint32	rxdtocast; /**< number of received DATA frames (good FCS and not matching RA) */
+	uint32	rxmgocast; /**< number of received MGMT frames (good FCS and not matching RA) */
+	uint32	rxctlocast; /**< number of received CNTRL frame (good FCS and not matching RA) */
+	uint32	rxrtsocast;	/**< number of received RTS not addressed to the MAC */
+	uint32	rxctsocast;	/**< number of received CTS not addressed to the MAC */
+	uint32	rxdtmcast;	/**< number of RX Data multicast frames received by the MAC */
+	uint32	rxmgmcast;	/**< number of RX Management multicast frames received by the MAC */
+	uint32	rxctlmcast;	/**< number of RX Control multicast frames received by the MAC
+				 * (unlikely to see these)
+				 */
+	uint32	rxbeaconmbss;	/**< beacons received from member of BSS */
+	uint32	rxdtucastobss; /**< number of unicast frames addressed to the MAC from
+				  * other BSS (WDS FRAME)
+				  */
+	uint32	rxbeaconobss;	/**< beacons received from other BSS */
+	uint32	rxrsptmout;	/**< number of response timeouts for transmitted frames
+				 * expecting a response
+				 */
+	uint32	bcntxcancl;	/**< transmit beacons canceled due to receipt of beacon (IBSS) */
+	uint32	rxnodelim;	/**< number of no valid delimiter detected by ampdu parser */
+	uint32	rxf0ovfl;	/**< number of receive fifo 0 overflows */
+	uint32	rxf1ovfl;	/**< number of receive fifo 1 overflows */
+	uint32	rxhlovfl;	/**< number of length / header fifo overflows */
+	uint32	missbcn_dbg;	/**< number of beacon missed to receive */
+	uint32	pmqovfl;	/**< number of PMQ overflows */
+	uint32	rxcgprqfrm;	/**< number of received Probe requests that made it into
+				 * the PRQ fifo
+				 */
+	uint32	rxcgprsqovfl;	/**< Rx Probe Request Que overflow in the AP */
+	uint32	txcgprsfail;	/**< Tx Probe Response Fail. AP sent probe response but did
+				 * not get ACK
+				 */
+	uint32	txcgprssuc;	/**< Tx Probe Response Success (ACK was received) */
+	uint32	prs_timeout;	/**< number of probe requests that were dropped from the PRQ
+				 * fifo because a probe response could not be sent out within
+				 * the time limit defined in M_PRS_MAXTIME
+				 */
+	uint32	txrtsfail;	/**< number of rts transmission failure that reach retry limit */
+	uint32	txucast;	/**< number of unicast tx expecting response other than cts/cwcts */
+	uint32  txinrtstxop;	/**< number of data frame transmissions during rts txop */
+	uint32	rxback;		/**< blockack rxcnt */
+	uint32	txback;		/**< blockack txcnt */
+	uint32	bphy_rxcrsglitch;	/**< PHY count of bphy glitches */
+	uint32	rxdrop20s;	/**< drop secondary cnt */
+	uint32	rxtoolate;	/**< receive too late */
+	uint32  bphy_badplcp;	/**< number of bad PLCP reception on BPHY rate */
+} wl_cnt_ge40mcst_v1_t;
+
+/** MACSTAT counters for ucode (corerev < 40) */
+typedef struct {
+	/* MAC counters: 32-bit version of d11.h's macstat_t */
+	uint32	txallfrm;	/**< total number of frames sent, incl. Data, ACK, RTS, CTS,
+				 * Control Management (includes retransmissions)
+				 */
+	uint32	txrtsfrm;	/**< number of RTS sent out by the MAC */
+	uint32	txctsfrm;	/**< number of CTS sent out by the MAC */
+	uint32	txackfrm;	/**< number of ACK frames sent out */
+	uint32	txdnlfrm;	/**< number of Null-Data transmission generated from template  */
+	uint32	txbcnfrm;	/**< beacons transmitted */
+	uint32	txfunfl[6];	/**< per-fifo tx underflows */
+	uint32	txampdu;	/**< number of AMPDUs transmitted */
+	uint32	txmpdu;		/**< number of MPDUs transmitted */
+	uint32	txtplunfl;	/**< Template underflows (mac was too slow to transmit ACK/CTS
+				 * or BCN)
+				 */
+	uint32	txphyerror;	/**< Transmit phy error, type of error is reported in tx-status for
+				 * driver enqueued frames
+				 */
+	uint32  pktengrxducast; /**< unicast frames rxed by the pkteng code */
+	uint32  pktengrxdmcast; /**< multicast frames rxed by the pkteng code */
+	uint32	rxfrmtoolong;	/**< Received frame longer than legal limit (2346 bytes) */
+	uint32	rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */
+	uint32	rxanyerr;	/**< Any RX error that is not counted by other counters. */
+	uint32	rxbadfcs;	/**< number of frames for which the CRC check failed in the MAC */
+	uint32	rxbadplcp;	/**< parity check of the PLCP header failed */
+	uint32	rxcrsglitch;	/**< PHY was able to correlate the preamble but not the header */
+	uint32	rxstrt;		/**< Number of received frames with a good PLCP
+				 * (i.e. passing parity check)
+				 */
+	uint32	rxdtucastmbss; /**< number of received DATA frames with good FCS and matching RA */
+	uint32	rxmgucastmbss; /**< number of received mgmt frames with good FCS and matching RA */
+	uint32	rxctlucast; /**< number of received CNTRL frames with good FCS and matching RA */
+	uint32	rxrtsucast;	/**< number of unicast RTS addressed to the MAC (good FCS) */
+	uint32	rxctsucast;	/**< number of unicast CTS addressed to the MAC (good FCS) */
+	uint32	rxackucast;	/**< number of ucast ACKS received (good FCS) */
+	uint32	rxdtocast;  /**< number of received DATA frames (good FCS and not matching RA) */
+	uint32	rxmgocast;  /**< number of received MGMT frames (good FCS and not matching RA) */
+	uint32	rxctlocast; /**< number of received CNTRL frame (good FCS and not matching RA) */
+	uint32	rxrtsocast;	/**< number of received RTS not addressed to the MAC */
+	uint32	rxctsocast;	/**< number of received CTS not addressed to the MAC */
+	uint32	rxdtmcast;	/**< number of RX Data multicast frames received by the MAC */
+	uint32	rxmgmcast;	/**< number of RX Management multicast frames received by the MAC */
+	uint32	rxctlmcast;	/**< number of RX Control multicast frames received by the MAC
+				 * (unlikely to see these)
+				 */
+	uint32	rxbeaconmbss;	/**< beacons received from member of BSS */
+	uint32	rxdtucastobss; /**< number of unicast frames addressed to the MAC from
+				  * other BSS (WDS FRAME)
+				  */
+	uint32	rxbeaconobss;	/**< beacons received from other BSS */
+	uint32	rxrsptmout;	/**< number of response timeouts for transmitted frames
+				 * expecting a response
+				 */
+	uint32	bcntxcancl;	/**< transmit beacons canceled due to receipt of beacon (IBSS) */
+	uint32	rxnodelim;	/**< number of no valid delimiter detected by ampdu parser */
+	uint32	rxf0ovfl;	/**< number of receive fifo 0 overflows */
+	uint32	dbgoff46;
+	uint32	dbgoff47;
+	uint32	dbgoff48;	/**< Used for counting txstatus queue overflow (corerev <= 4)  */
+	uint32	pmqovfl;	/**< number of PMQ overflows */
+	uint32	rxcgprqfrm;	/**< number of received Probe requests that made it into
+				 * the PRQ fifo
+				 */
+	uint32	rxcgprsqovfl;	/**< Rx Probe Request Que overflow in the AP */
+	uint32	txcgprsfail;	/**< Tx Probe Response Fail. AP sent probe response but did
+				 * not get ACK
+				 */
+	uint32	txcgprssuc;	/**< Tx Probe Response Success (ACK was received) */
+	uint32	prs_timeout;	/**< number of probe requests that were dropped from the PRQ
+				 * fifo because a probe response could not be sent out within
+				 * the time limit defined in M_PRS_MAXTIME
+				 */
+	uint32	txrtsfail;	/**< number of rts transmission failure that reach retry limit */
+	uint32	txucast;	/**< number of unicast tx expecting response other than cts/cwcts */
+	uint32  txinrtstxop;	/**< number of data frame transmissions during rts txop */
+	uint32	rxback;		/**< blockack rxcnt */
+	uint32	txback;		/**< blockack txcnt */
+	uint32	bphy_rxcrsglitch;	/**< PHY count of bphy glitches */
+	uint32	phywatch;
+	uint32	rxtoolate;	/**< receive too late */
+	uint32  bphy_badplcp;	/**< number of bad PLCP reception on BPHY rate */
+} wl_cnt_lt40mcst_v1_t;
+
+/** MACSTAT counters for "wl counter" version <= 10 */
+typedef struct {
+	/* MAC counters: 32-bit version of d11.h's macstat_t */
+	uint32	txallfrm;	/**< total number of frames sent, incl. Data, ACK, RTS, CTS,
+				 * Control Management (includes retransmissions)
+				 */
+	uint32	txrtsfrm;	/**< number of RTS sent out by the MAC */
+	uint32	txctsfrm;	/**< number of CTS sent out by the MAC */
+	uint32	txackfrm;	/**< number of ACK frames sent out */
+	uint32	txdnlfrm;	/**< number of Null-Data transmission generated from template  */
+	uint32	txbcnfrm;	/**< beacons transmitted */
+	uint32	txfunfl[6];	/**< per-fifo tx underflows */
+	uint32	txfbw;		/**< transmit at fallback bw (dynamic bw) */
+	uint32	PAD0;		/**< number of MPDUs transmitted */
+	uint32	txtplunfl;	/**< Template underflows (mac was too slow to transmit ACK/CTS
+				 * or BCN)
+				 */
+	uint32	txphyerror;	/**< Transmit phy error, type of error is reported in tx-status for
+				 * driver enqueued frames
+				 */
+	uint32  pktengrxducast; /**< unicast frames rxed by the pkteng code */
+	uint32  pktengrxdmcast; /**< multicast frames rxed by the pkteng code */
+	uint32	rxfrmtoolong;	/**< Received frame longer than legal limit (2346 bytes) */
+	uint32	rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */
+	uint32	rxinvmachdr;	/**< Either the protocol version != 0 or frame type not
+				 * data/control/management
+				 */
+	uint32	rxbadfcs;	/**< number of frames for which the CRC check failed in the MAC */
+	uint32	rxbadplcp;	/**< parity check of the PLCP header failed */
+	uint32	rxcrsglitch;	/**< PHY was able to correlate the preamble but not the header */
+	uint32	rxstrt;		/**< Number of received frames with a good PLCP
+				 * (i.e. passing parity check)
+				 */
+	uint32	rxdfrmucastmbss; /* number of received DATA frames with good FCS and matching RA */
+	uint32	rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
+	uint32	rxcfrmucast; /**< number of received CNTRL frames with good FCS and matching RA */
+	uint32	rxrtsucast;  /**< number of unicast RTS addressed to the MAC (good FCS) */
+	uint32	rxctsucast;  /**< number of unicast CTS addressed to the MAC (good FCS) */
+	uint32	rxackucast;	/**< number of ucast ACKS received (good FCS) */
+	uint32	rxdfrmocast; /**< number of received DATA frames (good FCS and not matching RA) */
+	uint32	rxmfrmocast; /**< number of received MGMT frames (good FCS and not matching RA) */
+	uint32	rxcfrmocast; /**< number of received CNTRL frame (good FCS and not matching RA) */
+	uint32	rxrtsocast;	/**< number of received RTS not addressed to the MAC */
+	uint32	rxctsocast;	/**< number of received CTS not addressed to the MAC */
+	uint32	rxdfrmmcast;	/**< number of RX Data multicast frames received by the MAC */
+	uint32	rxmfrmmcast;	/**< number of RX Management multicast frames received by the MAC */
+	uint32	rxcfrmmcast;	/**< number of RX Control multicast frames received by the MAC
+				 * (unlikely to see these)
+				 */
+	uint32	rxbeaconmbss;	/**< beacons received from member of BSS */
+	uint32	rxdfrmucastobss; /**< number of unicast frames addressed to the MAC from
+				  * other BSS (WDS FRAME)
+				  */
+	uint32	rxbeaconobss;	/**< beacons received from other BSS */
+	uint32	rxrsptmout;	/**< number of response timeouts for transmitted frames
+				 * expecting a response
+				 */
+	uint32	bcntxcancl;	/**< transmit beacons canceled due to receipt of beacon (IBSS) */
+	uint32	PAD1;
+	uint32	rxf0ovfl;	/**< number of receive fifo 0 overflows */
+	uint32	rxf1ovfl;	/**< Number of receive fifo 1 overflows (obsolete) */
+	uint32	rxf2ovfl;	/**< Number of receive fifo 2 overflows (obsolete) */
+	uint32	txsfovfl;	/**< Number of transmit status fifo overflows (obsolete) */
+	uint32	pmqovfl;	/**< number of PMQ overflows */
+	uint32	rxcgprqfrm;	/**< number of received Probe requests that made it into
+				 * the PRQ fifo
+				 */
+	uint32	rxcgprsqovfl;	/**< Rx Probe Request Que overflow in the AP */
+	uint32	txcgprsfail;	/**< Tx Probe Response Fail. AP sent probe response but did
+				 * not get ACK
+				 */
+	uint32	txcgprssuc;	/**< Tx Probe Response Success (ACK was received) */
+	uint32	prs_timeout;	/**< number of probe requests that were dropped from the PRQ
+				 * fifo because a probe response could not be sent out within
+				 * the time limit defined in M_PRS_MAXTIME
+				 */
+	uint32	rxnack;		/**< obsolete */
+	uint32	frmscons;	/**< obsolete */
+	uint32  txnack;		/**< obsolete */
+	uint32	rxback;		/**< blockack rxcnt */
+	uint32	txback;		/**< blockack txcnt */
+	uint32	bphy_rxcrsglitch;	/**< PHY count of bphy glitches */
+	uint32	rxdrop20s;	/**< drop secondary cnt */
+	uint32	rxtoolate;	/**< receive too late */
+	uint32  bphy_badplcp;	/**< number of bad PLCP reception on BPHY rate */
+} wl_cnt_v_le10_mcst_t;
+
+#define MAX_RX_FIFO 3
+#define WL_RXFIFO_CNT_VERSION  1   /* current version of wl_rxfifo_cnt_t */
+typedef struct {
+	/* Counters for frames received from rx fifos */
+	uint16	version;
+	uint16	length;		/* length of entire structure */
+	uint32	rxf_data[MAX_RX_FIFO];		/* data frames from rx fifo */
+	uint32	rxf_mgmtctl[MAX_RX_FIFO];	/* mgmt/ctl frames from rx fifo */
+} wl_rxfifo_cnt_t;
+
+typedef struct {
+	uint16	version;	/**< see definition of WL_CNT_T_VERSION */
+	uint16	length;		/**< length of entire structure */
+
+	/* transmit stat counters */
+	uint32	txframe;	/**< tx data frames */
+	uint32	txbyte;		/**< tx data bytes */
+	uint32	txretrans;	/**< tx mac retransmits */
+	uint32	txerror;	/**< tx data errors (derived: sum of others) */
+	uint32	txctl;		/**< tx management frames */
+	uint32	txprshort;	/**< tx short preamble frames */
+	uint32	txserr;		/**< tx status errors */
+	uint32	txnobuf;	/**< tx out of buffers errors */
+	uint32	txnoassoc;	/**< tx discard because we're not associated */
+	uint32	txrunt;		/**< tx runt frames */
+	uint32	txchit;		/**< tx header cache hit (fastpath) */
+	uint32	txcmiss;	/**< tx header cache miss (slowpath) */
+
+	/* transmit chip error counters */
+	uint32	txuflo;		/**< tx fifo underflows */
+	uint32	txphyerr;	/**< tx phy errors (indicated in tx status) */
+	uint32	txphycrs;
+
+	/* receive stat counters */
+	uint32	rxframe;	/**< rx data frames */
+	uint32	rxbyte;		/**< rx data bytes */
+	uint32	rxerror;	/**< rx data errors (derived: sum of others) */
+	uint32	rxctl;		/**< rx management frames */
+	uint32	rxnobuf;	/**< rx out of buffers errors */
+	uint32	rxnondata;	/**< rx non data frames in the data channel errors */
+	uint32	rxbadds;	/**< rx bad DS errors */
+	uint32	rxbadcm;	/**< rx bad control or management frames */
+	uint32	rxfragerr;	/**< rx fragmentation errors */
+	uint32	rxrunt;		/**< rx runt frames */
+	uint32	rxgiant;	/**< rx giant frames */
+	uint32	rxnoscb;	/**< rx no scb error */
+	uint32	rxbadproto;	/**< rx invalid frames */
+	uint32	rxbadsrcmac;	/**< rx frames with Invalid Src Mac */
+	uint32	rxbadda;	/**< rx frames tossed for invalid da */
+	uint32	rxfilter;	/**< rx frames filtered out */
+
+	/* receive chip error counters */
+	uint32	rxoflo;		/**< rx fifo overflow errors */
+	uint32	rxuflo[NFIFO];	/**< rx dma descriptor underflow errors */
+
+	uint32	d11cnt_txrts_off;	/**< d11cnt txrts value when reset d11cnt */
+	uint32	d11cnt_rxcrc_off;	/**< d11cnt rxcrc value when reset d11cnt */
+	uint32	d11cnt_txnocts_off;	/**< d11cnt txnocts value when reset d11cnt */
+
+	/* misc counters */
+	uint32	dmade;		/**< tx/rx dma descriptor errors */
+	uint32	dmada;		/**< tx/rx dma data errors */
+	uint32	dmape;		/**< tx/rx dma descriptor protocol errors */
+	uint32	reset;		/**< reset count */
+	uint32	tbtt;		/**< cnts the TBTT int's */
+	uint32	txdmawar;
+	uint32	pkt_callback_reg_fail;	/**< callbacks register failure */
+
+	/* MAC counters: 32-bit version of d11.h's macstat_t */
+	uint32	txallfrm;	/**< total number of frames sent, incl. Data, ACK, RTS, CTS,
+				 * Control Management (includes retransmissions)
+				 */
+	uint32	txrtsfrm;	/**< number of RTS sent out by the MAC */
+	uint32	txctsfrm;	/**< number of CTS sent out by the MAC */
+	uint32	txackfrm;	/**< number of ACK frames sent out */
+	uint32	txdnlfrm;	/**< Not used */
+	uint32	txbcnfrm;	/**< beacons transmitted */
+	uint32	txfunfl[6];	/**< per-fifo tx underflows */
+	uint32	rxtoolate;	/**< receive too late */
+	uint32  txfbw;		/**< transmit at fallback bw (dynamic bw) */
+	uint32	txtplunfl;	/**< Template underflows (mac was too slow to transmit ACK/CTS
+				 * or BCN)
+				 */
+	uint32	txphyerror;	/**< Transmit phy error, type of error is reported in tx-status for
+				 * driver enqueued frames
+				 */
+	uint32	rxfrmtoolong;	/**< Received frame longer than legal limit (2346 bytes) */
+	uint32	rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */
+	uint32	rxinvmachdr;	/**< Either the protocol version != 0 or frame type not
+				 * data/control/management
+				 */
+	uint32	rxbadfcs;	/**< number of frames for which the CRC check failed in the MAC */
+	uint32	rxbadplcp;	/**< parity check of the PLCP header failed */
+	uint32	rxcrsglitch;	/**< PHY was able to correlate the preamble but not the header */
+	uint32	rxstrt;		/**< Number of received frames with a good PLCP
+				 * (i.e. passing parity check)
+				 */
+	uint32	rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */
+	uint32	rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
+	uint32	rxcfrmucast; /**< number of received CNTRL frames with good FCS and matching RA */
+	uint32	rxrtsucast;	/**< number of unicast RTS addressed to the MAC (good FCS) */
+	uint32	rxctsucast;	/**< number of unicast CTS addressed to the MAC (good FCS) */
+	uint32	rxackucast;	/**< number of ucast ACKS received (good FCS) */
+	uint32	rxdfrmocast; /**< number of received DATA frames (good FCS and not matching RA) */
+	uint32	rxmfrmocast; /**< number of received MGMT frames (good FCS and not matching RA) */
+	uint32	rxcfrmocast; /**< number of received CNTRL frame (good FCS and not matching RA) */
+	uint32	rxrtsocast;	/**< number of received RTS not addressed to the MAC */
+	uint32	rxctsocast;	/**< number of received CTS not addressed to the MAC */
+	uint32	rxdfrmmcast;	/**< number of RX Data multicast frames received by the MAC */
+	uint32	rxmfrmmcast;	/**< number of RX Management multicast frames received by the MAC */
+	uint32	rxcfrmmcast;	/**< number of RX Control multicast frames received by the MAC
+				 * (unlikely to see these)
+				 */
+	uint32	rxbeaconmbss;	/**< beacons received from member of BSS */
+	uint32	rxdfrmucastobss; /**< number of unicast frames addressed to the MAC from
+				  * other BSS (WDS FRAME)
+				  */
+	uint32	rxbeaconobss;	/**< beacons received from other BSS */
+	uint32	rxrsptmout;	/**< Number of response timeouts for transmitted frames
+				 * expecting a response
+				 */
+	uint32	bcntxcancl;	/**< transmit beacons canceled due to receipt of beacon (IBSS) */
+	uint32	rxf0ovfl;	/**< Number of receive fifo 0 overflows */
+	uint32	rxf1ovfl;	/**< Number of receive fifo 1 overflows (obsolete) */
+	uint32	rxf2ovfl;	/**< Number of receive fifo 2 overflows (obsolete) */
+	uint32	txsfovfl;	/**< Number of transmit status fifo overflows (obsolete) */
+	uint32	pmqovfl;	/**< Number of PMQ overflows */
+	uint32	rxcgprqfrm;	/**< Number of received Probe requests that made it into
+				 * the PRQ fifo
+				 */
+	uint32	rxcgprsqovfl;	/**< Rx Probe Request Que overflow in the AP */
+	uint32	txcgprsfail;	/**< Tx Probe Response Fail. AP sent probe response but did
+				 * not get ACK
+				 */
+	uint32	txcgprssuc;	/**< Tx Probe Response Success (ACK was received) */
+	uint32	prs_timeout;	/**< Number of probe requests that were dropped from the PRQ
+				 * fifo because a probe response could not be sent out within
+				 * the time limit defined in M_PRS_MAXTIME
+				 */
+	uint32	rxnack;		/**< obsolete */
+	uint32	frmscons;	/**< obsolete */
+	uint32  txnack;		/**< obsolete */
+	uint32	rxback;		/**< blockack rxcnt */
+	uint32	txback;		/**< blockack txcnt */
+
+	/* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
+	uint32	txfrag;		/**< dot11TransmittedFragmentCount */
+	uint32	txmulti;	/**< dot11MulticastTransmittedFrameCount */
+	uint32	txfail;		/**< dot11FailedCount */
+	uint32	txretry;	/**< dot11RetryCount */
+	uint32	txretrie;	/**< dot11MultipleRetryCount */
+	uint32	rxdup;		/**< dot11FrameduplicateCount */
+	uint32	txrts;		/**< dot11RTSSuccessCount */
+	uint32	txnocts;	/**< dot11RTSFailureCount */
+	uint32	txnoack;	/**< dot11ACKFailureCount */
+	uint32	rxfrag;		/**< dot11ReceivedFragmentCount */
+	uint32	rxmulti;	/**< dot11MulticastReceivedFrameCount */
+	uint32	rxcrc;		/**< dot11FCSErrorCount */
+	uint32	txfrmsnt;	/**< dot11TransmittedFrameCount (bogus MIB?) */
+	uint32	rxundec;	/**< dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32	tkipmicfaill;	/**< TKIPLocalMICFailures */
+	uint32	tkipcntrmsr;	/**< TKIPCounterMeasuresInvoked */
+	uint32	tkipreplay;	/**< TKIPReplays */
+	uint32	ccmpfmterr;	/**< CCMPFormatErrors */
+	uint32	ccmpreplay;	/**< CCMPReplays */
+	uint32	ccmpundec;	/**< CCMPDecryptErrors */
+	uint32	fourwayfail;	/**< FourWayHandshakeFailures */
+	uint32	wepundec;	/**< dot11WEPUndecryptableCount */
+	uint32	wepicverr;	/**< dot11WEPICVErrorCount */
+	uint32	decsuccess;	/**< DecryptSuccessCount */
+	uint32	tkipicverr;	/**< TKIPICVErrorCount */
+	uint32	wepexcluded;	/**< dot11WEPExcludedCount */
+
+	uint32	txchanrej;	/**< Tx frames suppressed due to channel rejection */
+	uint32	psmwds;		/**< Count PSM watchdogs */
+	uint32	phywatchdog;	/**< Count Phy watchdogs (triggered by ucode) */
+
+	/* MBSS counters, AP only */
+	uint32	prq_entries_handled;	/**< PRQ entries read in */
+	uint32	prq_undirected_entries;	/**<    which were bcast bss & ssid */
+	uint32	prq_bad_entries;	/**<    which could not be translated to info */
+	uint32	atim_suppress_count;	/**< TX suppressions on ATIM fifo */
+	uint32	bcn_template_not_ready;	/**< Template marked in use on send bcn ... */
+	uint32	bcn_template_not_ready_done; /**< ...but "DMA done" interrupt rcvd */
+	uint32	late_tbtt_dpc;	/**< TBTT DPC did not happen in time */
+
+	/* per-rate receive stat counters */
+	uint32  rx1mbps;	/**< packets rx at 1Mbps */
+	uint32  rx2mbps;	/**< packets rx at 2Mbps */
+	uint32  rx5mbps5;	/**< packets rx at 5.5Mbps */
+	uint32  rx6mbps;	/**< packets rx at 6Mbps */
+	uint32  rx9mbps;	/**< packets rx at 9Mbps */
+	uint32  rx11mbps;	/**< packets rx at 11Mbps */
+	uint32  rx12mbps;	/**< packets rx at 12Mbps */
+	uint32  rx18mbps;	/**< packets rx at 18Mbps */
+	uint32  rx24mbps;	/**< packets rx at 24Mbps */
+	uint32  rx36mbps;	/**< packets rx at 36Mbps */
+	uint32  rx48mbps;	/**< packets rx at 48Mbps */
+	uint32  rx54mbps;	/**< packets rx at 54Mbps */
+	uint32  rx108mbps;	/**< packets rx at 108mbps */
+	uint32  rx162mbps;	/**< packets rx at 162mbps */
+	uint32  rx216mbps;	/**< packets rx at 216 mbps */
+	uint32  rx270mbps;	/**< packets rx at 270 mbps */
+	uint32  rx324mbps;	/**< packets rx at 324 mbps */
+	uint32  rx378mbps;	/**< packets rx at 378 mbps */
+	uint32  rx432mbps;	/**< packets rx at 432 mbps */
+	uint32  rx486mbps;	/**< packets rx at 486 mbps */
+	uint32  rx540mbps;	/**< packets rx at 540 mbps */
+
+	/* pkteng rx frame stats */
+	uint32	pktengrxducast; /**< unicast frames rxed by the pkteng code */
+	uint32	pktengrxdmcast; /**< multicast frames rxed by the pkteng code */
+
+	uint32	rfdisable;	/**< count of radio disables */
+	uint32	bphy_rxcrsglitch;	/**< PHY count of bphy glitches */
+	uint32  bphy_badplcp;
+
+	uint32	txexptime;	/**< Tx frames suppressed due to timer expiration */
+
+	uint32	txmpdu_sgi;	/**< count for sgi transmit */
+	uint32	rxmpdu_sgi;	/**< count for sgi received */
+	uint32	txmpdu_stbc;	/**< count for stbc transmit */
+	uint32	rxmpdu_stbc;	/**< count for stbc received */
+
+	uint32	rxundec_mcst;	/**< dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32	tkipmicfaill_mcst;	/**< TKIPLocalMICFailures */
+	uint32	tkipcntrmsr_mcst;	/**< TKIPCounterMeasuresInvoked */
+	uint32	tkipreplay_mcst;	/**< TKIPReplays */
+	uint32	ccmpfmterr_mcst;	/**< CCMPFormatErrors */
+	uint32	ccmpreplay_mcst;	/**< CCMPReplays */
+	uint32	ccmpundec_mcst;	/**< CCMPDecryptErrors */
+	uint32	fourwayfail_mcst;	/**< FourWayHandshakeFailures */
+	uint32	wepundec_mcst;	/**< dot11WEPUndecryptableCount */
+	uint32	wepicverr_mcst;	/**< dot11WEPICVErrorCount */
+	uint32	decsuccess_mcst;	/**< DecryptSuccessCount */
+	uint32	tkipicverr_mcst;	/**< TKIPICVErrorCount */
+	uint32	wepexcluded_mcst;	/**< dot11WEPExcludedCount */
+
+	uint32	dma_hang;	/**< count for dma hang */
+	uint32	reinit;		/**< count for reinit */
+
+	uint32  pstatxucast;	/**< count of ucast frames xmitted on all psta assoc */
+	uint32  pstatxnoassoc;	/**< count of txnoassoc frames xmitted on all psta assoc */
+	uint32  pstarxucast;	/**< count of ucast frames received on all psta assoc */
+	uint32  pstarxbcmc;	/**< count of bcmc frames received on all psta */
+	uint32  pstatxbcmc;	/**< count of bcmc frames transmitted on all psta */
+
+	uint32  cso_passthrough; /**< hw cso required but passthrough */
+	uint32	cso_normal;	/**< hw cso hdr for normal process */
+	uint32	chained;	/**< number of frames chained */
+	uint32	chainedsz1;	/**< number of chain size 1 frames */
+	uint32	unchained;	/**< number of frames not chained */
+	uint32	maxchainsz;	/**< max chain size so far */
+	uint32	currchainsz;	/**< current chain size */
+	uint32	rxdrop20s;	/**< drop secondary cnt */
+	uint32	pciereset;	/**< Secondary Bus Reset issued by driver */
+	uint32	cfgrestore;	/**< configspace restore by driver */
+	uint32	reinitreason[NREINITREASONCOUNT]; /**< reinitreason counters; 0: Unknown reason */
+	uint32  rxrtry;		/**< num of received packets with retry bit on */
+	uint32	txmpdu;		/**< macstat cnt only valid in ver 11. number of MPDUs txed.  */
+	uint32	rxnodelim;	/**< macstat cnt only valid in ver 11.
+				 * number of occasions that no valid delimiter is detected
+				 * by ampdu parser.
+				 */
+	uint32  rxmpdu_mu;      /**< Number of MU MPDUs received */
+
+	/* detailed control/management frames */
+	uint32	txbar;		/**< Number of TX BAR */
+	uint32	rxbar;		/**< Number of RX BAR */
+	uint32	txpspoll;	/**< Number of TX PS-poll */
+	uint32	rxpspoll;	/**< Number of RX PS-poll */
+	uint32	txnull;		/**< Number of TX NULL_DATA */
+	uint32	rxnull;		/**< Number of RX NULL_DATA */
+	uint32	txqosnull;	/**< Number of TX NULL_QoSDATA */
+	uint32	rxqosnull;	/**< Number of RX NULL_QoSDATA */
+	uint32	txassocreq;	/**< Number of TX ASSOC request */
+	uint32	rxassocreq;	/**< Number of RX ASSOC request */
+	uint32	txreassocreq;	/**< Number of TX REASSOC request */
+	uint32	rxreassocreq;	/**< Number of RX REASSOC request */
+	uint32	txdisassoc;	/**< Number of TX DISASSOC */
+	uint32	rxdisassoc;	/**< Number of RX DISASSOC */
+	uint32	txassocrsp;	/**< Number of TX ASSOC response */
+	uint32	rxassocrsp;	/**< Number of RX ASSOC response */
+	uint32	txreassocrsp;	/**< Number of TX REASSOC response */
+	uint32	rxreassocrsp;	/**< Number of RX REASSOC response */
+	uint32	txauth;		/**< Number of TX AUTH */
+	uint32	rxauth;		/**< Number of RX AUTH */
+	uint32	txdeauth;	/**< Number of TX DEAUTH */
+	uint32	rxdeauth;	/**< Number of RX DEAUTH */
+	uint32	txprobereq;	/**< Number of TX probe request */
+	uint32	rxprobereq;	/**< Number of RX probe request */
+	uint32	txprobersp;	/**< Number of TX probe response */
+	uint32	rxprobersp;	/**< Number of RX probe response */
+	uint32	txaction;	/**< Number of TX action frame */
+	uint32	rxaction;	/**< Number of RX action frame */
+	uint32  ampdu_wds;      /**< Number of AMPDU watchdogs */
+	uint32  txlost;         /**< Number of lost packets reported in txs */
+	uint32  txdatamcast;	/**< Number of TX multicast data packets */
+	uint32  txdatabcast;	/**< Number of TX broadcast data packets */
+
+} wl_cnt_ver_11_t;
+
+typedef struct {
+	uint16	version;	/* see definition of WL_CNT_T_VERSION */
+	uint16	length;		/* length of entire structure */
+
+	/* transmit stat counters */
+	uint32	txframe;	/* tx data frames */
+	uint32	txbyte;		/* tx data bytes */
+	uint32	txretrans;	/* tx mac retransmits */
+	uint32	txerror;	/* tx data errors (derived: sum of others) */
+	uint32	txctl;		/* tx management frames */
+	uint32	txprshort;	/* tx short preamble frames */
+	uint32	txserr;		/* tx status errors */
+	uint32	txnobuf;	/* tx out of buffers errors */
+	uint32	txnoassoc;	/* tx discard because we're not associated */
+	uint32	txrunt;		/* tx runt frames */
+	uint32	txchit;		/* tx header cache hit (fastpath) */
+	uint32	txcmiss;	/* tx header cache miss (slowpath) */
+
+	/* transmit chip error counters */
+	uint32	txuflo;		/* tx fifo underflows */
+	uint32	txphyerr;	/* tx phy errors (indicated in tx status) */
+	uint32	txphycrs;
+
+	/* receive stat counters */
+	uint32	rxframe;	/* rx data frames */
+	uint32	rxbyte;		/* rx data bytes */
+	uint32	rxerror;	/* rx data errors (derived: sum of others) */
+	uint32	rxctl;		/* rx management frames */
+	uint32	rxnobuf;	/* rx out of buffers errors */
+	uint32	rxnondata;	/* rx non data frames in the data channel errors */
+	uint32	rxbadds;	/* rx bad DS errors */
+	uint32	rxbadcm;	/* rx bad control or management frames */
+	uint32	rxfragerr;	/* rx fragmentation errors */
+	uint32	rxrunt;		/* rx runt frames */
+	uint32	rxgiant;	/* rx giant frames */
+	uint32	rxnoscb;	/* rx no scb error */
+	uint32	rxbadproto;	/* rx invalid frames */
+	uint32	rxbadsrcmac;	/* rx frames with Invalid Src Mac */
+	uint32	rxbadda;	/* rx frames tossed for invalid da */
+	uint32	rxfilter;	/* rx frames filtered out */
+
+	/* receive chip error counters */
+	uint32	rxoflo;		/* rx fifo overflow errors */
+	uint32	rxuflo[NFIFO];	/* rx dma descriptor underflow errors */
+
+	uint32	d11cnt_txrts_off;	/* d11cnt txrts value when reset d11cnt */
+	uint32	d11cnt_rxcrc_off;	/* d11cnt rxcrc value when reset d11cnt */
+	uint32	d11cnt_txnocts_off;	/* d11cnt txnocts value when reset d11cnt */
+
+	/* misc counters */
+	uint32	dmade;		/* tx/rx dma descriptor errors */
+	uint32	dmada;		/* tx/rx dma data errors */
+	uint32	dmape;		/* tx/rx dma descriptor protocol errors */
+	uint32	reset;		/* reset count */
+	uint32	tbtt;		/* cnts the TBTT int's */
+	uint32	txdmawar;
+	uint32	pkt_callback_reg_fail;	/* callbacks register failure */
+
+	/* MAC counters: 32-bit version of d11.h's macstat_t */
+	uint32	txallfrm;	/* total number of frames sent, incl. Data, ACK, RTS, CTS,
+				 * Control Management (includes retransmissions)
+				 */
+	uint32	txrtsfrm;	/* number of RTS sent out by the MAC */
+	uint32	txctsfrm;	/* number of CTS sent out by the MAC */
+	uint32	txackfrm;	/* number of ACK frames sent out */
+	uint32	txdnlfrm;	/* Not used */
+	uint32	txbcnfrm;	/* beacons transmitted */
+	uint32	txfunfl[8];	/* per-fifo tx underflows */
+	uint32	txtplunfl;	/* Template underflows (mac was too slow to transmit ACK/CTS
+				 * or BCN)
+				 */
+	uint32	txphyerror;	/* Transmit phy error, type of error is reported in tx-status for
+				 * driver enqueued frames
+				 */
+	uint32	rxfrmtoolong;	/* Received frame longer than legal limit (2346 bytes) */
+	uint32	rxfrmtooshrt;	/* Received frame did not contain enough bytes for its frame type */
+	uint32	rxinvmachdr;	/* Either the protocol version != 0 or frame type not
+				 * data/control/management
+				 */
+	uint32	rxbadfcs;	/* number of frames for which the CRC check failed in the MAC */
+	uint32	rxbadplcp;	/* parity check of the PLCP header failed */
+	uint32	rxcrsglitch;	/* PHY was able to correlate the preamble but not the header */
+	uint32	rxstrt;		/* Number of received frames with a good PLCP
+				 * (i.e. passing parity check)
+				 */
+	uint32	rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */
+	uint32	rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */
+	uint32	rxcfrmucast;	/* number of received CNTRL frames with good FCS and matching RA */
+	uint32	rxrtsucast;	/* number of unicast RTS addressed to the MAC (good FCS) */
+	uint32	rxctsucast;	/* number of unicast CTS addressed to the MAC (good FCS) */
+	uint32	rxackucast;	/* number of ucast ACKS received (good FCS) */
+	uint32	rxdfrmocast;	/* number of received DATA frames (good FCS and not matching RA) */
+	uint32	rxmfrmocast;	/* number of received MGMT frames (good FCS and not matching RA) */
+	uint32	rxcfrmocast;	/* number of received CNTRL frame (good FCS and not matching RA) */
+	uint32	rxrtsocast;	/* number of received RTS not addressed to the MAC */
+	uint32	rxctsocast;	/* number of received CTS not addressed to the MAC */
+	uint32	rxdfrmmcast;	/* number of RX Data multicast frames received by the MAC */
+	uint32	rxmfrmmcast;	/* number of RX Management multicast frames received by the MAC */
+	uint32	rxcfrmmcast;	/* number of RX Control multicast frames received by the MAC
+				 * (unlikely to see these)
+				 */
+	uint32	rxbeaconmbss;	/* beacons received from member of BSS */
+	uint32	rxdfrmucastobss; /* number of unicast frames addressed to the MAC from
+				  * other BSS (WDS FRAME)
+				  */
+	uint32	rxbeaconobss;	/* beacons received from other BSS */
+	uint32	rxrsptmout;	/* Number of response timeouts for transmitted frames
+				 * expecting a response
+				 */
+	uint32	bcntxcancl;	/* transmit beacons canceled due to receipt of beacon (IBSS) */
+	uint32	rxf0ovfl;	/* Number of receive fifo 0 overflows */
+	uint32	rxf1ovfl;	/* Number of receive fifo 1 overflows (obsolete) */
+	uint32	rxf2ovfl;	/* Number of receive fifo 2 overflows (obsolete) */
+	uint32	txsfovfl;	/* Number of transmit status fifo overflows (obsolete) */
+	uint32	pmqovfl;	/* Number of PMQ overflows */
+	uint32	rxcgprqfrm;	/* Number of received Probe requests that made it into
+				 * the PRQ fifo
+				 */
+	uint32	rxcgprsqovfl;	/* Rx Probe Request Que overflow in the AP */
+	uint32	txcgprsfail;	/* Tx Probe Response Fail. AP sent probe response but did
+				 * not get ACK
+				 */
+	uint32	txcgprssuc;	/* Tx Probe Response Success (ACK was received) */
+	uint32	prs_timeout;	/* Number of probe requests that were dropped from the PRQ
+				 * fifo because a probe response could not be sent out within
+				 * the time limit defined in M_PRS_MAXTIME
+				 */
+	uint32	rxnack;		/* obsolete */
+	uint32	frmscons;	/* obsolete */
+	uint32	txnack;		/* obsolete */
+	uint32	txglitch_nack;	/* obsolete */
+	uint32	txburst;	/* obsolete */
+
+	/* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
+	uint32	txfrag;		/* dot11TransmittedFragmentCount */
+	uint32	txmulti;	/* dot11MulticastTransmittedFrameCount */
+	uint32	txfail;		/* dot11FailedCount */
+	uint32	txretry;	/* dot11RetryCount */
+	uint32	txretrie;	/* dot11MultipleRetryCount */
+	uint32	rxdup;		/* dot11FrameduplicateCount */
+	uint32	txrts;		/* dot11RTSSuccessCount */
+	uint32	txnocts;	/* dot11RTSFailureCount */
+	uint32	txnoack;	/* dot11ACKFailureCount */
+	uint32	rxfrag;		/* dot11ReceivedFragmentCount */
+	uint32	rxmulti;	/* dot11MulticastReceivedFrameCount */
+	uint32	rxcrc;		/* dot11FCSErrorCount */
+	uint32	txfrmsnt;	/* dot11TransmittedFrameCount (bogus MIB?) */
+	uint32	rxundec;	/* dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32	tkipmicfaill;	/* TKIPLocalMICFailures */
+	uint32	tkipcntrmsr;	/* TKIPCounterMeasuresInvoked */
+	uint32	tkipreplay;	/* TKIPReplays */
+	uint32	ccmpfmterr;	/* CCMPFormatErrors */
+	uint32	ccmpreplay;	/* CCMPReplays */
+	uint32	ccmpundec;	/* CCMPDecryptErrors */
+	uint32	fourwayfail;	/* FourWayHandshakeFailures */
+	uint32	wepundec;	/* dot11WEPUndecryptableCount */
+	uint32	wepicverr;	/* dot11WEPICVErrorCount */
+	uint32	decsuccess;	/* DecryptSuccessCount */
+	uint32	tkipicverr;	/* TKIPICVErrorCount */
+	uint32	wepexcluded;	/* dot11WEPExcludedCount */
+
+	uint32	txchanrej;	/* Tx frames suppressed due to channel rejection */
+	uint32	psmwds;		/* Count PSM watchdogs */
+	uint32	phywatchdog;	/**< Count Phy watchdogs (triggered by ucode) */
+
+	/* MBSS counters, AP only */
+	uint32	prq_entries_handled;	/* PRQ entries read in */
+	uint32	prq_undirected_entries;	/*    which were bcast bss & ssid */
+	uint32	prq_bad_entries;	/*    which could not be translated to info */
+	uint32	atim_suppress_count;	/* TX suppressions on ATIM fifo */
+	uint32	bcn_template_not_ready;	/* Template marked in use on send bcn ... */
+	uint32	bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */
+	uint32	late_tbtt_dpc;	/* TBTT DPC did not happen in time */
+
+	/* per-rate receive stat counters */
+	uint32  rx1mbps;	/* packets rx at 1Mbps */
+	uint32  rx2mbps;	/* packets rx at 2Mbps */
+	uint32  rx5mbps5;	/* packets rx at 5.5Mbps */
+	uint32  rx6mbps;	/* packets rx at 6Mbps */
+	uint32  rx9mbps;	/* packets rx at 9Mbps */
+	uint32  rx11mbps;	/* packets rx at 11Mbps */
+	uint32  rx12mbps;	/* packets rx at 12Mbps */
+	uint32  rx18mbps;	/* packets rx at 18Mbps */
+	uint32  rx24mbps;	/* packets rx at 24Mbps */
+	uint32  rx36mbps;	/* packets rx at 36Mbps */
+	uint32  rx48mbps;	/* packets rx at 48Mbps */
+	uint32  rx54mbps;	/* packets rx at 54Mbps */
+	uint32  rx108mbps;	/* packets rx at 108mbps */
+	uint32  rx162mbps;	/* packets rx at 162mbps */
+	uint32  rx216mbps;	/* packets rx at 216 mbps */
+	uint32  rx270mbps;	/* packets rx at 270 mbps */
+	uint32  rx324mbps;	/* packets rx at 324 mbps */
+	uint32  rx378mbps;	/* packets rx at 378 mbps */
+	uint32  rx432mbps;	/* packets rx at 432 mbps */
+	uint32  rx486mbps;	/* packets rx at 486 mbps */
+	uint32  rx540mbps;	/* packets rx at 540 mbps */
+
+	/* pkteng rx frame stats */
+	uint32	pktengrxducast; /* unicast frames rxed by the pkteng code */
+	uint32	pktengrxdmcast; /* multicast frames rxed by the pkteng code */
+
+	uint32	rfdisable;	/* count of radio disables */
+	uint32	bphy_rxcrsglitch;	/* PHY count of bphy glitches */
+
+	uint32	txexptime;	/* Tx frames suppressed due to timer expiration */
+
+	uint32	txmpdu_sgi;	/* count for sgi transmit */
+	uint32	rxmpdu_sgi;	/* count for sgi received */
+	uint32	txmpdu_stbc;	/* count for stbc transmit */
+	uint32	rxmpdu_stbc;	/* count for stbc received */
+
+	uint32	rxundec_mcst;	/* dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32	tkipmicfaill_mcst;	/* TKIPLocalMICFailures */
+	uint32	tkipcntrmsr_mcst;	/* TKIPCounterMeasuresInvoked */
+	uint32	tkipreplay_mcst;	/* TKIPReplays */
+	uint32	ccmpfmterr_mcst;	/* CCMPFormatErrors */
+	uint32	ccmpreplay_mcst;	/* CCMPReplays */
+	uint32	ccmpundec_mcst;	/* CCMPDecryptErrors */
+	uint32	fourwayfail_mcst;	/* FourWayHandshakeFailures */
+	uint32	wepundec_mcst;	/* dot11WEPUndecryptableCount */
+	uint32	wepicverr_mcst;	/* dot11WEPICVErrorCount */
+	uint32	decsuccess_mcst;	/* DecryptSuccessCount */
+	uint32	tkipicverr_mcst;	/* TKIPICVErrorCount */
+	uint32	wepexcluded_mcst;	/* dot11WEPExcludedCount */
+
+	uint32	dma_hang;	/* count for stbc received */
+} wl_cnt_ver_7_t;
+
+typedef struct {
+	uint16  version;    /**< see definition of WL_CNT_T_VERSION */
+	uint16  length;     /**< length of entire structure */
+
+	/* transmit stat counters */
+	uint32  txframe;    /**< tx data frames */
+	uint32  txbyte;     /**< tx data bytes */
+	uint32  txretrans;  /**< tx mac retransmits */
+	uint32  txerror;    /**< tx data errors (derived: sum of others) */
+	uint32  txctl;      /**< tx management frames */
+	uint32  txprshort;  /**< tx short preamble frames */
+	uint32  txserr;     /**< tx status errors */
+	uint32  txnobuf;    /**< tx out of buffers errors */
+	uint32  txnoassoc;  /**< tx discard because we're not associated */
+	uint32  txrunt;     /**< tx runt frames */
+	uint32  txchit;     /**< tx header cache hit (fastpath) */
+	uint32  txcmiss;    /**< tx header cache miss (slowpath) */
+
+	/* transmit chip error counters */
+	uint32  txuflo;     /**< tx fifo underflows */
+	uint32  txphyerr;   /**< tx phy errors (indicated in tx status) */
+	uint32  txphycrs;
+
+	/* receive stat counters */
+	uint32  rxframe;    /**< rx data frames */
+	uint32  rxbyte;     /**< rx data bytes */
+	uint32  rxerror;    /**< rx data errors (derived: sum of others) */
+	uint32  rxctl;      /**< rx management frames */
+	uint32  rxnobuf;    /**< rx out of buffers errors */
+	uint32  rxnondata;  /**< rx non data frames in the data channel errors */
+	uint32  rxbadds;    /**< rx bad DS errors */
+	uint32  rxbadcm;    /**< rx bad control or management frames */
+	uint32  rxfragerr;  /**< rx fragmentation errors */
+	uint32  rxrunt;     /**< rx runt frames */
+	uint32  rxgiant;    /**< rx giant frames */
+	uint32  rxnoscb;    /**< rx no scb error */
+	uint32  rxbadproto; /**< rx invalid frames */
+	uint32  rxbadsrcmac;    /**< rx frames with Invalid Src Mac */
+	uint32  rxbadda;    /**< rx frames tossed for invalid da */
+	uint32  rxfilter;   /**< rx frames filtered out */
+
+	/* receive chip error counters */
+	uint32  rxoflo;     /**< rx fifo overflow errors */
+	uint32  rxuflo[NFIFO];  /**< rx dma descriptor underflow errors */
+
+	uint32  d11cnt_txrts_off;   /**< d11cnt txrts value when reset d11cnt */
+	uint32  d11cnt_rxcrc_off;   /**< d11cnt rxcrc value when reset d11cnt */
+	uint32  d11cnt_txnocts_off; /**< d11cnt txnocts value when reset d11cnt */
+
+	/* misc counters */
+	uint32  dmade;      /**< tx/rx dma descriptor errors */
+	uint32  dmada;      /**< tx/rx dma data errors */
+	uint32  dmape;      /**< tx/rx dma descriptor protocol errors */
+	uint32  reset;      /**< reset count */
+	uint32  tbtt;       /**< cnts the TBTT int's */
+	uint32  txdmawar;
+	uint32  pkt_callback_reg_fail;  /**< callbacks register failure */
+
+	/* MAC counters: 32-bit version of d11.h's macstat_t */
+	uint32  txallfrm;   /**< total number of frames sent, incl. Data, ACK, RTS, CTS,
+			     * Control Management (includes retransmissions)
+			     */
+	uint32  txrtsfrm;   /**< number of RTS sent out by the MAC */
+	uint32  txctsfrm;   /**< number of CTS sent out by the MAC */
+	uint32  txackfrm;   /**< number of ACK frames sent out */
+	uint32  txdnlfrm;   /**< Not used */
+	uint32  txbcnfrm;   /**< beacons transmitted */
+	uint32  txfunfl[6]; /**< per-fifo tx underflows */
+	uint32	rxtoolate;	/**< receive too late */
+	uint32  txfbw;	    /**< transmit at fallback bw (dynamic bw) */
+	uint32  txtplunfl;  /**< Template underflows (mac was too slow to transmit ACK/CTS
+			     * or BCN)
+			     */
+	uint32  txphyerror; /**< Transmit phy error, type of error is reported in tx-status for
+			     * driver enqueued frames
+			     */
+	uint32  rxfrmtoolong;   /**< Received frame longer than legal limit (2346 bytes) */
+	uint32  rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */
+	uint32  rxinvmachdr;    /**< Either the protocol version != 0 or frame type not
+				 * data/control/management
+			   */
+	uint32  rxbadfcs;   /**< number of frames for which the CRC check failed in the MAC */
+	uint32  rxbadplcp;  /**< parity check of the PLCP header failed */
+	uint32  rxcrsglitch;    /**< PHY was able to correlate the preamble but not the header */
+	uint32  rxstrt;     /**< Number of received frames with a good PLCP
+			     * (i.e. passing parity check)
+			     */
+	uint32  rxdfrmucastmbss; /**< # of received DATA frames with good FCS and matching RA */
+	uint32  rxmfrmucastmbss; /**< # of received mgmt frames with good FCS and matching RA */
+	uint32  rxcfrmucast;     /**< # of received CNTRL frames with good FCS and matching RA */
+	uint32  rxrtsucast; /**< number of unicast RTS addressed to the MAC (good FCS) */
+	uint32  rxctsucast; /**< number of unicast CTS addressed to the MAC (good FCS) */
+	uint32  rxackucast; /**< number of ucast ACKS received (good FCS) */
+	uint32  rxdfrmocast;    /**< # of received DATA frames (good FCS and not matching RA) */
+	uint32  rxmfrmocast;    /**< # of received MGMT frames (good FCS and not matching RA) */
+	uint32  rxcfrmocast;    /**< # of received CNTRL frame (good FCS and not matching RA) */
+	uint32  rxrtsocast; /**< number of received RTS not addressed to the MAC */
+	uint32  rxctsocast; /**< number of received CTS not addressed to the MAC */
+	uint32  rxdfrmmcast;    /**< number of RX Data multicast frames received by the MAC */
+	uint32  rxmfrmmcast;    /**< number of RX Management multicast frames received by the MAC */
+	uint32  rxcfrmmcast;    /**< number of RX Control multicast frames received by the MAC
+				 * (unlikely to see these)
+				 */
+	uint32  rxbeaconmbss;   /**< beacons received from member of BSS */
+	uint32  rxdfrmucastobss; /**< number of unicast frames addressed to the MAC from
+				  * other BSS (WDS FRAME)
+				  */
+	uint32  rxbeaconobss;   /**< beacons received from other BSS */
+	uint32  rxrsptmout; /**< Number of response timeouts for transmitted frames
+			     * expecting a response
+			     */
+	uint32  bcntxcancl; /**< transmit beacons canceled due to receipt of beacon (IBSS) */
+	uint32  rxf0ovfl;   /**< Number of receive fifo 0 overflows */
+	uint32  rxf1ovfl;   /**< Number of receive fifo 1 overflows (obsolete) */
+	uint32  rxf2ovfl;   /**< Number of receive fifo 2 overflows (obsolete) */
+	uint32  txsfovfl;   /**< Number of transmit status fifo overflows (obsolete) */
+	uint32  pmqovfl;    /**< Number of PMQ overflows */
+	uint32  rxcgprqfrm; /**< Number of received Probe requests that made it into
+			     * the PRQ fifo
+			     */
+	uint32  rxcgprsqovfl;   /**< Rx Probe Request Que overflow in the AP */
+	uint32  txcgprsfail;    /**< Tx Probe Response Fail. AP sent probe response but did
+				 * not get ACK
+				 */
+	uint32  txcgprssuc; /**< Tx Probe Response Success (ACK was received) */
+	uint32  prs_timeout;    /**< Number of probe requests that were dropped from the PRQ
+				 * fifo because a probe response could not be sent out within
+				 * the time limit defined in M_PRS_MAXTIME
+				 */
+	uint32  rxnack;
+	uint32  frmscons;
+	uint32  txnack;		/**< obsolete */
+	uint32	rxback;		/**< blockack rxcnt */
+	uint32	txback;		/**< blockack txcnt */
+
+	/* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */
+	uint32  txfrag;     /**< dot11TransmittedFragmentCount */
+	uint32  txmulti;    /**< dot11MulticastTransmittedFrameCount */
+	uint32  txfail;     /**< dot11FailedCount */
+	uint32  txretry;    /**< dot11RetryCount */
+	uint32  txretrie;   /**< dot11MultipleRetryCount */
+	uint32  rxdup;      /**< dot11FrameduplicateCount */
+	uint32  txrts;      /**< dot11RTSSuccessCount */
+	uint32  txnocts;    /**< dot11RTSFailureCount */
+	uint32  txnoack;    /**< dot11ACKFailureCount */
+	uint32  rxfrag;     /**< dot11ReceivedFragmentCount */
+	uint32  rxmulti;    /**< dot11MulticastReceivedFrameCount */
+	uint32  rxcrc;      /**< dot11FCSErrorCount */
+	uint32  txfrmsnt;   /**< dot11TransmittedFrameCount (bogus MIB?) */
+	uint32  rxundec;    /**< dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32  tkipmicfaill;   /**< TKIPLocalMICFailures */
+	uint32  tkipcntrmsr;    /**< TKIPCounterMeasuresInvoked */
+	uint32  tkipreplay; /**< TKIPReplays */
+	uint32  ccmpfmterr; /**< CCMPFormatErrors */
+	uint32  ccmpreplay; /**< CCMPReplays */
+	uint32  ccmpundec;  /**< CCMPDecryptErrors */
+	uint32  fourwayfail;    /**< FourWayHandshakeFailures */
+	uint32  wepundec;   /**< dot11WEPUndecryptableCount */
+	uint32  wepicverr;  /**< dot11WEPICVErrorCount */
+	uint32  decsuccess; /**< DecryptSuccessCount */
+	uint32  tkipicverr; /**< TKIPICVErrorCount */
+	uint32  wepexcluded;    /**< dot11WEPExcludedCount */
+
+	uint32  rxundec_mcst;   /**< dot11WEPUndecryptableCount */
+
+	/* WPA2 counters (see rxundec for DecryptFailureCount) */
+	uint32  tkipmicfaill_mcst;  /**< TKIPLocalMICFailures */
+	uint32  tkipcntrmsr_mcst;   /**< TKIPCounterMeasuresInvoked */
+	uint32  tkipreplay_mcst;    /**< TKIPReplays */
+	uint32  ccmpfmterr_mcst;    /**< CCMPFormatErrors */
+	uint32  ccmpreplay_mcst;    /**< CCMPReplays */
+	uint32  ccmpundec_mcst; /**< CCMPDecryptErrors */
+	uint32  fourwayfail_mcst;   /**< FourWayHandshakeFailures */
+	uint32  wepundec_mcst;  /**< dot11WEPUndecryptableCount */
+	uint32  wepicverr_mcst; /**< dot11WEPICVErrorCount */
+	uint32  decsuccess_mcst;    /**< DecryptSuccessCount */
+	uint32  tkipicverr_mcst;    /**< TKIPICVErrorCount */
+	uint32  wepexcluded_mcst;   /**< dot11WEPExcludedCount */
+
+	uint32  txchanrej;  /**< Tx frames suppressed due to channel rejection */
+	uint32  txexptime;  /**< Tx frames suppressed due to timer expiration */
+	uint32  psmwds;     /**< Count PSM watchdogs */
+	uint32  phywatchdog;    /**< Count Phy watchdogs (triggered by ucode) */
+
+	/* MBSS counters, AP only */
+	uint32  prq_entries_handled;    /**< PRQ entries read in */
+	uint32  prq_undirected_entries; /**<    which were bcast bss & ssid */
+	uint32  prq_bad_entries;    /**<    which could not be translated to info */
+	uint32  atim_suppress_count;    /**< TX suppressions on ATIM fifo */
+	uint32  bcn_template_not_ready; /**< Template marked in use on send bcn ... */
+	uint32  bcn_template_not_ready_done; /**< ...but "DMA done" interrupt rcvd */
+	uint32  late_tbtt_dpc;  /**< TBTT DPC did not happen in time */
+
+	/* per-rate receive stat counters */
+	uint32  rx1mbps;    /**< packets rx at 1Mbps */
+	uint32  rx2mbps;    /**< packets rx at 2Mbps */
+	uint32  rx5mbps5;   /**< packets rx at 5.5Mbps */
+	uint32  rx6mbps;    /**< packets rx at 6Mbps */
+	uint32  rx9mbps;    /**< packets rx at 9Mbps */
+	uint32  rx11mbps;   /**< packets rx at 11Mbps */
+	uint32  rx12mbps;   /**< packets rx at 12Mbps */
+	uint32  rx18mbps;   /**< packets rx at 18Mbps */
+	uint32  rx24mbps;   /**< packets rx at 24Mbps */
+	uint32  rx36mbps;   /**< packets rx at 36Mbps */
+	uint32  rx48mbps;   /**< packets rx at 48Mbps */
+	uint32  rx54mbps;   /**< packets rx at 54Mbps */
+	uint32  rx108mbps;  /**< packets rx at 108mbps */
+	uint32  rx162mbps;  /**< packets rx at 162mbps */
+	uint32  rx216mbps;  /**< packets rx at 216 mbps */
+	uint32  rx270mbps;  /**< packets rx at 270 mbps */
+	uint32  rx324mbps;  /**< packets rx at 324 mbps */
+	uint32  rx378mbps;  /**< packets rx at 378 mbps */
+	uint32  rx432mbps;  /**< packets rx at 432 mbps */
+	uint32  rx486mbps;  /**< packets rx at 486 mbps */
+	uint32  rx540mbps;  /**< packets rx at 540 mbps */
+
+	/* pkteng rx frame stats */
+	uint32  pktengrxducast; /**< unicast frames rxed by the pkteng code */
+	uint32  pktengrxdmcast; /**< multicast frames rxed by the pkteng code */
+
+	uint32  rfdisable;  /**< count of radio disables */
+	uint32  bphy_rxcrsglitch;   /**< PHY count of bphy glitches */
+	uint32  bphy_badplcp;
+
+	uint32  txmpdu_sgi; /**< count for sgi transmit */
+	uint32  rxmpdu_sgi; /**< count for sgi received */
+	uint32  txmpdu_stbc;    /**< count for stbc transmit */
+	uint32  rxmpdu_stbc;    /**< count for stbc received */
+
+	uint32	rxdrop20s;	/**< drop secondary cnt */
+} wl_cnt_ver_6_t;
+
+#define	WL_DELTA_STATS_T_VERSION	2	/**< current version of wl_delta_stats_t struct */
+
+typedef struct {
+	uint16 version;     /**< see definition of WL_DELTA_STATS_T_VERSION */
+	uint16 length;      /**< length of entire structure */
+
+	/* transmit stat counters */
+	uint32 txframe;     /**< tx data frames */
+	uint32 txbyte;      /**< tx data bytes */
+	uint32 txretrans;   /**< tx mac retransmits */
+	uint32 txfail;      /**< tx failures */
+
+	/* receive stat counters */
+	uint32 rxframe;     /**< rx data frames */
+	uint32 rxbyte;      /**< rx data bytes */
+
+	/* per-rate receive stat counters */
+	uint32  rx1mbps;	/**< packets rx at 1Mbps */
+	uint32  rx2mbps;	/**< packets rx at 2Mbps */
+	uint32  rx5mbps5;	/**< packets rx at 5.5Mbps */
+	uint32  rx6mbps;	/**< packets rx at 6Mbps */
+	uint32  rx9mbps;	/**< packets rx at 9Mbps */
+	uint32  rx11mbps;	/**< packets rx at 11Mbps */
+	uint32  rx12mbps;	/**< packets rx at 12Mbps */
+	uint32  rx18mbps;	/**< packets rx at 18Mbps */
+	uint32  rx24mbps;	/**< packets rx at 24Mbps */
+	uint32  rx36mbps;	/**< packets rx at 36Mbps */
+	uint32  rx48mbps;	/**< packets rx at 48Mbps */
+	uint32  rx54mbps;	/**< packets rx at 54Mbps */
+	uint32  rx108mbps;	/**< packets rx at 108mbps */
+	uint32  rx162mbps;	/**< packets rx at 162mbps */
+	uint32  rx216mbps;	/**< packets rx at 216 mbps */
+	uint32  rx270mbps;	/**< packets rx at 270 mbps */
+	uint32  rx324mbps;	/**< packets rx at 324 mbps */
+	uint32  rx378mbps;	/**< packets rx at 378 mbps */
+	uint32  rx432mbps;	/**< packets rx at 432 mbps */
+	uint32  rx486mbps;	/**< packets rx at 486 mbps */
+	uint32  rx540mbps;	/**< packets rx at 540 mbps */
+
+	/* phy stats */
+	uint32 rxbadplcp;
+	uint32 rxcrsglitch;
+	uint32 bphy_rxcrsglitch;
+	uint32 bphy_badplcp;
+
+} wl_delta_stats_t;
+
+/* Partial statistics counter report */
+#define WL_CNT_CTL_MGT_FRAMES	0
+
+typedef struct {
+	uint16	type;
+	uint16	len;
+
+	/* detailed control/management frames */
+	uint32	txnull;
+	uint32	rxnull;
+	uint32	txqosnull;
+	uint32	rxqosnull;
+	uint32	txassocreq;
+	uint32	rxassocreq;
+	uint32	txreassocreq;
+	uint32	rxreassocreq;
+	uint32	txdisassoc;
+	uint32	rxdisassoc;
+	uint32	txassocrsp;
+	uint32	rxassocrsp;
+	uint32	txreassocrsp;
+	uint32	rxreassocrsp;
+	uint32	txauth;
+	uint32	rxauth;
+	uint32	txdeauth;
+	uint32	rxdeauth;
+	uint32	txprobereq;
+	uint32	rxprobereq;
+	uint32	txprobersp;
+	uint32	rxprobersp;
+	uint32	txaction;
+	uint32	rxaction;
+	uint32	txrts;
+	uint32	rxrts;
+	uint32	txcts;
+	uint32	rxcts;
+	uint32	txack;
+	uint32	rxack;
+	uint32	txbar;
+	uint32	rxbar;
+	uint32	txback;
+	uint32	rxback;
+	uint32	txpspoll;
+	uint32	rxpspoll;
+} wl_ctl_mgt_cnt_t;
+
+typedef struct {
+	uint32 packets;
+	uint32 bytes;
+} wl_traffic_stats_t;
+
+typedef struct {
+	uint16	version;	/**< see definition of WL_WME_CNT_VERSION */
+	uint16	length;		/**< length of entire structure */
+
+	wl_traffic_stats_t tx[AC_COUNT];	/**< Packets transmitted */
+	wl_traffic_stats_t tx_failed[AC_COUNT];	/**< Packets dropped or failed to transmit */
+	wl_traffic_stats_t rx[AC_COUNT];	/**< Packets received */
+	wl_traffic_stats_t rx_failed[AC_COUNT];	/**< Packets failed to receive */
+
+	wl_traffic_stats_t forward[AC_COUNT];	/**< Packets forwarded by AP */
+
+	wl_traffic_stats_t tx_expired[AC_COUNT]; /**< packets dropped due to lifetime expiry */
+
+} wl_wme_cnt_t;
+
+struct wl_msglevel2 {
+	uint32 low;
+	uint32 high;
+};
+
+#define WL_ICMP_IPV6_CFG_VERSION         1
+#define WL_ICMP_IPV6_CLEAR_ALL           (1 << 0)
+
+typedef struct wl_icmp_ipv6_cfg {
+	uint16 version;
+	uint16 length;
+	uint16 fixed_length;
+	uint16 flags;
+	uint32 num_ipv6;
+	/* num_ipv6 to follow */
+	struct ipv6_addr host_ipv6[];
+} wl_icmp_ipv6_cfg_t;
+
+#define WL_ICMP_CFG_IPV6_FIXED_LEN      OFFSETOF(wl_icmp_ipv6_cfg_t, host_ipv6)
+#define WL_ICMP_CFG_IPV6_LEN(count)    (WL_ICMP_CFG_IPV6_FIXED_LEN + \
+					((count) * sizeof(struct ipv6_addr)))
+
+typedef struct wl_mkeep_alive_pkt {
+	uint16	version; /* Version for mkeep_alive */
+	uint16	length; /* length of fixed parameters in the structure */
+	uint32	period_msec; /* high bit on means immediate send */
+	uint16	len_bytes;
+	uint8	keep_alive_id; /* 0 - 3 for N = 4 */
+	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
+#define WL_MKEEP_ALIVE_PERIOD_MASK  0x7FFFFFFF
+#define WL_MKEEP_ALIVE_IMMEDIATE    0x80000000
+
+/** TCP Keep-Alive conn struct */
+typedef struct wl_mtcpkeep_alive_conn_pkt {
+	struct ether_addr saddr;		/**< src mac address */
+	struct ether_addr daddr;		/**< dst mac address */
+	struct ipv4_addr sipaddr;		/**< source IP addr */
+	struct ipv4_addr dipaddr;		/**< dest IP addr */
+	uint16 sport;				/**< src port */
+	uint16 dport;				/**< dest port */
+	uint32 seq;				/**< seq number */
+	uint32 ack;				/**< ACK number */
+	uint16 tcpwin;				/**< TCP window */
+} wl_mtcpkeep_alive_conn_pkt_t;
+
+/** TCP Keep-Alive interval struct */
+typedef struct wl_mtcpkeep_alive_timers_pkt {
+	uint16 interval;		/**< interval timer */
+	uint16 retry_interval;		/**< retry_interval timer */
+	uint16 retry_count;		/**< retry_count */
+} wl_mtcpkeep_alive_timers_pkt_t;
+
+typedef struct wake_info {
+	uint32 wake_reason;
+	uint32 wake_info_len;		/**< size of packet */
+	uint8  packet[1];
+} wake_info_t;
+
+typedef struct wake_pkt {
+	uint32 wake_pkt_len;		/**< size of packet */
+	uint8  packet[1];
+} wake_pkt_t;
+
+
+#define WL_MTCPKEEP_ALIVE_VERSION		1
+
+#ifdef WLBA
+
+#define WLC_BA_CNT_VERSION  1   /**< current version of wlc_ba_cnt_t */
+
+/** block ack related stats */
+typedef struct wlc_ba_cnt {
+	uint16  version;    /**< WLC_BA_CNT_VERSION */
+	uint16  length;     /**< length of entire structure */
+
+	/* transmit stat counters */
+	uint32 txpdu;       /**< pdus sent */
+	uint32 txsdu;       /**< sdus sent */
+	uint32 txfc;        /**< tx side flow controlled packets */
+	uint32 txfci;       /**< tx side flow control initiated */
+	uint32 txretrans;   /**< retransmitted pdus */
+	uint32 txbatimer;   /**< ba resend due to timer */
+	uint32 txdrop;      /**< dropped packets */
+	uint32 txaddbareq;  /**< addba req sent */
+	uint32 txaddbaresp; /**< addba resp sent */
+	uint32 txdelba;     /**< delba sent */
+	uint32 txba;        /**< ba sent */
+	uint32 txbar;       /**< bar sent */
+	uint32 txpad[4];    /**< future */
+
+	/* receive side counters */
+	uint32 rxpdu;       /**< pdus recd */
+	uint32 rxqed;       /**< pdus buffered before sending up */
+	uint32 rxdup;       /**< duplicate pdus */
+	uint32 rxnobuf;     /**< pdus discarded due to no buf */
+	uint32 rxaddbareq;  /**< addba req recd */
+	uint32 rxaddbaresp; /**< addba resp recd */
+	uint32 rxdelba;     /**< delba recd */
+	uint32 rxba;        /**< ba recd */
+	uint32 rxbar;       /**< bar recd */
+	uint32 rxinvba;     /**< invalid ba recd */
+	uint32 rxbaholes;   /**< ba recd with holes */
+	uint32 rxunexp;     /**< unexpected packets */
+	uint32 rxpad[4];    /**< future */
+} wlc_ba_cnt_t;
+#endif /* WLBA */
+
+/** structure for per-tid ampdu control */
+struct ampdu_tid_control {
+	uint8 tid;			/* tid */
+	uint8 enable;			/* enable/disable */
+};
+
+/** struct for ampdu tx/rx aggregation control */
+struct ampdu_aggr {
+	int8 aggr_override;	/**< aggr overrided by dongle. Not to be set by host. */
+	uint16 conf_TID_bmap;	/**< bitmap of TIDs to configure */
+	uint16 enab_TID_bmap;	/**< enable/disable per TID */
+};
+
+/** structure for identifying ea/tid for sending addba/delba */
+struct ampdu_ea_tid {
+	struct ether_addr ea;		/**< Station address */
+	uint8 tid;			/**< tid */
+	uint8 initiator;	/**< 0 is recipient, 1 is originator */
+};
+
+/** structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */
+struct ampdu_retry_tid {
+	uint8 tid;	/**< tid */
+	uint8 retry;	/**< retry value */
+};
+
+#define BDD_FNAME_LEN       32  /**< Max length of friendly name */
+typedef struct bdd_fname {
+	uint8 len;          /**< length of friendly name */
+	uchar name[BDD_FNAME_LEN];  /**< friendly name */
+} bdd_fname_t;
+
+/* structure for addts arguments */
+/** For ioctls that take a list of TSPEC */
+struct tslist {
+	int32 count;			/**< number of tspecs */
+	struct tsinfo_arg tsinfo[1];	/**< variable length array of tsinfo */
+};
+
+#ifdef WLTDLS
+/**structure for tdls iovars */
+typedef struct tdls_iovar {
+	struct ether_addr ea;		/**< Station address */
+	uint8 mode;			/**< mode: depends on iovar */
+	chanspec_t chanspec;
+	uint32 pad;			/**< future */
+} tdls_iovar_t;
+
+#define TDLS_WFD_IE_SIZE		512
+/**structure for tdls wfd ie */
+typedef struct tdls_wfd_ie_iovar {
+	struct ether_addr ea;		/**< Station address */
+	uint8 mode;
+	uint16 length;
+	uint8 data[TDLS_WFD_IE_SIZE];
+} tdls_wfd_ie_iovar_t;
+#endif /* WLTDLS */
+
+/** structure for addts/delts arguments */
+typedef struct tspec_arg {
+	uint16 version;			/**< see definition of TSPEC_ARG_VERSION */
+	uint16 length;			/**< length of entire structure */
+	uint32 flag;			/**< bit field */
+	/* TSPEC Arguments */
+	struct tsinfo_arg tsinfo;	/**< TS Info bit field */
+	uint16 nom_msdu_size;		/**< (Nominal or fixed) MSDU Size (bytes) */
+	uint16 max_msdu_size;		/**< Maximum MSDU Size (bytes) */
+	uint32 min_srv_interval;		/**< Minimum Service Interval (us) */
+	uint32 max_srv_interval;		/**< Maximum Service Interval (us) */
+	uint32 inactivity_interval;	/**< Inactivity Interval (us) */
+	uint32 suspension_interval;	/**< Suspension Interval (us) */
+	uint32 srv_start_time;		/**< Service Start Time (us) */
+	uint32 min_data_rate;		/**< Minimum Data Rate (bps) */
+	uint32 mean_data_rate;		/**< Mean Data Rate (bps) */
+	uint32 peak_data_rate;		/**< Peak Data Rate (bps) */
+	uint32 max_burst_size;		/**< Maximum Burst Size (bytes) */
+	uint32 delay_bound;		/**< Delay Bound (us) */
+	uint32 min_phy_rate;		/**< Minimum PHY Rate (bps) */
+	uint16 surplus_bw;		/**< Surplus Bandwidth Allowance (range 1.0 to 8.0) */
+	uint16 medium_time;		/**< Medium Time (32 us/s periods) */
+	uint8 dialog_token;		/**< dialog token */
+} tspec_arg_t;
+
+/** tspec arg for desired station */
+typedef	struct tspec_per_sta_arg {
+	struct ether_addr ea;
+	struct tspec_arg ts;
+} tspec_per_sta_arg_t;
+
+/** structure for max bandwidth for each access category */
+typedef	struct wme_max_bandwidth {
+	uint32	ac[AC_COUNT];	/**< max bandwidth for each access category */
+} wme_max_bandwidth_t;
+
+#define WL_WME_MBW_PARAMS_IO_BYTES (sizeof(wme_max_bandwidth_t))
+
+/* current version of wl_tspec_arg_t struct */
+#define	TSPEC_ARG_VERSION		2	/**< current version of wl_tspec_arg_t struct */
+#define TSPEC_ARG_LENGTH		55	/**< argument length from tsinfo to medium_time */
+#define TSPEC_DEFAULT_DIALOG_TOKEN	42	/**< default dialog token */
+#define TSPEC_DEFAULT_SBW_FACTOR	0x3000	/**< default surplus bw */
+
+
+#define WL_WOWL_KEEPALIVE_MAX_PACKET_SIZE  80
+#define WLC_WOWL_MAX_KEEPALIVE	2
+
+/** Packet lifetime configuration per ac */
+typedef struct wl_lifetime {
+	uint32 ac;	        /**< access class */
+	uint32 lifetime;    /**< Packet lifetime value in ms */
+} wl_lifetime_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/** Management time configuration */
+typedef struct wl_lifetime_mg {
+	uint32 mgmt_bitmap;	/**< Mgmt subtype */
+	uint32 lifetime;    /**< Packet lifetime value in us */
+} wl_lifetime_mg_t;
+
+#if defined(BCMDBG) || defined(BCMDBG_DUMP) || defined(BCMDBG_PHYDUMP) || \
+	defined(TDLS_TESTBED) || defined(BCMDBG_AMPDU) || defined(BCMDBG_TXBF) || \
+	defined(BCMDBG_DUMP_RSSI) || defined(MCHAN_MINIDUMP)
+/* MAC Sample Capture related */
+#define	WL_MACCAPTR_DEFSTART_PTR	0xA00
+#define	WL_MACCAPTR_DEFSTOP_PTR		0xA3F
+#define	WL_MACCAPTR_DEFSZ		0x3F
+
+#define WL_MACCAPTR_DEF_MASK		0xFFFFFFFF
+
+typedef enum {
+	WL_MACCAPT_TRIG		= 0,
+	WL_MACCAPT_STORE	= 1,
+	WL_MACCAPT_TRANS	= 2,
+	WL_MACCAPT_MATCH	= 3
+} maccaptr_optn;
+
+typedef enum {
+	WL_MACCAPT_STRT	= 1,
+	WL_MACCAPT_STOP	= 2,
+	WL_MACCAPT_RST	= 3
+} maccaptr_cmd_t;
+
+/* MAC Sample Capture Set-up Paramters */
+typedef struct wl_maccapture_params {
+	uint8	gpio_sel;
+	uint8	la_mode;	/* TRUE: GPIO Out Enabled */
+	uint32	start_ptr;	/* Start address to store */
+	uint32	stop_ptr;	/* Stop address to store */
+	uint8	optn_bmp;	/* Options */
+	uint32	tr_mask;	/* Trigger Mask */
+	uint32	tr_val;		/* Trigger Value */
+	uint32	s_mask;		/* Store Mode Mask */
+	uint32	x_mask;		/* Trans. Mode Mask */
+	uint32	m_mask;		/* Match Mode Mask */
+	uint32	m_val;		/* Match Value */
+	maccaptr_cmd_t cmd;	/* Start / Stop */
+} wl_maccapture_params_t;
+#endif 
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/** Channel Switch Announcement param */
+typedef struct wl_chan_switch {
+	uint8 mode;		/**< value 0 or 1 */
+	uint8 count;		/**< count # of beacons before switching */
+	chanspec_t chspec;	/**< chanspec */
+	uint8 reg;		/**< regulatory class */
+	uint8 frame_type;		/**< csa frame type, unicast or broadcast */
+} wl_chan_switch_t;
+
+enum {
+	PFN_LIST_ORDER,
+	PFN_RSSI
+};
+
+enum {
+	DISABLE,
+	ENABLE
+};
+
+enum {
+	OFF_ADAPT,
+	SMART_ADAPT,
+	STRICT_ADAPT,
+	SLOW_ADAPT
+};
+
+#define SORT_CRITERIA_BIT		0
+#define AUTO_NET_SWITCH_BIT		1
+#define ENABLE_BKGRD_SCAN_BIT		2
+#define IMMEDIATE_SCAN_BIT		3
+#define	AUTO_CONNECT_BIT		4
+#define	ENABLE_BD_SCAN_BIT		5
+#define ENABLE_ADAPTSCAN_BIT		6
+#define IMMEDIATE_EVENT_BIT		8
+#define SUPPRESS_SSID_BIT		9
+#define ENABLE_NET_OFFLOAD_BIT		10
+/** report found/lost events for SSID and BSSID networks seperately */
+#define REPORT_SEPERATELY_BIT		11
+
+#define SORT_CRITERIA_MASK	0x0001
+#define AUTO_NET_SWITCH_MASK	0x0002
+#define ENABLE_BKGRD_SCAN_MASK	0x0004
+#define IMMEDIATE_SCAN_MASK	0x0008
+#define AUTO_CONNECT_MASK	0x0010
+
+#define ENABLE_BD_SCAN_MASK	0x0020
+#define ENABLE_ADAPTSCAN_MASK	0x00c0
+#define IMMEDIATE_EVENT_MASK	0x0100
+#define SUPPRESS_SSID_MASK	0x0200
+#define ENABLE_NET_OFFLOAD_MASK	0x0400
+/** report found/lost events for SSID and BSSID networks seperately */
+#define REPORT_SEPERATELY_MASK	0x0800
+
+#define PFN_VERSION			2
+
+#define PFN_COMPLETE			1
+#define PFN_INCOMPLETE			0
+
+#define DEFAULT_BESTN			2
+#define DEFAULT_MSCAN			0
+#define DEFAULT_REPEAT			10
+#define DEFAULT_EXP			2
+
+#define PFN_PARTIAL_SCAN_BIT		0
+#define PFN_PARTIAL_SCAN_MASK		1
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define PFN_SWC_RSSI_WINDOW_MAX   8
+#define PFN_SWC_MAX_NUM_APS       16
+#define PFN_HOTLIST_MAX_NUM_APS   64
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* Version 1 and 2 for various scan results structures defined below */
+#define PFN_SCANRESULTS_VERSION_V1	1
+#define PFN_SCANRESULTS_VERSION_V2	2
+
+/** PFN network info structure */
+typedef struct wl_pfn_subnet_info_v1 {
+	struct ether_addr BSSID;
+	uint8	channel; /**< channel number only */
+	uint8	SSID_len;
+	uint8	SSID[32];
+} wl_pfn_subnet_info_v1_t;
+
+typedef struct wl_pfn_subnet_info_v2 {
+	struct ether_addr BSSID;
+	uint8   channel; /**< channel number only */
+	uint8   SSID_len;
+	union {
+		uint8   SSID[32];
+		uint16 index;
+	} u;
+} wl_pfn_subnet_info_v2_t;
+
+typedef struct wl_pfn_net_info_v1 {
+	wl_pfn_subnet_info_v1_t pfnsubnet;
+	int16	RSSI; /**< receive signal strength (in dBm) */
+	uint16	timestamp; /**< age in seconds */
+} wl_pfn_net_info_v1_t;
+
+typedef struct wl_pfn_net_info_v2 {
+	wl_pfn_subnet_info_v2_t pfnsubnet;
+	int16   RSSI; /**< receive signal strength (in dBm) */
+	uint16  timestamp; /**< age in seconds */
+} wl_pfn_net_info_v2_t;
+
+/* Version 1 and 2 for various lbest scan results structures below */
+#define PFN_LBEST_SCAN_RESULT_VERSION_V1 1
+#define PFN_LBEST_SCAN_RESULT_VERSION_V2 2
+
+#define MAX_CHBKT_PER_RESULT		4
+
+typedef struct wl_pfn_lnet_info_v1 {
+	wl_pfn_subnet_info_v1_t pfnsubnet; /**< BSSID + channel + SSID len + SSID */
+	uint16	flags; /**< partial scan, etc */
+	int16	RSSI; /**< receive signal strength (in dBm) */
+	uint32	timestamp; /**< age in miliseconds */
+	uint16	rtt0; /**< estimated distance to this AP in centimeters */
+	uint16	rtt1; /**< standard deviation of the distance to this AP in centimeters */
+} wl_pfn_lnet_info_v1_t;
+
+typedef struct wl_pfn_lnet_info_v2 {
+	wl_pfn_subnet_info_v2_t pfnsubnet; /**< BSSID + channel + SSID len + SSID */
+	uint16  flags; /**< partial scan, etc */
+	int16   RSSI; /**< receive signal strength (in dBm) */
+	uint32  timestamp; /**< age in miliseconds */
+	uint16  rtt0; /**< estimated distance to this AP in centimeters */
+	uint16  rtt1; /**< standard deviation of the distance to this AP in centimeters */
+} wl_pfn_lnet_info_v2_t;
+
+typedef struct wl_pfn_lscanresults_v1 {
+	uint32 version;
+	uint32 status;
+	uint32 count;
+	wl_pfn_lnet_info_v1_t netinfo[1];
+} wl_pfn_lscanresults_v1_t;
+
+typedef struct wl_pfn_lscanresults_v2 {
+	uint32 version;
+	uint16 status;
+	uint16 count;
+	uint32 scan_ch_buckets[MAX_CHBKT_PER_RESULT];
+	wl_pfn_lnet_info_v2_t netinfo[1];
+} wl_pfn_lscanresults_v2_t;
+
+/**this is used to report on 1-* pfn scan results */
+typedef struct wl_pfn_scanresults_v1 {
+	uint32 version;
+	uint32 status;
+	uint32 count;
+	wl_pfn_net_info_v1_t netinfo[1];
+} wl_pfn_scanresults_v1_t;
+
+typedef struct wl_pfn_scanresults_v2 {
+	uint32 version;
+	uint32 status;
+	uint32 count;
+	uint32 scan_ch_bucket;
+	wl_pfn_net_info_v2_t netinfo[1];
+} wl_pfn_scanresults_v2_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+typedef struct wl_pfn_significant_net {
+	uint16 flags;
+	uint16 channel;
+	struct ether_addr BSSID;
+	int8 rssi[PFN_SWC_RSSI_WINDOW_MAX];
+} wl_pfn_significant_net_t;
+
+#define PFN_SWC_SCANRESULT_VERSION     1
+
+typedef struct wl_pfn_swc_results {
+	uint32 version;
+	uint32 pkt_count;   /**< No. of results in current frame */
+	uint32 total_count; /**< Total expected results */
+	wl_pfn_significant_net_t list[1];
+} wl_pfn_swc_results_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+typedef struct wl_pfn_net_info_bssid {
+	struct ether_addr BSSID;
+	uint8 channel;	/**< channel number only */
+	int8  RSSI;	/**< receive signal strength (in dBm) */
+	uint16 flags;	/**< (e.g. partial scan, off channel) */
+	uint16 timestamp; /**< age in seconds */
+} wl_pfn_net_info_bssid_t;
+
+typedef struct wl_pfn_scanhist_bssid {
+	uint32 version;
+	uint32 status;
+	uint32 count;
+	wl_pfn_net_info_bssid_t netinfo[1];
+} wl_pfn_scanhist_bssid_t;
+
+/* Version 1 and 2 for various single scan result */
+#define PFN_SCANRESULT_VERSION_V1	1
+#define PFN_SCANRESULT_VERSION_V2	2
+
+/* used to report exactly one scan result */
+/* plus reports detailed scan info in bss_info */
+typedef struct wl_pfn_scanresult_v1 {
+	uint32 version;
+	uint32 status;
+	uint32 count;
+	wl_pfn_net_info_v1_t netinfo;
+	wl_bss_info_t bss_info;
+} wl_pfn_scanresult_v1_t;
+
+typedef struct wl_pfn_scanresult_v2 {
+	uint32 version;
+	uint32 status;
+	uint32 count;
+	wl_pfn_net_info_v2_t netinfo;
+	wl_bss_info_t bss_info;
+} wl_pfn_scanresult_v2_t;
+
+/**PFN data structure */
+typedef struct wl_pfn_param {
+	int32 version;			/**< PNO parameters version */
+	int32 scan_freq;		/**< Scan frequency */
+	int32 lost_network_timeout;	/**< Timeout in sec. to declare
+								* discovered network as lost
+								*/
+	int16 flags;			/**< Bit field to control features
+							* of PFN such as sort criteria auto
+							* enable switch and background scan
+							*/
+	int16 rssi_margin;		/**< Margin to avoid jitter for choosing a
+							* PFN based on RSSI sort criteria
+							*/
+	uint8 bestn; /**< number of best networks in each scan */
+	uint8 mscan; /**< number of scans recorded */
+	uint8 repeat; /**< Minimum number of scan intervals
+				     *before scan frequency changes in adaptive scan
+				     */
+	uint8 exp; /**< Exponent of 2 for maximum scan interval */
+	int32 slow_freq; /**< slow scan period */
+} wl_pfn_param_t;
+
+typedef struct wl_pfn_bssid {
+	struct ether_addr  macaddr;
+	/* Bit4: suppress_lost, Bit3: suppress_found */
+	uint16             flags;
+} wl_pfn_bssid_t;
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+typedef struct wl_pfn_significant_bssid {
+	struct ether_addr	macaddr;
+	int8    rssi_low_threshold;
+	int8    rssi_high_threshold;
+} wl_pfn_significant_bssid_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WL_PFN_SUPPRESSFOUND_MASK	0x08
+#define WL_PFN_SUPPRESSLOST_MASK	0x10
+#define WL_PFN_SSID_IMPRECISE_MATCH	0x80
+#define WL_PFN_SSID_SAME_NETWORK	0x10000
+#define WL_PFN_SUPPRESS_AGING_MASK	0x20000
+#define WL_PFN_FLUSH_ALL_SSIDS		0x40000
+
+#define WL_PFN_IOVAR_FLAG_MASK		0xFFFF00F
+#define WL_PFN_RSSI_MASK		0xff00
+#define WL_PFN_RSSI_SHIFT		8
+
+typedef struct wl_pfn_cfg {
+	uint32	reporttype;
+	int32	channel_num;
+	uint16	channel_list[WL_NUMCHANNELS];
+	uint32	flags;
+} wl_pfn_cfg_t;
+
+#define WL_PFN_SSID_CFG_VERSION		1
+#define WL_PFN_SSID_CFG_CLEAR		0x1
+
+typedef struct wl_ssid_ext_params {
+	int8 min5G_rssi;	/* minimum 5GHz RSSI for a BSSID to be considered      */
+	int8 min2G_rssi;	/* minimum 2.4GHz RSSI for a BSSID to be considered   */
+	int16 init_score_max;	/* The maximum score that a network can have before bonuses  */
+	int16 cur_bssid_bonus;	/* Add to current bssid                                      */
+	int16 same_ssid_bonus;	/* score bonus for all networks with the same network flag   */
+	int16 secure_bonus;	/* score bonus for networks that are not open                */
+	int16 band_5g_bonus;
+} wl_ssid_ext_params_t;
+
+typedef struct wl_pfn_ssid_cfg {
+	uint16 version;
+	uint16 flags;
+	wl_ssid_ext_params_t params;
+} wl_pfn_ssid_cfg_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define CH_BUCKET_REPORT_NONE                   0
+#define CH_BUCKET_REPORT_SCAN_COMPLETE_ONLY     1
+#define CH_BUCKET_REPORT_FULL_RESULT            2
+#define CH_BUCKET_REPORT_SCAN_COMPLETE    (CH_BUCKET_REPORT_SCAN_COMPLETE_ONLY | \
+								CH_BUCKET_REPORT_FULL_RESULT)
+#define CH_BUCKET_REPORT_REGULAR            0
+#define CH_BUCKET_GSCAN                     4
+
+typedef struct wl_pfn_gscan_ch_bucket_cfg {
+	uint8 bucket_end_index;
+	uint8 bucket_freq_multiple;
+	uint8 flag;
+	uint8 reserved;
+	uint16 repeat;
+	uint16 max_freq_multiple;
+} wl_pfn_gscan_ch_bucket_cfg_t;
+
+typedef struct wl_pfn_capabilities {
+	uint16 max_mscan;
+	uint16 max_bestn;
+	uint16 max_swc_bssid;
+	uint16 max_hotlist_bssid;
+} wl_pfn_capabilities_t;
+
+#define GSCAN_SEND_ALL_RESULTS_MASK          (1 << 0)
+#define GSCAN_ALL_BUCKETS_IN_FIRST_SCAN_MASK (1 << 3)
+#define GSCAN_CFG_FLAGS_ONLY_MASK            (1 << 7)
+#define WL_GSCAN_CFG_VERSION                     1
+typedef struct wl_pfn_gscan_cfg {
+	uint16 version;
+	/**
+	 * BIT0 1 = send probes/beacons to HOST
+	 * BIT1 Reserved
+	 * BIT2 Reserved
+	 * Add any future flags here
+	 * BIT7 1 = no other useful cfg sent
+	 */
+	uint8  flags;
+	/** Buffer filled threshold in % to generate an event */
+	uint8   buffer_threshold;
+	/**
+	 * No. of BSSIDs with "change" to generate an evt
+	 * change - crosses rssi threshold/lost
+	 */
+	uint8   swc_nbssid_threshold;
+	/* Max=8 (for now) Size of rssi cache buffer */
+	uint8  swc_rssi_window_size;
+	uint8  count_of_channel_buckets;
+	uint8  retry_threshold;
+	uint16  lost_ap_window;
+	wl_pfn_gscan_ch_bucket_cfg_t channel_bucket[1];
+} wl_pfn_gscan_cfg_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#define WL_PFN_REPORT_ALLNET    0
+#define WL_PFN_REPORT_SSIDNET   1
+#define WL_PFN_REPORT_BSSIDNET  2
+
+#define WL_PFN_CFG_FLAGS_PROHIBITED	0x00000001	/* Accept and use prohibited channels */
+#define WL_PFN_CFG_FLAGS_RESERVED	0xfffffffe	/**< Remaining reserved for future use */
+
+typedef struct wl_pfn {
+	wlc_ssid_t		ssid;			/**< ssid name and its length */
+	int32			flags;			/**< bit2: hidden */
+	int32			infra;			/**< BSS Vs IBSS */
+	int32			auth;			/**< Open Vs Closed */
+	int32			wpa_auth;		/**< WPA type */
+	int32			wsec;			/**< wsec value */
+} wl_pfn_t;
+
+typedef struct wl_pfn_list {
+	uint32		version;
+	uint32		enabled;
+	uint32		count;
+	wl_pfn_t	pfn[1];
+} wl_pfn_list_t;
+
+#define WL_PFN_HIDDEN_BIT		2
+#define WL_PFN_HIDDEN_MASK		0x4
+
+#ifndef BESTN_MAX
+#define BESTN_MAX			10
+#endif
+
+#ifndef MSCAN_MAX
+#define MSCAN_MAX			90
+#endif
+
+/* Dynamic scan configuration for motion profiles */
+
+#define WL_PFN_MPF_VERSION 1
+
+/* Valid group IDs, may be expanded in the future */
+#define WL_PFN_MPF_GROUP_SSID 0
+#define WL_PFN_MPF_GROUP_BSSID 1
+#define WL_PFN_MPF_MAX_GROUPS 2
+
+/* Max number of MPF states supported in this time */
+#define WL_PFN_MPF_STATES_MAX 4
+
+/* Flags for the mpf-specific stuff */
+#define WL_PFN_MPF_ADAPT_ON_BIT		0
+#define WL_PFN_MPF_ADAPTSCAN_BIT	1
+
+#define WL_PFN_MPF_ADAPT_ON_MASK	0x0001
+#define WL_PFN_MPF_ADAPTSCAN_MASK 	0x0006
+
+/* Per-state timing values */
+typedef struct wl_pfn_mpf_state_params {
+	int32  scan_freq;	/* Scan frequency (secs) */
+	int32  lost_network_timeout; /* Timeout to declare net lost (secs) */
+	int16  flags;		/* Space for flags: ADAPT etc */
+	uint8  exp;		/* Exponent of 2 for max interval for SMART/STRICT_ADAPT */
+	uint8  repeat;		/* Number of scans before changing adaptation level */
+	int32  slow_freq;	/* Slow scan period for SLOW_ADAPT */
+} wl_pfn_mpf_state_params_t;
+
+typedef struct wl_pfn_mpf_param {
+	uint16 version;		/* Structure version */
+	uint16 groupid;		/* Group ID: 0 (SSID), 1 (BSSID), other: reserved */
+	wl_pfn_mpf_state_params_t state[WL_PFN_MPF_STATES_MAX];
+} wl_pfn_mpf_param_t;
+
+/* Structure for setting pfn_override iovar */
+typedef struct wl_pfn_override_param {
+	uint16 version;         /* Structure version */
+	uint16 start_offset;    /* Seconds from now to apply new params */
+	uint16 duration;        /* Seconds to keep new params applied */
+	uint16 reserved;
+	wl_pfn_mpf_state_params_t override;
+} wl_pfn_override_param_t;
+#define WL_PFN_OVERRIDE_VERSION	1
+
+/*
+ * Definitions for base MPF configuration
+ */
+
+#define WL_MPF_VERSION 1
+#define WL_MPF_MAX_BITS 3
+#define WL_MPF_MAX_STATES (1 << WL_MPF_MAX_BITS)
+
+#define WL_MPF_STATE_NAME_MAX 12
+
+typedef struct wl_mpf_val {
+	uint16 val;		/* Value of GPIO bits */
+	uint16 state;		/* State identifier */
+	char name[WL_MPF_STATE_NAME_MAX]; /* Optional name */
+} wl_mpf_val_t;
+
+typedef struct wl_mpf_map {
+	uint16 version;
+	uint16 type;
+	uint16 mask;		/* Which GPIO bits to use */
+	uint8  count;		/* Count of state/value mappings */
+	uint8  PAD1;
+	wl_mpf_val_t vals[WL_MPF_MAX_STATES];
+} wl_mpf_map_t;
+
+#define WL_MPF_STATE_AUTO (0xFFFF) /* (uint16)-1) */
+
+typedef struct wl_mpf_state {
+	uint16 version;
+	uint16 type;
+	uint16 state;		/* Get/Set */
+	uint8 force;		/* 0 - auto (HW) state, 1 - forced state */
+	char name[WL_MPF_STATE_NAME_MAX]; /* Get/Set: Optional/actual name */
+} wl_mpf_state_t;
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/*
+ * WLFCTS definition
+ */
+typedef struct wl_txstatus_additional_info {
+	uint32 rspec;
+	uint32 enq_ts;
+	uint32 last_ts;
+	uint32 entry_ts;
+	uint16 seq;
+	uint8  rts_cnt;
+	uint8  tx_cnt;
+} wl_txstatus_additional_info_t;
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/** Service discovery */
+typedef struct {
+	uint8	transaction_id;	/**< Transaction id */
+	uint8	protocol;	/**< Service protocol type */
+	uint16	query_len;	/**< Length of query */
+	uint16	response_len;	/**< Length of response */
+	uint8	qrbuf[1];
+} wl_p2po_qr_t;
+
+typedef struct {
+	uint16			period;			/**< extended listen period */
+	uint16			interval;		/**< extended listen interval */
+	uint16                  count;                  /* count to repeat */
+	uint16                  pad;                    /* pad for 32bit align */
+} wl_p2po_listen_t;
+
+/** GAS state machine tunable parameters.  Structure field values of 0 means use the default. */
+typedef struct wl_gas_config {
+	uint16 max_retransmit;		/**< Max # of firmware/driver retransmits on no Ack
+					 * from peer (on top of the ucode retries).
+					 */
+	uint16 response_timeout;	/**< Max time to wait for a GAS-level response
+					 * after sending a packet.
+					 */
+	uint16 max_comeback_delay;	/**< Max GAS response comeback delay.
+					 * Exceeding this fails the GAS exchange.
+					 */
+	uint16 max_retries;		/**< Max # of GAS state machine retries on failure
+					 * of a GAS frame exchange.
+					 */
+} wl_gas_config_t;
+
+/** P2P Find Offload parameters */
+typedef struct wl_p2po_find_config {
+	uint16 version;			/**< Version of this struct */
+	uint16 length;			/**< sizeof(wl_p2po_find_config_t) */
+	int32 search_home_time;		/**< P2P search state home time when concurrent
+					 * connection exists.  -1 for default.
+					 */
+	uint8 num_social_channels;
+			/**< Number of social channels up to WL_P2P_SOCIAL_CHANNELS_MAX.
+			 * 0 means use default social channels.
+			 */
+	uint8 flags;
+	uint16 social_channels[1];	/**< Variable length array of social channels */
+} wl_p2po_find_config_t;
+#define WL_P2PO_FIND_CONFIG_VERSION 2	/**< value for version field */
+
+/** wl_p2po_find_config_t flags */
+#define P2PO_FIND_FLAG_SCAN_ALL_APS 0x01	/**< Whether to scan for all APs in the p2po_find
+						 * periodic scans of all channels.
+						 * 0 means scan for only P2P devices.
+						 * 1 means scan for P2P devices plus non-P2P APs.
+						 */
+
+
+/** For adding a WFDS service to seek */
+typedef struct {
+	uint32 seek_hdl;		/**< unique id chosen by host */
+	uint8 addr[6];			/**< Seek service from a specific device with this
+					 * MAC address, all 1's for any device.
+					 */
+	uint8 service_hash[P2P_WFDS_HASH_LEN];
+	uint8 service_name_len;
+	uint8 service_name[MAX_WFDS_SEEK_SVC_NAME_LEN];
+					/**< Service name to seek, not null terminated */
+	uint8 service_info_req_len;
+	uint8 service_info_req[1];	/**< Service info request, not null terminated.
+					 * Variable length specified by service_info_req_len.
+					 * Maximum length is MAX_WFDS_SEEK_SVC_INFO_LEN.
+					 */
+} wl_p2po_wfds_seek_add_t;
+
+/** For deleting a WFDS service to seek */
+typedef struct {
+	uint32 seek_hdl;		/**< delete service specified by id */
+} wl_p2po_wfds_seek_del_t;
+
+
+/** For adding a WFDS service to advertise */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 advertise_hdl;		/**< unique id chosen by host */
+	uint8 service_hash[P2P_WFDS_HASH_LEN];
+	uint32 advertisement_id;
+	uint16 service_config_method;
+	uint8 service_name_len;
+	uint8 service_name[MAX_WFDS_SVC_NAME_LEN];
+					/**< Service name , not null terminated */
+	uint8 service_status;
+	uint16 service_info_len;
+	uint8 service_info[1];		/**< Service info, not null terminated.
+					 * Variable length specified by service_info_len.
+					 * Maximum length is MAX_WFDS_ADV_SVC_INFO_LEN.
+					 */
+} BWL_POST_PACKED_STRUCT wl_p2po_wfds_advertise_add_t;
+#include <packed_section_end.h>
+
+/** For deleting a WFDS service to advertise */
+typedef struct {
+	uint32 advertise_hdl;	/**< delete service specified by hdl */
+} wl_p2po_wfds_advertise_del_t;
+
+/** P2P Offload discovery mode for the p2po_state iovar */
+typedef enum {
+	WL_P2PO_DISC_STOP,
+	WL_P2PO_DISC_LISTEN,
+	WL_P2PO_DISC_DISCOVERY
+} disc_mode_t;
+
+/* ANQP offload */
+
+#define ANQPO_MAX_QUERY_SIZE		256
+typedef struct {
+	uint16 max_retransmit;		/**< ~0 use default, max retransmit on no ACK from peer */
+	uint16 response_timeout; /**< ~0 use default, msec to wait for resp after tx packet */
+	uint16 max_comeback_delay;	/**< ~0 use default, max comeback delay in resp else fail */
+	uint16 max_retries;		/**< ~0 use default, max retries on failure */
+	uint16 query_len;		/**< length of ANQP query */
+	uint8 query_data[1];		/**< ANQP encoded query (max ANQPO_MAX_QUERY_SIZE) */
+} wl_anqpo_set_t;
+
+typedef struct {
+	uint16 channel;			/**< channel of the peer */
+	struct ether_addr addr;		/**< addr of the peer */
+} wl_anqpo_peer_t;
+
+#define ANQPO_MAX_PEER_LIST			64
+typedef struct {
+	uint16 count;				/**< number of peers in list */
+	wl_anqpo_peer_t peer[1];	/**< max ANQPO_MAX_PEER_LIST */
+} wl_anqpo_peer_list_t;
+
+#define ANQPO_MAX_IGNORE_SSID		64
+typedef struct {
+	uint8 is_clear;				/**< set to clear list (not used on GET) */
+	uint16 count;				/**< number of SSID in list */
+	wlc_ssid_t ssid[1];			/**< max ANQPO_MAX_IGNORE_SSID */
+} wl_anqpo_ignore_ssid_list_t;
+
+#define ANQPO_MAX_IGNORE_BSSID		64
+typedef struct {
+	uint8 is_clear;				/**< set to clear list (not used on GET) */
+	uint16 count;				/**< number of addr in list */
+	struct ether_addr bssid[1];	/**< max ANQPO_MAX_IGNORE_BSSID */
+} wl_anqpo_ignore_bssid_list_t;
+
+
+struct toe_ol_stats_t {
+	/** Num of tx packets that don't need to be checksummed */
+	uint32 tx_summed;
+
+	/* Num of tx packets where checksum is filled by offload engine */
+	uint32 tx_iph_fill;
+	uint32 tx_tcp_fill;
+	uint32 tx_udp_fill;
+	uint32 tx_icmp_fill;
+
+	/*  Num of rx packets where toe finds out if checksum is good or bad */
+	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;
+
+	/* Num of tx packets in which csum error is injected */
+	uint32 tx_tcp_errinj;
+	uint32 tx_udp_errinj;
+	uint32 tx_icmp_errinj;
+
+	/* Num of rx packets in which csum error is injected */
+	uint32 rx_tcp_errinj;
+	uint32 rx_udp_errinj;
+	uint32 rx_icmp_errinj;
+};
+
+/** Arp offload statistic counts */
+struct arp_ol_stats_t {
+	uint32  host_ip_entries; /**< Host IP table addresses (more than one if multihomed) */
+	uint32  host_ip_overflow;	/**< Host IP table additions skipped due to overflow */
+
+	uint32  arp_table_entries;	/**< ARP table entries */
+	uint32  arp_table_overflow;	/**< ARP table additions skipped due to overflow */
+
+	uint32  host_request;		/**< ARP requests from host */
+	uint32  host_reply;		/**< ARP replies from host */
+	uint32  host_service;		/**< ARP requests from host serviced by ARP Agent */
+
+	uint32  peer_request;		/**< ARP requests received from network */
+	uint32  peer_request_drop;	/**< ARP requests from network that were dropped */
+	uint32  peer_reply;		/**< ARP replies received from network */
+	uint32  peer_reply_drop;	/**< ARP replies from network that were dropped */
+	uint32  peer_service;		/**< ARP request from host serviced by ARP Agent */
+};
+
+/** NS offload statistic counts */
+struct nd_ol_stats_t {
+	uint32  host_ip_entries;    /**< Host IP table addresses (more than one if multihomed) */
+	uint32  host_ip_overflow;   /**< Host IP table additions skipped due to overflow */
+	uint32  peer_request;       /**< NS requests received from network */
+	uint32  peer_request_drop;  /**< NS requests from network that were dropped */
+	uint32  peer_reply_drop;    /**< NA replies from network that were dropped */
+	uint32  peer_service;       /**< NS request from host serviced by firmware */
+};
+
+/*
+ * Neighbor Discovery Offloading
+ */
+enum {
+	WL_ND_IPV6_ADDR_TYPE_UNICAST = 0,
+	WL_ND_IPV6_ADDR_TYPE_ANYCAST
+};
+
+typedef struct wl_nd_host_ip_addr {
+	struct ipv6_addr ip_addr;	/* host ip address */
+	uint8 type;			/* type of address */
+	uint8 pad[3];
+} wl_nd_host_ip_addr_t;
+
+typedef struct wl_nd_host_ip_list {
+	uint32 count;
+	wl_nd_host_ip_addr_t host_ip[1];
+} wl_nd_host_ip_list_t;
+
+#define WL_ND_HOSTIP_IOV_VER    1
+
+enum {
+	WL_ND_HOSTIP_OP_VER = 0,	/* get version */
+	WL_ND_HOSTIP_OP_ADD,		/* add address */
+	WL_ND_HOSTIP_OP_DEL,		/* delete specified address */
+	WL_ND_HOSTIP_OP_DEL_UC,		/* delete all unicast address */
+	WL_ND_HOSTIP_OP_DEL_AC,		/* delete all anycast address */
+	WL_ND_HOSTIP_OP_DEL_ALL,	/* delete all addresses */
+	WL_ND_HOSTIP_OP_LIST,		/* get list of host ip address */
+	WL_ND_HOSTIP_OP_MAX
+};
+
+typedef struct wl_nd_hostip {
+	uint16 version;				/* version of iovar buf */
+	uint16 op_type;				/* operation type */
+	uint32 length;				/* length of entire structure */
+	union {
+		wl_nd_host_ip_addr_t host_ip;	/* set param for add */
+		uint16 version;			/* get return for ver */
+	} u;
+} wl_nd_hostip_t;
+
+#define WL_ND_HOSTIP_FIXED_LEN		OFFSETOF(wl_nd_hostip_t, u)
+#define WL_ND_HOSTIP_WITH_ADDR_LEN	(WL_ND_HOSTIP_FIXED_LEN + sizeof(wl_nd_host_ip_addr_t))
+
+/*
+ * Keep-alive packet offloading.
+ */
+
+/**
+ * NAT keep-alive packets format: specifies the re-transmission period, the packet
+ * length, and packet contents.
+ */
+typedef struct wl_keep_alive_pkt {
+	uint32	period_msec;	/** Retransmission period (0 to disable packet re-transmits) */
+	uint16	len_bytes;	/* Size of packet to transmit (0 to disable packet re-transmits) */
+	uint8	data[1];	/** Variable length packet to transmit.  Contents should include
+				 * entire ethernet packet (enet header, IP header, UDP header,
+				 * and UDP payload) in network byte order.
+				 */
+} wl_keep_alive_pkt_t;
+
+#define WL_KEEP_ALIVE_FIXED_LEN		OFFSETOF(wl_keep_alive_pkt_t, data)
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/*
+ * ptk_start: iovar to start 4-way handshake for secured ranging
+*/
+
+/* ptk negotiation security type - determines negotiation parameters */
+typedef enum {
+	WL_PTK_START_SEC_TYPE_PMK = 1
+} wl_ptk_start_sec_type_t;
+
+/* ptk negotiation role */
+enum {
+	ROLE_NONE	= 0x0,
+	ROLE_AUTH	= 0x1,
+	ROLE_SUP	= 0x2,
+	ROLE_STATIC	= 0x3,
+	ROLE_INVALID	= 0xff
+};
+typedef int32 wl_ptk_start_role_t;
+
+typedef struct wl_ptk_start_tlv_v1 {
+	uint16 id;
+	uint16 len;
+	uint8 data[1];
+} wl_ptk_start_tlv_v1_t;
+
+typedef enum {
+	WL_PTK_START_TLV_PMK	= 1	/* uint8[] */
+} wl_ptk_start_tlv_type;
+
+typedef enum {
+	WL_PTK_START_FLAG_NO_DATA_PROT	= 1,	/* data frame protection disabled */
+	WL_PTK_START_FLAG_GEN_FTM_TPK	= 2	/* Generate FTM Toast/Seq Protection Key */
+} wl_ptk_start_flags_t;
+
+struct wl_ptk_start_iov_v1 {
+	uint16 version;
+	uint16 len;				/* length of entire iov from version */
+	wl_ptk_start_flags_t flags;
+	wl_ptk_start_sec_type_t sec_type;
+	wl_ptk_start_role_t role;
+	struct ether_addr peer_addr;
+	uint16 pad;				/* reserved/32 bit alignment */
+	wl_ptk_start_tlv_v1_t tlvs[1];
+};
+
+/*
+ * Dongle pattern matching filter.
+ */
+
+#define MAX_WAKE_PACKET_CACHE_BYTES 128 /**< Maximum cached wake packet */
+
+#define MAX_WAKE_PACKET_BYTES	    (DOT11_A3_HDR_LEN +			    \
+				     DOT11_QOS_LEN +			    \
+				     sizeof(struct dot11_llc_snap_header) + \
+				     ETHER_MAX_DATA)
+
+typedef struct pm_wake_packet {
+	uint32	status;		/**< Is the wake reason a packet (if all the other field's valid) */
+	uint32	pattern_id;	/**< Pattern ID that matched */
+	uint32	original_packet_size;
+	uint32	saved_packet_size;
+	uint8	packet[MAX_WAKE_PACKET_CACHE_BYTES];
+} pm_wake_packet_t;
+
+/* Packet filter types. Currently, only pattern matching is supported. */
+typedef enum wl_pkt_filter_type {
+	WL_PKT_FILTER_TYPE_PATTERN_MATCH=0,       /**< Pattern matching filter */
+	WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH=1, /**< Magic packet match */
+	WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH=2,  /**< A pattern list (match all to match filter) */
+	WL_PKT_FILTER_TYPE_ENCRYPTED_PATTERN_MATCH=3, /**< SECURE WOWL magic / net pattern match */
+	WL_PKT_FILTER_TYPE_APF_MATCH=4, /* Android packet filter match */
+	WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT=5, /* Pattern matching filter with timeout event */
+	WL_PKT_FILTER_TYPE_IMMEDIATE_PATTERN_MATCH=6, /* Immediately pattern matching filter */
+} wl_pkt_filter_type_t;
+
+#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t
+
+/* String mapping for types that may be used by applications or debug */
+#define WL_PKT_FILTER_TYPE_NAMES \
+	{ "PATTERN", WL_PKT_FILTER_TYPE_PATTERN_MATCH },	\
+	{ "MAGIC",   WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH },	\
+	{ "PATLIST", WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH },	\
+	{ "SECURE WOWL", WL_PKT_FILTER_TYPE_ENCRYPTED_PATTERN_MATCH },	\
+	{ "APF", WL_PKT_FILTER_TYPE_APF_MATCH }, \
+	{ "PATTERN TIMEOUT", WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT }, \
+	{ "IMMEDIATE", WL_PKT_FILTER_TYPE_IMMEDIATE_PATTERN_MATCH }
+
+/** Secured WOWL packet was encrypted, need decrypted before check filter match */
+typedef struct wl_pkt_decrypter {
+	uint8* (*dec_cb)(void* dec_ctx, const void *sdu, int sending);
+	void*  dec_ctx;
+} wl_pkt_decrypter_t;
+
+/**
+ * Pattern matching filter. Specifies an offset within received packets to
+ * start matching, the pattern to match, the size of the pattern, and a bitmask
+ * that indicates which bits within the pattern should be matched.
+ */
+typedef struct wl_pkt_filter_pattern {
+	uint32	offset;		/**< Offset within received packet to start pattern matching.
+				 * Offset '0' is the first byte of the ethernet header.
+				 */
+	uint32	size_bytes;	/**< Size of the pattern.  Bitmask must be the same size. */
+	uint8   mask_and_pattern[1]; /**< Variable length mask and pattern data.  mask starts
+				      * at offset 0.  Pattern immediately follows mask. for
+				      * secured pattern, put the descrypter pointer to the
+				      * beginning, mask and pattern postponed correspondingly
+				      */
+} wl_pkt_filter_pattern_t;
+
+/** A pattern list is a numerically specified list of modified pattern structures. */
+typedef struct wl_pkt_filter_pattern_listel {
+	uint16 rel_offs;	/**< Offset to begin match (relative to 'base' below) */
+	uint16 base_offs;	/**< Base for offset (defined below) */
+	uint16 size_bytes;	/**< Size of mask/pattern */
+	uint16 match_flags;	/**< Addition flags controlling the match */
+	uint8  mask_and_data[1]; /**< Variable length mask followed by data, each size_bytes */
+} wl_pkt_filter_pattern_listel_t;
+
+typedef struct wl_pkt_filter_pattern_list {
+	uint8 list_cnt;		/**< Number of elements in the list */
+	uint8 PAD1[1];		/**< Reserved (possible version: reserved) */
+	uint16 totsize;		/**< Total size of this pattern list (includes this struct) */
+	wl_pkt_filter_pattern_listel_t patterns[1]; /**< Variable number of list elements */
+} wl_pkt_filter_pattern_list_t;
+
+typedef struct wl_apf_program {
+	uint16 version;
+	uint16 instr_len;	/* number of instruction blocks */
+	uint32 inst_ts;		/* program installation timestamp */
+	uint8 instrs[1];	/* variable length instructions */
+} wl_apf_program_t;
+
+typedef struct wl_pkt_filter_pattern_timeout {
+	uint32	offset;	/* Offset within received packet to start pattern matching.
+					 * Offset '0' is the first byte of the ethernet header.
+					 */
+	uint32	size_bytes;	/* Size of the pattern. Bitmask must be the same size. */
+	uint32	timeout;	/* Timeout(seconds) */
+	uint8	mask_and_pattern[1]; /* Variable length mask and pattern data.
+								 * mask starts at offset 0. Pattern
+								 * immediately follows mask.
+								*/
+} wl_pkt_filter_pattern_timeout_t;
+
+/** IOVAR "pkt_filter_add" parameter. Used to install packet filters. */
+typedef struct wl_pkt_filter {
+	uint32	id;		/**< Unique filter id, specified by app. */
+	uint32	type;		/**< Filter type (WL_PKT_FILTER_TYPE_xxx). */
+	uint32	negate_match;	/**< Negate the result of filter matches */
+	union {			/* Filter definitions */
+		wl_pkt_filter_pattern_t pattern;	/**< Pattern matching filter */
+		wl_pkt_filter_pattern_list_t patlist; /**< List of patterns to match */
+		wl_apf_program_t apf_program; /* apf program */
+		wl_pkt_filter_pattern_timeout_t pattern_timeout; /* Pattern timeout event filter */
+	} u;
+} wl_pkt_filter_t;
+
+/** IOVAR "tcp_keep_set" parameter. Used to install tcp keep_alive stuff. */
+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)
+#define WL_PKT_FILTER_PATTERN_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_list_t, patterns)
+#define WL_PKT_FILTER_PATTERN_LISTEL_FIXED_LEN	\
+			OFFSETOF(wl_pkt_filter_pattern_listel_t, mask_and_data)
+#define WL_PKT_FILTER_PATTERN_TIMEOUT_FIXED_LEN	\
+			OFFSETOF(wl_pkt_filter_pattern_timeout_t, mask_and_pattern)
+
+#define WL_APF_INTERNAL_VERSION	1
+#define WL_APF_PROGRAM_FIXED_LEN	OFFSETOF(wl_apf_program_t, instrs)
+#define WL_APF_PROGRAM_LEN(apf_program)	\
+	((apf_program)->instr_len * sizeof((apf_program)->instrs[0]))
+#define WL_APF_PROGRAM_TOTAL_LEN(apf_program)	\
+	(WL_APF_PROGRAM_FIXED_LEN + WL_APF_PROGRAM_LEN(apf_program))
+
+/** IOVAR "pkt_filter_enable" parameter. */
+typedef struct wl_pkt_filter_enable {
+	uint32	id;		/**< Unique filter id */
+	uint32	enable;		/**< Enable/disable bool */
+} wl_pkt_filter_enable_t;
+
+/** IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */
+typedef struct wl_pkt_filter_list {
+	uint32	num;		/**< Number of installed packet filters */
+	wl_pkt_filter_t	filter[1];	/**< Variable array of packet filters. */
+} wl_pkt_filter_list_t;
+
+#define WL_PKT_FILTER_LIST_FIXED_LEN	  OFFSETOF(wl_pkt_filter_list_t, filter)
+
+/** IOVAR "pkt_filter_stats" parameter. Used to retrieve debug statistics. */
+typedef struct wl_pkt_filter_stats {
+	uint32	num_pkts_matched;	/**< # filter matches for specified filter id */
+	uint32	num_pkts_forwarded;	/**< # packets fwded from dongle to host for all filters */
+	uint32	num_pkts_discarded;	/**< # packets discarded by dongle for all filters */
+} wl_pkt_filter_stats_t;
+
+/** IOVAR "pkt_filter_ports" parameter.  Configure TCP/UDP port filters. */
+typedef struct wl_pkt_filter_ports {
+	uint8 version;		/**< Be proper */
+	uint8 reserved;		/**< Be really proper */
+	uint16 count;		/**< Number of ports following */
+	/* End of fixed data */
+	uint16 ports[1];	/**< Placeholder for ports[<count>] */
+} wl_pkt_filter_ports_t;
+
+#define WL_PKT_FILTER_PORTS_FIXED_LEN	OFFSETOF(wl_pkt_filter_ports_t, ports)
+
+#define WL_PKT_FILTER_PORTS_VERSION	0
+#define WL_PKT_FILTER_PORTS_MAX		128
+
+#define RSN_REPLAY_LEN 8
+typedef struct _gtkrefresh {
+	uint8	KCK[RSN_KCK_LENGTH];
+	uint8	KEK[RSN_KEK_LENGTH];
+	uint8	ReplayCounter[RSN_REPLAY_LEN];
+} gtk_keyinfo_t, *pgtk_keyinfo_t;
+
+/** Sequential Commands ioctl */
+typedef struct wl_seq_cmd_ioctl {
+	uint32 cmd;		/**< common ioctl definition */
+	uint32 len;		/**< length of user buffer */
+} wl_seq_cmd_ioctl_t;
+
+#define WL_SEQ_CMD_ALIGN_BYTES	4
+
+/**
+ * These are the set of get IOCTLs that should be allowed when using
+ * IOCTL sequence commands. These are issued implicitly by wl.exe each time
+ * it is invoked. We never want to buffer these, or else wl.exe will stop working.
+ */
+#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \
+	(((cmd) == WLC_GET_MAGIC)		|| \
+	 ((cmd) == WLC_GET_VERSION)		|| \
+	 ((cmd) == WLC_GET_AP)			|| \
+	 ((cmd) == WLC_GET_INSTANCE))
+
+typedef struct wl_pkteng {
+	uint32 flags;
+	uint32 delay;			/**< Inter-packet delay */
+	uint32 nframes;			/**< Number of frames */
+	uint32 length;			/**< Packet length */
+	uint8  seqno;			/**< Enable/disable sequence no. */
+	struct ether_addr dest;		/**< Destination address */
+	struct ether_addr src;		/**< Source address */
+} wl_pkteng_t;
+
+typedef struct wl_pkteng_stats {
+	uint32 lostfrmcnt;		/**< RX PER test: no of frames lost (skip seqno) */
+	int32 rssi;			/**< RSSI */
+	int32 snr;			/**< signal to noise ratio */
+	uint16 rxpktcnt[NUM_80211_RATES+1];
+	uint8 rssi_qdb;			/**< qdB portion of the computed rssi */
+} wl_pkteng_stats_t;
+
+typedef struct wl_txcal_params {
+	wl_pkteng_t pkteng;
+	uint8 gidx_start;
+	int8 gidx_step;
+	uint8 gidx_stop;
+} wl_txcal_params_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#if !defined(BCMDONGLEHOST)
+typedef struct wl_sslpnphy_papd_debug_data {
+	uint8 psat_pwr;
+	uint8 psat_indx;
+	uint8 final_idx;
+	uint8 start_idx;
+	int32 min_phase;
+	int32 voltage;
+	int8 temperature;
+} wl_sslpnphy_papd_debug_data_t;
+typedef struct wl_sslpnphy_debug_data {
+	int16 papdcompRe [64];
+	int16 papdcompIm [64];
+} wl_sslpnphy_debug_data_t;
+typedef struct wl_sslpnphy_spbdump_data {
+	uint16 tbl_length;
+	int16 spbreal[256];
+	int16 spbimg[256];
+} wl_sslpnphy_spbdump_data_t;
+typedef struct wl_sslpnphy_percal_debug_data {
+	uint32 cur_idx;
+	uint32 tx_drift;
+	uint8 prev_cal_idx;
+	uint32 percal_ctr;
+	int32 nxt_cal_idx;
+	uint32 force_1idxcal;
+	uint32 onedxacl_req;
+	int32 last_cal_volt;
+	int8 last_cal_temp;
+	uint32 vbat_ripple;
+	uint32 exit_route;
+	int32 volt_winner;
+} wl_sslpnphy_percal_debug_data_t;
+#endif 
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+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;		/**< Size of the mask in #of bytes */
+	uint32		    offset;		/**< Pattern byte offset in packet */
+	uint32		    patternoffset;	/**< Offset of start of pattern in the structure */
+	uint32		    patternsize;	/**< Size of the pattern itself in #of bytes */
+	uint32		    id;			/**< id */
+	uint32		    reasonsize;		/**< Size of the wakeup reason code */
+	wowl_pattern_type_t type;		/**< Type of pattern */
+	/* Mask follows the structure above */
+	/* Pattern follows the mask is at 'patternoffset' from the start */
+} wl_wowl_pattern_t;
+
+typedef struct wl_wowl_pattern_list {
+	uint32			count;
+	wl_wowl_pattern_t	pattern[1];
+} wl_wowl_pattern_list_t;
+
+typedef struct wl_wowl_wakeind {
+	uint8	pci_wakeind;	/**< Whether PCI PMECSR PMEStatus bit was set */
+	uint32	ucode_wakeind;	/**< What wakeup-event indication was set by ucode */
+} wl_wowl_wakeind_t;
+
+typedef struct {
+	uint32		pktlen;		    /**< size of packet */
+	void		*sdu;
+} tcp_keepalive_wake_pkt_infop_t;
+
+/** per AC rate control related data structure */
+typedef struct wl_txrate_class {
+	uint8		init_rate;
+	uint8		min_rate;
+	uint8		max_rate;
+} wl_txrate_class_t;
+
+/** structure for Overlap BSS scan arguments */
+typedef struct wl_obss_scan_arg {
+	int16	passive_dwell;
+	int16	active_dwell;
+	int16	bss_widthscan_interval;
+	int16	passive_total;
+	int16	active_total;
+	int16	chanwidth_transition_delay;
+	int16	activity_threshold;
+} wl_obss_scan_arg_t;
+
+#define WL_OBSS_SCAN_PARAM_LEN	sizeof(wl_obss_scan_arg_t)
+
+/** RSSI event notification configuration. */
+typedef struct wl_rssi_event {
+	uint32 rate_limit_msec;		/**< # of events posted to application will be limited to
+					 * one per specified period (0 to disable rate limit).
+					 */
+	uint8 num_rssi_levels;		/**< Number of entries in rssi_levels[] below */
+	int8 rssi_levels[MAX_RSSI_LEVELS];	/**< Variable number of RSSI levels. An event
+						 * will be posted each time the RSSI of received
+						 * beacons/packets crosses a level.
+						 */
+	int8 pad[3];
+} wl_rssi_event_t;
+
+#define RSSI_MONITOR_VERSION    1
+#define RSSI_MONITOR_STOP       (1 << 0)
+typedef struct wl_rssi_monitor_cfg {
+	uint8 version;
+	uint8 flags;
+	int8 max_rssi;
+	int8 min_rssi;
+} wl_rssi_monitor_cfg_t;
+
+typedef struct wl_rssi_monitor_evt {
+	uint8 version;
+	int8 cur_rssi;
+	uint16 pad;
+} wl_rssi_monitor_evt_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/* CCA based channel quality event configuration */
+#define WL_CHAN_QUAL_CCA	0
+#define WL_CHAN_QUAL_NF		1
+#define WL_CHAN_QUAL_NF_LTE	2
+#define WL_CHAN_QUAL_TOTAL	3
+
+#define MAX_CHAN_QUAL_LEVELS	8
+
+typedef struct wl_chan_qual_metric {
+	uint8 id;				/**< metric ID */
+	uint8 num_levels;               	/**< Number of entries in rssi_levels[] below */
+	uint16 flags;
+	int16 htol[MAX_CHAN_QUAL_LEVELS];	/**< threshold level array: hi-to-lo */
+	int16 ltoh[MAX_CHAN_QUAL_LEVELS];	/**< threshold level array: lo-to-hi */
+} wl_chan_qual_metric_t;
+
+typedef struct wl_chan_qual_event {
+	uint32 rate_limit_msec;		/**< # of events posted to application will be limited to
+					 * one per specified period (0 to disable rate limit).
+					 */
+	uint16 flags;
+	uint16 num_metrics;
+	wl_chan_qual_metric_t metric[WL_CHAN_QUAL_TOTAL];	/**< metric array */
+} wl_chan_qual_event_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+typedef struct wl_action_obss_coex_req {
+	uint8 info;
+	uint8 num;
+	uint8 ch_list[1];
+} wl_action_obss_coex_req_t;
+
+
+/** IOVar parameter block for small MAC address array with type indicator */
+#define WL_IOV_MAC_PARAM_LEN  4
+
+#define WL_IOV_PKTQ_LOG_PRECS 16
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 num_addrs;
+	uint8   addr_type[WL_IOV_MAC_PARAM_LEN];
+	struct ether_addr ea[WL_IOV_MAC_PARAM_LEN];
+} BWL_POST_PACKED_STRUCT wl_iov_mac_params_t;
+#include <packed_section_end.h>
+
+/** This is extra info that follows wl_iov_mac_params_t */
+typedef struct {
+	uint32 addr_info[WL_IOV_MAC_PARAM_LEN];
+} wl_iov_mac_extra_params_t;
+
+/** Combined structure */
+typedef struct {
+	wl_iov_mac_params_t params;
+	wl_iov_mac_extra_params_t extra_params;
+} wl_iov_mac_full_params_t;
+
+/** Parameter block for PKTQ_LOG statistics */
+#define PKTQ_LOG_COUNTERS_V4 \
+	/* packets requested to be stored */ \
+	uint32 requested; \
+	/* packets stored */ \
+	uint32 stored; \
+	/* packets saved, because a lowest priority queue has given away one packet */ \
+	uint32 saved; \
+	/* packets saved, because an older packet from the same queue has been dropped */ \
+	uint32 selfsaved; \
+	/* packets dropped, because pktq is full with higher precedence packets */ \
+	uint32 full_dropped; \
+	 /* packets dropped because pktq per that precedence is full */ \
+	uint32 dropped; \
+	/* packets dropped, in order to save one from a queue of a highest priority */ \
+	uint32 sacrificed; \
+	/* packets droped because of hardware/transmission error */ \
+	uint32 busy; \
+	/* packets re-sent because they were not received */ \
+	uint32 retry; \
+	/* packets retried again (ps pretend) prior to moving power save mode */ \
+	uint32 ps_retry; \
+	 /* suppressed packet count */ \
+	uint32 suppress; \
+	/* packets finally dropped after retry limit */ \
+	uint32 retry_drop; \
+	/* the high-water mark of the queue capacity for packets - goes to zero as queue fills */ \
+	uint32 max_avail; \
+	/* the high-water mark of the queue utilisation for packets - ('inverse' of max_avail) */ \
+	uint32 max_used; \
+	 /* the maximum capacity of the queue */ \
+	uint32 queue_capacity; \
+	/* count of rts attempts that failed to receive cts */ \
+	uint32 rtsfail; \
+	/* count of packets sent (acked) successfully */ \
+	uint32 acked; \
+	/* running total of phy rate of packets sent successfully */ \
+	uint32 txrate_succ; \
+	/* running total of phy 'main' rate */ \
+	uint32 txrate_main; \
+	/* actual data transferred successfully */ \
+	uint32 throughput; \
+	/* time difference since last pktq_stats */ \
+	uint32 time_delta;
+
+typedef struct {
+	PKTQ_LOG_COUNTERS_V4
+} pktq_log_counters_v04_t;
+
+/** v5 is the same as V4 with extra parameter */
+typedef struct {
+	PKTQ_LOG_COUNTERS_V4
+	/** cumulative time to transmit */
+	uint32 airtime;
+} pktq_log_counters_v05_t;
+
+typedef struct {
+	uint8                num_prec[WL_IOV_MAC_PARAM_LEN];
+	pktq_log_counters_v04_t  counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS];
+	uint32               counter_info[WL_IOV_MAC_PARAM_LEN];
+	uint32               pspretend_time_delta[WL_IOV_MAC_PARAM_LEN];
+	char                 headings[1];
+} pktq_log_format_v04_t;
+
+typedef struct {
+	uint8                num_prec[WL_IOV_MAC_PARAM_LEN];
+	pktq_log_counters_v05_t  counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS];
+	uint32               counter_info[WL_IOV_MAC_PARAM_LEN];
+	uint32               pspretend_time_delta[WL_IOV_MAC_PARAM_LEN];
+	char                 headings[1];
+} pktq_log_format_v05_t;
+
+
+typedef struct {
+	uint32               version;
+	wl_iov_mac_params_t  params;
+	union {
+		pktq_log_format_v04_t v04;
+		pktq_log_format_v05_t v05;
+	} pktq_log;
+} wl_iov_pktq_log_t;
+
+/* PKTQ_LOG_AUTO, PKTQ_LOG_DEF_PREC flags introduced in v05, they are ignored by v04 */
+#define PKTQ_LOG_AUTO     (1 << 31)
+#define PKTQ_LOG_DEF_PREC (1 << 30)
+
+typedef struct wl_pfn_macaddr_cfg_0 {
+	uint8 version;
+	uint8 reserved;
+	struct ether_addr macaddr;
+} wl_pfn_macaddr_cfg_0_t;
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define LEGACY1_WL_PFN_MACADDR_CFG_VER 0
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WL_PFN_MAC_OUI_ONLY_MASK      1
+#define WL_PFN_SET_MAC_UNASSOC_MASK   2
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_PFN_RESTRICT_LA_MAC_MASK   4
+#define WL_PFN_MACADDR_FLAG_MASK     0x7
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/** To configure pfn_macaddr */
+typedef struct wl_pfn_macaddr_cfg {
+	uint8 version;
+	uint8 flags;
+	struct ether_addr macaddr;
+} wl_pfn_macaddr_cfg_t;
+#define WL_PFN_MACADDR_CFG_VER 1
+
+/*
+ * SCB_BS_DATA iovar definitions start.
+ */
+#define SCB_BS_DATA_STRUCT_VERSION	1
+
+/** The actual counters maintained for each station */
+typedef struct {
+	/* The following counters are a subset of what pktq_stats provides per precedence. */
+	uint32 retry;          /**< packets re-sent because they were not received */
+	uint32 retry_drop;     /**< packets finally dropped after retry limit */
+	uint32 rtsfail;        /**< count of rts attempts that failed to receive cts */
+	uint32 acked;          /**< count of packets sent (acked) successfully */
+	uint32 txrate_succ;    /**< running total of phy rate of packets sent successfully */
+	uint32 txrate_main;    /**< running total of phy 'main' rate */
+	uint32 throughput;     /**< actual data transferred successfully */
+	uint32 time_delta;     /**< time difference since last pktq_stats */
+	uint32 airtime;        /**< cumulative total medium access delay in useconds */
+} iov_bs_data_counters_t;
+
+/** The structure for individual station information. */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	struct ether_addr	station_address;	/**< The station MAC address */
+	uint16			station_flags;		/**< Bit mask of flags, for future use. */
+	iov_bs_data_counters_t	station_counters;	/**< The actual counter values */
+} BWL_POST_PACKED_STRUCT iov_bs_data_record_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16	structure_version;	/**< Structure version number (for wl/wlu matching) */
+	uint16	structure_count;	/**< Number of iov_bs_data_record_t records following */
+	iov_bs_data_record_t	structure_record[1];	/**< 0 - structure_count records */
+} BWL_POST_PACKED_STRUCT iov_bs_data_struct_t;
+#include <packed_section_end.h>
+
+/* Bitmask of options that can be passed in to the iovar. */
+enum {
+	SCB_BS_DATA_FLAG_NO_RESET = (1<<0)	/**< Do not clear the counters after reading */
+};
+/*
+ * SCB_BS_DATA iovar definitions end.
+ */
+
+typedef struct wlc_extlog_cfg {
+	int32 max_number;
+	uint16 module;	/**< bitmap */
+	uint8 level;
+	uint8 flag;
+	uint16 version;
+} wlc_extlog_cfg_t;
+
+typedef struct log_record {
+	uint32 time;
+	uint16 module;
+	uint16 id;
+	uint8 level;
+	uint8 sub_unit;
+	uint8 seq_num;
+	uint8 pad;
+	int32 arg;
+	char  str[MAX_ARGSTR_LEN];
+} log_record_t;
+
+typedef struct wlc_extlog_req {
+	uint32 from_last;
+	uint32 num;
+} wlc_extlog_req_t;
+
+typedef struct wlc_extlog_results {
+	uint16 version;
+	uint16 record_len;
+	uint32 num;
+	log_record_t logs[1];
+} wlc_extlog_results_t;
+
+typedef struct log_idstr {
+	uint16	id;
+	uint16	flag;
+	uint8	arg_type;
+	const char	*fmt_str;
+} log_idstr_t;
+
+#define FMTSTRF_USER		1
+
+/* flat ID definitions
+ * New definitions HAVE TO BE ADDED at the end of the table. Otherwise, it will
+ * affect backward compatibility with pre-existing apps
+ */
+typedef enum {
+	FMTSTR_DRIVER_UP_ID = 0,
+	FMTSTR_DRIVER_DOWN_ID = 1,
+	FMTSTR_SUSPEND_MAC_FAIL_ID = 2,
+	FMTSTR_NO_PROGRESS_ID = 3,
+	FMTSTR_RFDISABLE_ID = 4,
+	FMTSTR_REG_PRINT_ID = 5,
+	FMTSTR_EXPTIME_ID = 6,
+	FMTSTR_JOIN_START_ID = 7,
+	FMTSTR_JOIN_COMPLETE_ID = 8,
+	FMTSTR_NO_NETWORKS_ID = 9,
+	FMTSTR_SECURITY_MISMATCH_ID = 10,
+	FMTSTR_RATE_MISMATCH_ID = 11,
+	FMTSTR_AP_PRUNED_ID = 12,
+	FMTSTR_KEY_INSERTED_ID = 13,
+	FMTSTR_DEAUTH_ID = 14,
+	FMTSTR_DISASSOC_ID = 15,
+	FMTSTR_LINK_UP_ID = 16,
+	FMTSTR_LINK_DOWN_ID = 17,
+	FMTSTR_RADIO_HW_OFF_ID = 18,
+	FMTSTR_RADIO_HW_ON_ID = 19,
+	FMTSTR_EVENT_DESC_ID = 20,
+	FMTSTR_PNP_SET_POWER_ID = 21,
+	FMTSTR_RADIO_SW_OFF_ID = 22,
+	FMTSTR_RADIO_SW_ON_ID = 23,
+	FMTSTR_PWD_MISMATCH_ID = 24,
+	FMTSTR_FATAL_ERROR_ID = 25,
+	FMTSTR_AUTH_FAIL_ID = 26,
+	FMTSTR_ASSOC_FAIL_ID = 27,
+	FMTSTR_IBSS_FAIL_ID = 28,
+	FMTSTR_EXTAP_FAIL_ID = 29,
+	FMTSTR_MAX_ID
+} log_fmtstr_id_t;
+
+/** 11k Neighbor Report element (unversioned, deprecated) */
+typedef struct nbr_element {
+	uint8 id;
+	uint8 len;
+	struct ether_addr bssid;
+	uint32 bssid_info;
+	uint8 reg;
+	uint8 channel;
+	uint8 phytype;
+	uint8 pad;
+} nbr_element_t;
+
+#define WL_RRM_NBR_RPT_VER		1
+/** 11k Neighbor Report element */
+typedef struct nbr_rpt_elem {
+	uint8 version;
+	uint8 id;
+	uint8 len;
+	uint8 pad;
+	struct ether_addr bssid;
+	uint8 pad_1[2];
+	uint32 bssid_info;
+	uint8 reg;
+	uint8 channel;
+	uint8 phytype;
+	uint8 pad_2;
+	wlc_ssid_t ssid;
+	chanspec_t chanspec;
+	uint8 bss_trans_preference;
+	uint8 flags;
+} nbr_rpt_elem_t;
+
+typedef enum event_msgs_ext_command {
+	EVENTMSGS_NONE		=	0,
+	EVENTMSGS_SET_BIT	=	1,
+	EVENTMSGS_RESET_BIT	=	2,
+	EVENTMSGS_SET_MASK	=	3
+} event_msgs_ext_command_t;
+
+#define EVENTMSGS_VER 1
+#define EVENTMSGS_EXT_STRUCT_SIZE	OFFSETOF(eventmsgs_ext_t, mask[0])
+
+/* len-	for SET it would be mask size from the application to the firmware */
+/*		for GET it would be actual firmware mask size */
+/* maxgetsize -	is only used for GET. indicate max mask size that the */
+/*				application can read from the firmware */
+typedef struct eventmsgs_ext
+{
+	uint8	ver;
+	uint8	command;
+	uint8	len;
+	uint8	maxgetsize;
+	uint8	mask[1];
+} eventmsgs_ext_t;
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct pcie_bus_tput_params {
+	/** no of host dma descriptors programmed by the firmware before a commit */
+	uint16		max_dma_descriptors;
+
+	uint16		host_buf_len; /**< length of host buffer */
+	dmaaddr_t	host_buf_addr; /**< physical address for bus_throughput_buf */
+} BWL_POST_PACKED_STRUCT pcie_bus_tput_params_t;
+#include <packed_section_end.h>
+
+typedef struct pcie_bus_tput_stats {
+	uint16		time_taken; /**< no of secs the test is run */
+	uint16		nbytes_per_descriptor; /**< no of bytes of data dma ed per descriptor */
+
+	/** no of desciptors for which dma is sucessfully completed within the test time */
+	uint32		count;
+} pcie_bus_tput_stats_t;
+
+typedef struct keepalives_max_idle {
+	uint16  keepalive_count;        /**< nmbr of keepalives per bss_max_idle period */
+	uint8   mkeepalive_index;       /**< mkeepalive_index for keepalive frame to be used */
+	uint8   PAD;			/**< to align next field */
+	uint16  max_interval;           /**< seconds */
+} keepalives_max_idle_t;
+
+#define PM_IGNORE_BCMC_PROXY_ARP (1 << 0)
+#define PM_IGNORE_BCMC_ALL_DMS_ACCEPTED (1 << 1)
+
+/* ##### Power Stats section ##### */
+
+#define WL_PWRSTATS_VERSION	2
+
+/** Input structure for pwrstats IOVAR */
+typedef struct wl_pwrstats_query {
+	uint16 length;		/**< Number of entries in type array. */
+	uint16 type[1];		/**< Types (tags) to retrieve.
+				 * Length 0 (no types) means get all.
+				 */
+} wl_pwrstats_query_t;
+
+/** This structure is for version 2; version 1 will be deprecated in by FW */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_pwrstats {
+	uint16 version;		      /**< Version = 2 is TLV format */
+	uint16 length;		      /**< Length of entire structure */
+	uint8 data[1];		      /**< TLV data, a series of structures,
+				       * each starting with type and length.
+				       *
+				       * Padded as necessary so each section
+				       * starts on a 4-byte boundary.
+				       *
+				       * Both type and len are uint16, but the
+				       * upper nibble of length is reserved so
+				       * valid len values are 0-4095.
+				       */
+} BWL_POST_PACKED_STRUCT wl_pwrstats_t;
+#include <packed_section_end.h>
+#define WL_PWR_STATS_HDRLEN	OFFSETOF(wl_pwrstats_t, data)
+
+/* Bits for wake reasons */
+#define WLC_PMD_WAKE_SET		0x1
+#define WLC_PMD_PM_AWAKE_BCN		0x2
+/* BIT:3 is no longer being used */
+#define WLC_PMD_SCAN_IN_PROGRESS	0x8
+#define WLC_PMD_RM_IN_PROGRESS		0x10
+#define WLC_PMD_AS_IN_PROGRESS		0x20
+#define WLC_PMD_PM_PEND			0x40
+#define WLC_PMD_PS_POLL			0x80
+#define WLC_PMD_CHK_UNALIGN_TBTT	0x100
+#define WLC_PMD_APSD_STA_UP		0x200
+#define WLC_PMD_TX_PEND_WAR		0x400   /* obsolete, can be reused */
+#define WLC_PMD_GPTIMER_STAY_AWAKE	0x800
+#define WLC_PMD_PM2_RADIO_SOFF_PEND	0x2000
+#define WLC_PMD_NON_PRIM_STA_UP		0x4000
+#define WLC_PMD_AP_UP			0x8000
+
+typedef struct wlc_pm_debug {
+	uint32 timestamp;	     /**< timestamp in millisecond */
+	uint32 reason;		     /**< reason(s) for staying awake */
+} wlc_pm_debug_t;
+
+/** WL_PWRSTATS_TYPE_PM_AWAKE1 structures (for 6.25 firmware) */
+#define WLC_STA_AWAKE_STATES_MAX_V1	30
+#define WLC_PMD_EVENT_MAX_V1		32
+/** Data sent as part of pwrstats IOVAR (and EXCESS_PM_WAKE event) */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct pm_awake_data_v1 {
+	uint32 curr_time;	/**< ms */
+	uint32 hw_macc;		/**< HW maccontrol */
+	uint32 sw_macc;		/**< SW maccontrol */
+	uint32 pm_dur;		/**< Total sleep time in PM, msecs */
+	uint32 mpc_dur;		/**< Total sleep time in MPC, msecs */
+
+	/* int32 drifts = remote - local; +ve drift => local-clk slow */
+	int32 last_drift;	/**< Most recent TSF drift from beacon */
+	int32 min_drift;	/**< Min TSF drift from beacon in magnitude */
+	int32 max_drift;	/**< Max TSF drift from beacon in magnitude */
+
+	uint32 avg_drift;	/**< Avg TSF drift from beacon */
+
+	/* Wake history tracking */
+	uint8  pmwake_idx;				   /**< for stepping through pm_state */
+	wlc_pm_debug_t pm_state[WLC_STA_AWAKE_STATES_MAX_V1]; /**< timestamped wake bits */
+	uint32 pmd_event_wake_dur[WLC_PMD_EVENT_MAX_V1];   /**< cumulative usecs per wake reason */
+	uint32 drift_cnt;	/**< Count of drift readings over which avg_drift was computed */
+} BWL_POST_PACKED_STRUCT pm_awake_data_v1_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_pm_awake_stats_v1 {
+	uint16 type;	     /**< WL_PWRSTATS_TYPE_PM_AWAKE */
+	uint16 len;	     /**< Up to 4K-1, top 4 bits are reserved */
+
+	pm_awake_data_v1_t awake_data;
+	uint32 frts_time;	/**< Cumulative ms spent in frts since driver load */
+	uint32 frts_end_cnt;	/**< No of times frts ended since driver load */
+} BWL_POST_PACKED_STRUCT wl_pwr_pm_awake_stats_v1_t;
+#include <packed_section_end.h>
+
+/** WL_PWRSTATS_TYPE_PM_AWAKE2 structures. Data sent as part of pwrstats IOVAR */
+typedef struct pm_awake_data_v2 {
+	uint32 curr_time;	/**< ms */
+	uint32 hw_macc;		/**< HW maccontrol */
+	uint32 sw_macc;		/**< SW maccontrol */
+	uint32 pm_dur;		/**< Total sleep time in PM, msecs */
+	uint32 mpc_dur;		/**< Total sleep time in MPC, msecs */
+
+	/* int32 drifts = remote - local; +ve drift => local-clk slow */
+	int32 last_drift;	/**< Most recent TSF drift from beacon */
+	int32 min_drift;	/**< Min TSF drift from beacon in magnitude */
+	int32 max_drift;	/**< Max TSF drift from beacon in magnitude */
+
+	uint32 avg_drift;	/**< Avg TSF drift from beacon */
+
+	/* Wake history tracking */
+
+	/* pmstate array (type wlc_pm_debug_t) start offset */
+	uint16 pm_state_offset;
+	/** pmstate number of array entries */
+	uint16 pm_state_len;
+
+	/** array (type uint32) start offset */
+	uint16 pmd_event_wake_dur_offset;
+	/** pmd_event_wake_dur number of array entries */
+	uint16 pmd_event_wake_dur_len;
+
+	uint32 drift_cnt;	/**< Count of drift readings over which avg_drift was computed */
+	uint8  pmwake_idx;	/**< for stepping through pm_state */
+	uint8  flags;		/**< bit0: 1-sleep, 0- wake. bit1: 0-bit0 invlid, 1-bit0 valid */
+	uint8  pad[2];
+	uint32 frts_time;	/**< Cumulative ms spent in frts since driver load */
+	uint32 frts_end_cnt;	/**< No of times frts ended since driver load */
+} pm_awake_data_v2_t;
+
+typedef struct wl_pwr_pm_awake_stats_v2 {
+	uint16 type;	     /**< WL_PWRSTATS_TYPE_PM_AWAKE */
+	uint16 len;	     /**< Up to 4K-1, top 4 bits are reserved */
+
+	pm_awake_data_v2_t awake_data;
+} wl_pwr_pm_awake_stats_v2_t;
+
+/* bit0: 1-sleep, 0- wake. bit1: 0-bit0 invlid, 1-bit0 valid */
+#define WL_PWR_PM_AWAKE_STATS_WAKE      0x02
+#define WL_PWR_PM_AWAKE_STATS_ASLEEP    0x03
+#define WL_PWR_PM_AWAKE_STATS_WAKE_MASK 0x03
+
+/* WL_PWRSTATS_TYPE_PM_AWAKE Version 2 structures taken from 4324/43342 */
+/* These structures are only to be used with 4324/43342 devices */
+
+#define WL_STA_AWAKE_STATES_MAX_V2	30
+#define WL_PMD_EVENT_MAX_V2		32
+#define MAX_P2P_BSS_DTIM_PRD		4
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct ucode_dbg_v2 {
+	uint32 macctrl;
+	uint16 m_p2p_hps;
+	uint16 m_p2p_bss_dtim_prd[MAX_P2P_BSS_DTIM_PRD];
+	uint32 psmdebug[20];
+	uint32 phydebug[20];
+	uint32 psm_brc;
+	uint32 ifsstat;
+} BWL_POST_PACKED_STRUCT ucode_dbg_v2_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct pmalert_awake_data_v2 {
+	uint32 curr_time;	/* ms */
+	uint32 hw_macc;		/* HW maccontrol */
+	uint32 sw_macc;		/* SW maccontrol */
+	uint32 pm_dur;		/* Total sleep time in PM, msecs */
+	uint32 mpc_dur;		/* Total sleep time in MPC, msecs */
+
+	/* int32 drifts = remote - local; +ve drift => local-clk slow */
+	int32 last_drift;	/* Most recent TSF drift from beacon */
+	int32 min_drift;	/* Min TSF drift from beacon in magnitude */
+	int32 max_drift;	/* Max TSF drift from beacon in magnitude */
+
+	uint32 avg_drift;	/* Avg TSF drift from beacon */
+
+	/* Wake history tracking */
+	uint8  pmwake_idx;				   /* for stepping through pm_state */
+	wlc_pm_debug_t pm_state[WL_STA_AWAKE_STATES_MAX_V2]; /* timestamped wake bits */
+	uint32 pmd_event_wake_dur[WL_PMD_EVENT_MAX_V2];      /* cumulative usecs per wake reason */
+	uint32 drift_cnt;	/* Count of drift readings over which avg_drift was computed */
+	uint32	start_event_dur[WL_PMD_EVENT_MAX_V2]; /* start event-duration */
+	ucode_dbg_v2_t ud;
+	uint32 frts_time;	/* Cumulative ms spent in frts since driver load */
+	uint32 frts_end_cnt;	/* No of times frts ended since driver load */
+} BWL_POST_PACKED_STRUCT pmalert_awake_data_v2_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct pm_alert_data_v2 {
+	uint32 version;
+	uint32 length; /* Length of entire structure */
+	uint32 reasons; /* reason(s) for pm_alert */
+	/* Following fields are present only for reasons
+	 * PM_DUR_EXCEEDED, MPC_DUR_EXCEEDED & CONST_AWAKE_DUR_EXCEEDED
+	 */
+	uint32 prev_stats_time;	/* msecs */
+	uint32 prev_pm_dur;	/* msecs */
+	uint32 prev_mpc_dur;	/* msecs */
+	pmalert_awake_data_v2_t awake_data;
+} BWL_POST_PACKED_STRUCT pm_alert_data_v2_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_pm_awake_status_v2 {
+	uint16 type;	     /* WL_PWRSTATS_TYPE_PM_AWAKE */
+	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
+
+	pmalert_awake_data_v2_t awake_data;
+	uint32 frts_time;	/* Cumulative ms spent in frts since driver load */
+	uint32 frts_end_cnt;	/* No of times frts ended since driver load */
+} BWL_POST_PACKED_STRUCT wl_pwr_pm_awake_status_v2_t;
+#include <packed_section_end.h>
+
+/* Below are latest definitions from PHO25178RC100_BRANCH_6_50 */
+/* wl_pwr_pm_awake_stats_v1_t is used for WL_PWRSTATS_TYPE_PM_AWAKE */
+/* (at least) the chip independent registers */
+typedef struct ucode_dbg_ext {
+	uint32 x120;
+	uint32 x124;
+	uint32 x154;
+	uint32 x158;
+	uint32 x15c;
+	uint32 x180;
+	uint32 x184;
+	uint32 x188;
+	uint32 x18c;
+	uint32 x1a0;
+	uint32 x1a8;
+	uint32 x1e0;
+	uint32 scr_x14;
+	uint32 scr_x2b;
+	uint32 scr_x2c;
+	uint32 scr_x2d;
+	uint32 scr_x2e;
+
+	uint16 x40a;
+	uint16 x480;
+	uint16 x490;
+	uint16 x492;
+	uint16 x4d8;
+	uint16 x4b8;
+	uint16 x4ba;
+	uint16 x4bc;
+	uint16 x4be;
+	uint16 x500;
+	uint16 x50e;
+	uint16 x522;
+	uint16 x546;
+	uint16 x578;
+	uint16 x602;
+	uint16 x646;
+	uint16 x648;
+	uint16 x666;
+	uint16 x670;
+	uint16 x690;
+	uint16 x692;
+	uint16 x6a0;
+	uint16 x6a2;
+	uint16 x6a4;
+	uint16 x6b2;
+	uint16 x7c0;
+
+	uint16 shm_x20;
+	uint16 shm_x4a;
+	uint16 shm_x5e;
+	uint16 shm_x5f;
+	uint16 shm_xaab;
+	uint16 shm_x74a;
+	uint16 shm_x74b;
+	uint16 shm_x74c;
+	uint16 shm_x74e;
+	uint16 shm_x756;
+	uint16 shm_x75b;
+	uint16 shm_x7b9;
+	uint16 shm_x7d4;
+
+	uint16 shm_P2P_HPS;
+	uint16 shm_P2P_intr[16];
+	uint16 shm_P2P_perbss[48];
+} ucode_dbg_ext_t;
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct pm_alert_data_v1 {
+	uint32 version;
+	uint32 length; /**< Length of entire structure */
+	uint32 reasons; /**< reason(s) for pm_alert */
+	/* Following fields are present only for reasons
+	 * PM_DUR_EXCEEDED, MPC_DUR_EXCEEDED & CONST_AWAKE_DUR_EXCEEDED
+	 */
+	uint32 prev_stats_time;	/**< msecs */
+	uint32 prev_pm_dur;	/**< msecs */
+	uint32 prev_mpc_dur;	/**< msecs */
+	pm_awake_data_v1_t awake_data;
+	uint32	start_event_dur[WLC_PMD_EVENT_MAX_V1]; /**< start event-duration */
+	ucode_dbg_v2_t ud;
+	uint32 frts_time;	/**< Cumulative ms spent in frts since driver load */
+	uint32 frts_end_cnt;	/**< No of times frts ended since driver load */
+	ucode_dbg_ext_t ud_ext;
+	uint32 prev_frts_dur; /**< ms */
+} BWL_POST_PACKED_STRUCT pm_alert_data_v1_t;
+#include <packed_section_end.h>
+
+/* End of 43342/4324 v2 structure definitions */
+
+/* Original bus structure is for HSIC */
+
+typedef struct bus_metrics {
+	uint32 suspend_ct;	/**< suspend count */
+	uint32 resume_ct;	/**< resume count */
+	uint32 disconnect_ct;	/**< disconnect count */
+	uint32 reconnect_ct;	/**< reconnect count */
+	uint32 active_dur;	/**< msecs in bus, usecs for user */
+	uint32 suspend_dur;	/**< msecs in bus, usecs for user */
+	uint32 disconnect_dur;	/**< msecs in bus, usecs for user */
+} bus_metrics_t;
+
+/** Bus interface info for USB/HSIC */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_usb_hsic_stats {
+	uint16 type;	     /**< WL_PWRSTATS_TYPE_USB_HSIC */
+	uint16 len;	     /**< Up to 4K-1, top 4 bits are reserved */
+
+	bus_metrics_t hsic;	/**< stats from hsic bus driver */
+} BWL_POST_PACKED_STRUCT wl_pwr_usb_hsic_stats_t;
+#include <packed_section_end.h>
+
+typedef struct pcie_bus_metrics {
+	uint32 d3_suspend_ct;	/**< suspend count */
+	uint32 d0_resume_ct;	/**< resume count */
+	uint32 perst_assrt_ct;	/**< PERST# assert count */
+	uint32 perst_deassrt_ct;	/**< PERST# de-assert count */
+	uint32 active_dur;	/**< msecs */
+	uint32 d3_suspend_dur;	/**< msecs */
+	uint32 perst_dur;	/**< msecs */
+	uint32 l0_cnt;		/**< L0 entry count */
+	uint32 l0_usecs;	/**< L0 duration in usecs */
+	uint32 l1_cnt;		/**< L1 entry count */
+	uint32 l1_usecs;	/**< L1 duration in usecs */
+	uint32 l1_1_cnt;	/**< L1_1ss entry count */
+	uint32 l1_1_usecs;	/**< L1_1ss duration in usecs */
+	uint32 l1_2_cnt;	/**< L1_2ss entry count */
+	uint32 l1_2_usecs;	/**< L1_2ss duration in usecs */
+	uint32 l2_cnt;		/**< L2 entry count */
+	uint32 l2_usecs;	/**< L2 duration in usecs */
+	uint32 timestamp;	/**< Timestamp on when stats are collected */
+	uint32 num_h2d_doorbell;	/**< # of doorbell interrupts - h2d */
+	uint32 num_d2h_doorbell;	/**< # of doorbell interrupts - d2h */
+	uint32 num_submissions; /**< # of submissions */
+	uint32 num_completions; /**< # of completions */
+	uint32 num_rxcmplt;	/**< # of rx completions */
+	uint32 num_rxcmplt_drbl;	/**< of drbl interrupts for rx complt. */
+	uint32 num_txstatus;	/**< # of tx completions */
+	uint32 num_txstatus_drbl;	/**< of drbl interrupts for tx complt. */
+	uint32 deepsleep_count; /**< # of times chip went to deepsleep */
+	uint32 deepsleep_dur;   /**< # of msecs chip was in deepsleep */
+	uint32 ltr_active_ct;	/**< # of times chip went to LTR ACTIVE */
+	uint32 ltr_active_dur;	/**< # of msecs chip was in LTR ACTIVE */
+	uint32 ltr_sleep_ct;	/**< # of times chip went to LTR SLEEP */
+	uint32 ltr_sleep_dur;	/**< # of msecs chip was in LTR SLEEP */
+} pcie_bus_metrics_t;
+
+/** Bus interface info for PCIE */
+typedef struct wl_pwr_pcie_stats {
+	uint16 type;	     /**< WL_PWRSTATS_TYPE_PCIE */
+	uint16 len;	     /**< Up to 4K-1, top 4 bits are reserved */
+	pcie_bus_metrics_t pcie;	/**< stats from pcie bus driver */
+} wl_pwr_pcie_stats_t;
+
+/** Scan information history per category */
+typedef struct scan_data {
+	uint32 count;		/**< Number of scans performed */
+	uint32 dur;		/**< Total time (in us) used */
+} scan_data_t;
+
+typedef struct wl_pwr_scan_stats {
+	uint16 type;	     /**< WL_PWRSTATS_TYPE_SCAN */
+	uint16 len;	     /**< Up to 4K-1, top 4 bits are reserved */
+
+	/* Scan history */
+	scan_data_t user_scans;	  /**< User-requested scans: (i/e/p)scan */
+	scan_data_t assoc_scans;  /**< Scans initiated by association requests */
+	scan_data_t roam_scans;	  /**< Scans initiated by the roam engine */
+	scan_data_t pno_scans[8]; /**< For future PNO bucketing (BSSID, SSID, etc) */
+	scan_data_t other_scans;  /**< Scan engine usage not assigned to the above */
+} wl_pwr_scan_stats_t;
+
+typedef struct wl_pwr_connect_stats {
+	uint16 type;	     /**< WL_PWRSTATS_TYPE_SCAN */
+	uint16 len;	     /**< Up to 4K-1, top 4 bits are reserved */
+
+	/* Connection (Association + Key exchange) data */
+	uint32 count;	/**< Number of connections performed */
+	uint32 dur;		/**< Total time (in ms) used */
+} wl_pwr_connect_stats_t;
+
+typedef struct wl_pwr_phy_stats {
+	uint16 type;	    /**< WL_PWRSTATS_TYPE_PHY */
+	uint16 len;	    /**< Up to 4K-1, top 4 bits are reserved */
+	uint32 tx_dur;	    /**< TX Active duration in us */
+	uint32 rx_dur;	    /**< RX Active duration in us */
+} wl_pwr_phy_stats_t;
+
+
+typedef struct wl_mimo_meas_metrics_v1 {
+	uint16 type;
+	uint16 len;
+	/* Total time(us) idle in MIMO RX chain configuration */
+	uint32 total_idle_time_mimo;
+	/* Total time(us) idle in SISO  RX chain configuration */
+	uint32 total_idle_time_siso;
+	/* Total receive time (us) in SISO RX chain configuration */
+	uint32 total_rx_time_siso;
+	/* Total receive time (us) in MIMO RX chain configuration */
+	uint32 total_rx_time_mimo;
+	/* Total 1-chain transmit time(us) */
+	uint32 total_tx_time_1chain;
+	/* Total 2-chain transmit time(us) */
+	uint32 total_tx_time_2chain;
+	/* Total 3-chain transmit time(us) */
+	uint32 total_tx_time_3chain;
+} wl_mimo_meas_metrics_v1_t;
+
+typedef struct wl_mimo_meas_metrics {
+	uint16 type;
+	uint16 len;
+	/* Total time(us) idle in MIMO RX chain configuration */
+	uint32 total_idle_time_mimo;
+	/* Total time(us) idle in SISO  RX chain configuration */
+	uint32 total_idle_time_siso;
+	/* Total receive time (us) in SISO RX chain configuration */
+	uint32 total_rx_time_siso;
+	/* Total receive time (us) in MIMO RX chain configuration */
+	uint32 total_rx_time_mimo;
+	/* Total 1-chain transmit time(us) */
+	uint32 total_tx_time_1chain;
+	/* Total 2-chain transmit time(us) */
+	uint32 total_tx_time_2chain;
+	/* Total 3-chain transmit time(us) */
+	uint32 total_tx_time_3chain;
+	/* End of original, OCL fields start here */
+	/* Total time(us) idle in ocl mode */
+	uint32 total_idle_time_ocl;
+	/* Total receive time (us) in ocl mode */
+	uint32 total_rx_time_ocl;
+	/* End of OCL fields, internal adjustment fields here */
+	/* Total SIFS idle time in MIMO mode */
+	uint32 total_sifs_time_mimo;
+	/* Total SIFS idle time in SISO mode */
+	uint32 total_sifs_time_siso;
+} wl_mimo_meas_metrics_t;
+/* ##### End of Power Stats section ##### */
+
+/** IPV4 Arp offloads for ndis context */
+#include <packed_section_start.h>
+BWL_PRE_PACKED_STRUCT struct hostip_id {
+	struct ipv4_addr ipa;
+	uint8 id;
+} BWL_POST_PACKED_STRUCT;
+#include <packed_section_end.h>
+
+/* Return values */
+#define ND_REPLY_PEER		0x1	/**< Reply was sent to service NS request from peer */
+#define ND_REQ_SINK		0x2	/**< Input packet should be discarded */
+#define ND_FORCE_FORWARD	0X3	/**< For the dongle to forward req to HOST */
+
+/** Neighbor Solicitation Response Offload IOVAR param */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct nd_param {
+	struct ipv6_addr	host_ip[2];
+	struct ipv6_addr	solicit_ip;
+	struct ipv6_addr	remote_ip;
+	uint8	host_mac[ETHER_ADDR_LEN];
+	uint32	offload_id;
+} BWL_POST_PACKED_STRUCT nd_param_t;
+#include <packed_section_end.h>
+
+typedef struct wl_pfn_roam_thresh {
+	uint32 pfn_alert_thresh; /**< time in ms */
+	uint32 roam_alert_thresh; /**< time in ms */
+} wl_pfn_roam_thresh_t;
+
+
+/* Reasons for wl_pmalert_t */
+#define PM_DUR_EXCEEDED			(1<<0)
+#define MPC_DUR_EXCEEDED		(1<<1)
+#define ROAM_ALERT_THRESH_EXCEEDED	(1<<2)
+#define PFN_ALERT_THRESH_EXCEEDED	(1<<3)
+#define CONST_AWAKE_DUR_ALERT		(1<<4)
+#define CONST_AWAKE_DUR_RECOVERY	(1<<5)
+
+#define MIN_PM_ALERT_LEN 9
+
+/** Data sent in EXCESS_PM_WAKE event */
+#define WL_PM_ALERT_VERSION 3
+
+/** This structure is for version 3; version 2 will be deprecated in by FW */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_pmalert {
+	uint16 version;		/**< Version = 3 is TLV format */
+	uint16 length;		/**< Length of entire structure */
+	uint32 reasons;		/**< reason(s) for pm_alert */
+	uint8 data[1];		/**< TLV data, a series of structures,
+				 * each starting with type and length.
+				 *
+				 * Padded as necessary so each section
+				 * starts on a 4-byte boundary.
+				 *
+				 * Both type and len are uint16, but the
+				 * upper nibble of length is reserved so
+				 * valid len values are 0-4095.
+				*/
+} BWL_POST_PACKED_STRUCT wl_pmalert_t;
+#include <packed_section_end.h>
+
+/* Type values for the data section */
+#define WL_PMALERT_FIXED	0	/**< struct wl_pmalert_fixed_t, fixed fields */
+#define WL_PMALERT_PMSTATE	1	/**< struct wl_pmalert_pmstate_t, variable */
+#define WL_PMALERT_EVENT_DUR	2	/**< struct wl_pmalert_event_dur_t, variable */
+#define WL_PMALERT_UCODE_DBG	3	/**< struct wl_pmalert_ucode_dbg_v1, variable */
+#define WL_PMALERT_PS_ALLOWED_HIST	4 /**< struct wl_pmalert_ps_allowed_history, variable */
+#define WL_PMALERT_EXT_UCODE_DBG	5 /**< struct wl_pmalert_ext_ucode_dbg_t, variable */
+#define WL_PMALERT_EPM_START_EVENT_DUR	6 /**< struct wl_pmalert_event_dur_t, variable */
+#define WL_PMALERT_UCODE_DBG_V2		7 /**< struct wl_pmalert_ucode_dbg_v2, variable */
+
+typedef struct wl_pmalert_fixed {
+	uint16 type;		/**< WL_PMALERT_FIXED */
+	uint16 len;		/**< Up to 4K-1, top 4 bits are reserved */
+	uint32 prev_stats_time;	/**< msecs */
+	uint32 curr_time;	/**< ms */
+	uint32 prev_pm_dur;	/**< msecs */
+	uint32 pm_dur;		/**< Total sleep time in PM, msecs */
+	uint32 prev_mpc_dur;	/**< msecs */
+	uint32 mpc_dur;		/**< Total sleep time in MPC, msecs */
+	uint32 hw_macc;		/**< HW maccontrol */
+	uint32 sw_macc;		/**< SW maccontrol */
+
+	/* int32 drifts = remote - local; +ve drift -> local-clk slow */
+	int32 last_drift;	/**< Most recent TSF drift from beacon */
+	int32 min_drift;	/**< Min TSF drift from beacon in magnitude */
+	int32 max_drift;	/**< Max TSF drift from beacon in magnitude */
+
+	uint32 avg_drift;	/**< Avg TSF drift from beacon */
+	uint32 drift_cnt;	/**< Count of drift readings over which avg_drift was computed */
+	uint32 frts_time;	/**< Cumulative ms spent in data frts since driver load */
+	uint32 frts_end_cnt;	/**< No of times frts ended since driver load */
+	uint32 prev_frts_dur;	/**< Data frts duration at start of pm-period */
+	uint32 cal_dur;		/**< Cumulative ms spent in calibration */
+	uint32 prev_cal_dur;	/**< cal duration at start of pm-period */
+} wl_pmalert_fixed_t;
+
+typedef struct wl_pmalert_pmstate {
+	uint16 type;	     /**< WL_PMALERT_PMSTATE */
+	uint16 len;	     /**< Up to 4K-1, top 4 bits are reserved */
+
+	uint8 pmwake_idx;   /**< for stepping through pm_state */
+	uint8 pad[3];
+	/* Array of pmstate; len of array is based on tlv len */
+	wlc_pm_debug_t pmstate[1];
+} wl_pmalert_pmstate_t;
+
+typedef struct wl_pmalert_event_dur {
+	uint16 type;	     /**< WL_PMALERT_EVENT_DUR */
+	uint16 len;	     /**< Up to 4K-1, top 4 bits are reserved */
+
+	/* Array of event_dur, len of array is based on tlv len */
+	uint32 event_dur[1];
+} wl_pmalert_event_dur_t;
+
+#include <packed_section_start.h>
+BWL_PRE_PACKED_STRUCT struct wl_pmalert_ucode_dbg_v1 {
+	uint16 type;         /* WL_PMALERT_UCODE_DBG */
+	uint16 len;      /* Up to 4K-1, top 4 bits are reserved */
+	uint32 macctrl;
+	uint16 m_p2p_hps;
+	uint32 psm_brc;
+	uint32 ifsstat;
+	uint16 m_p2p_bss_dtim_prd[MAX_P2P_BSS_DTIM_PRD];
+	uint32 psmdebug[20];
+	uint32 phydebug[20];
+	uint16 M_P2P_BSS[3][12];
+	uint16 M_P2P_PRE_TBTT[3];
+
+	/* Following is valid only for corerevs<40 */
+	uint16 xmtfifordy;
+
+	/* Following 3 are valid only for 11ac corerevs (>=40) */
+	uint16 psm_maccommand;
+	uint16 txe_status1;
+	uint16 AQMFifoReady;
+} BWL_POST_PACKED_STRUCT;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+BWL_PRE_PACKED_STRUCT struct wl_pmalert_ucode_dbg_v2 {
+	uint16 type;	     /**< WL_PMALERT_UCODE_DBG_V2 */
+	uint16 len;	     /**< Up to 4K-1, top 4 bits are reserved */
+	uint32 macctrl;
+	uint16 m_p2p_hps;
+	uint32 psm_brc;
+	uint32 ifsstat;
+	uint16 m_p2p_bss_dtim_prd[MAX_P2P_BSS_DTIM_PRD];
+	uint32 psmdebug[20];
+	uint32 phydebug[20];
+	uint16 M_P2P_BSS[3][12];
+	uint16 M_P2P_PRE_TBTT[3];
+
+	/* Following is valid only for corerevs<40 */
+	uint16 xmtfifordy;
+
+	/* Following 3 are valid only for 11ac corerevs (>=40) */
+	uint16 psm_maccommand;
+	uint16 txe_status1;
+	uint32 AQMFifoReady;
+} BWL_POST_PACKED_STRUCT;
+#include <packed_section_end.h>
+
+
+/* Structures and constants used for "vndr_ie" IOVar interface */
+#define VNDR_IE_CMD_LEN		4	/**< length of the set command string:
+					 * "add", "del" (+ NUL)
+					 */
+
+#define VNDR_IE_INFO_HDR_LEN	(sizeof(uint32))
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 pktflag;			/**< bitmask indicating which packet(s) contain this IE */
+	vndr_ie_t vndr_ie_data;		/**< vendor IE data */
+} BWL_POST_PACKED_STRUCT vndr_ie_info_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	int32 iecount;			/**< number of entries in the vndr_ie_list[] array */
+	vndr_ie_info_t vndr_ie_list[1];	/**< variable size list of vndr_ie_info_t structs */
+} BWL_POST_PACKED_STRUCT vndr_ie_buf_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	char cmd[VNDR_IE_CMD_LEN];	/**< vndr_ie IOVar set command : "add", "del" + NUL */
+	vndr_ie_buf_t vndr_ie_buffer;	/**< buffer containing Vendor IE list information */
+} BWL_POST_PACKED_STRUCT vndr_ie_setbuf_t;
+#include <packed_section_end.h>
+
+/** tag_ID/length/value_buffer tuple */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint8	id;
+	uint8	len;
+	uint8	data[1];
+} BWL_POST_PACKED_STRUCT tlv_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 pktflag;			/**< bitmask indicating which packet(s) contain this IE */
+	tlv_t ie_data;		/**< IE data */
+} BWL_POST_PACKED_STRUCT ie_info_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	int32 iecount;			/**< number of entries in the ie_list[] array */
+	ie_info_t ie_list[1];	/**< variable size list of ie_info_t structs */
+} BWL_POST_PACKED_STRUCT ie_buf_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	char cmd[VNDR_IE_CMD_LEN];	/**< ie IOVar set command : "add" + NUL */
+	ie_buf_t ie_buffer;	/**< buffer containing IE list information */
+} BWL_POST_PACKED_STRUCT ie_setbuf_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 pktflag;		/**< bitmask indicating which packet(s) contain this IE */
+	uint8 id;		/**< IE type */
+} BWL_POST_PACKED_STRUCT ie_getbuf_t;
+#include <packed_section_end.h>
+
+/* structures used to define format of wps ie data from probe requests */
+/* passed up to applications via iovar "prbreq_wpsie" */
+typedef struct sta_prbreq_wps_ie_hdr {
+	struct ether_addr staAddr;
+	uint16 ieLen;
+} sta_prbreq_wps_ie_hdr_t;
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data {
+	sta_prbreq_wps_ie_hdr_t hdr;
+	uint8 ieData[1];
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list {
+	uint32 totLen;
+	uint8 ieDataList[1];
+} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t;
+#include <packed_section_end.h>
+
+
+#ifdef WLMEDIA_TXFAILEVENT
+typedef struct {
+	uint8   dest[ETHER_ADDR_LEN]; /**< destination MAC */
+	uint8  prio;            /**< Packet Priority */
+	uint8  flags;           /**< Flags           */
+	uint32 tsf_l;           /**< TSF timer low   */
+	uint32 tsf_h;           /**< TSF timer high  */
+	uint16 rates;           /**< Main Rates      */
+	uint16 txstatus;        /**< TX Status       */
+} txfailinfo_t;
+#endif /* WLMEDIA_TXFAILEVENT */
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 flags;
+	chanspec_t chanspec;			/**< txpwr report for this channel */
+	chanspec_t local_chanspec;		/**< channel on which we are associated */
+	uint8 local_max;			/**< local max according to the AP */
+	uint8 local_constraint;			/**< local constraint according to the AP */
+	int8  antgain[2];			/**< Ant gain for each band - from SROM */
+	uint8 rf_cores;				/**< count of RF Cores being reported */
+	uint8 est_Pout[4];			/**< Latest tx power out estimate per RF chain */
+	uint8 est_Pout_act[4]; /**< Latest tx power out estimate per RF chain w/o adjustment */
+	uint8 est_Pout_cck;			/**< Latest CCK tx power out estimate */
+	uint8 tx_power_max[4];			/**< Maximum target power among all rates */
+	uint32 tx_power_max_rate_ind[4];  /**< Index of the rate with the max target power */
+	int8 sar;				/**< SAR limit for display by wl executable */
+	int8 channel_bandwidth;		/**< 20, 40 or 80 MHz bandwidth? */
+	uint8 version;				/**< Version of the data format wlu <--> driver */
+	uint8 display_core;			/**< Displayed curpower core */
+	int8 target_offsets[4];		/**< Target power offsets for current rate per core */
+	uint32 last_tx_ratespec;	/**< Ratespec for last transmition */
+	uint32 user_target;		/**< user limit */
+	uint32 ppr_len;		/**< length of each ppr serialization buffer */
+	int8 SARLIMIT[MAX_STREAMS_SUPPORTED];
+	uint8  pprdata[1];		/**< ppr serialization buffer */
+} BWL_POST_PACKED_STRUCT tx_pwr_rpt_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	struct ipv4_addr	ipv4_addr;
+	struct ether_addr nexthop;
+} BWL_POST_PACKED_STRUCT ibss_route_entry_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint32 num_entry;
+	ibss_route_entry_t route_entry[1];
+} BWL_POST_PACKED_STRUCT ibss_route_tbl_t;
+#include <packed_section_end.h>
+
+#define MAX_IBSS_ROUTE_TBL_ENTRY	64
+
+#define TXPWR_TARGET_VERSION  0
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	int32 version;		/**< version number */
+	chanspec_t chanspec;	/**< txpwr report for this channel */
+	int8 txpwr[WL_STA_ANT_MAX]; /**< Max tx target power, in qdb */
+	uint8 rf_cores;		/**< count of RF Cores being reported */
+} BWL_POST_PACKED_STRUCT txpwr_target_max_t;
+#include <packed_section_end.h>
+
+#define BSS_PEER_INFO_PARAM_CUR_VER	0
+/** Input structure for IOV_BSS_PEER_INFO */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT	struct {
+	uint16			version;
+	struct	ether_addr ea;	/**< peer MAC address */
+} BWL_POST_PACKED_STRUCT bss_peer_info_param_t;
+#include <packed_section_end.h>
+
+#define BSS_PEER_INFO_CUR_VER		0
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16			version;
+	struct ether_addr	ea;
+	int32			rssi;
+	uint32			tx_rate;	/**< current tx rate */
+	uint32			rx_rate;	/**< current rx rate */
+	wl_rateset_t		rateset;	/**< rateset in use */
+	uint32			age;		/**< age in seconds */
+} BWL_POST_PACKED_STRUCT bss_peer_info_t;
+#include <packed_section_end.h>
+
+#define BSS_PEER_LIST_INFO_CUR_VER	0
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16			version;
+	uint16			bss_peer_info_len;	/**< length of bss_peer_info_t */
+	uint32			count;			/**< number of peer info */
+	bss_peer_info_t		peer_info[1];		/**< peer info */
+} BWL_POST_PACKED_STRUCT bss_peer_list_info_t;
+#include <packed_section_end.h>
+
+#define BSS_PEER_LIST_INFO_FIXED_LEN OFFSETOF(bss_peer_list_info_t, peer_info)
+
+#define AIBSS_BCN_FORCE_CONFIG_VER_0	0
+
+/** structure used to configure AIBSS beacon force xmit */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16  version;
+	uint16	len;
+	uint32 initial_min_bcn_dur;	/**< dur in ms to check a bcn in bcn_flood period */
+	uint32 min_bcn_dur;	/**< dur in ms to check a bcn after bcn_flood period */
+	uint32 bcn_flood_dur; /**< Initial bcn xmit period in ms */
+} BWL_POST_PACKED_STRUCT aibss_bcn_force_config_t;
+#include <packed_section_end.h>
+
+#define AIBSS_TXFAIL_CONFIG_VER_0    0
+#define AIBSS_TXFAIL_CONFIG_VER_1    1
+#define AIBSS_TXFAIL_CONFIG_CUR_VER		AIBSS_TXFAIL_CONFIG_VER_1
+
+/** structure used to configure aibss tx fail event */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint16  version;
+	uint16  len;
+	uint32 bcn_timeout;     /**< dur in seconds to receive 1 bcn */
+	uint32 max_tx_retry;     /**< no of consecutive no acks to send txfail event */
+	uint32 max_atim_failure; /**< no of consecutive atim failure */
+} BWL_POST_PACKED_STRUCT aibss_txfail_config_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_aibss_if {
+	uint16 version;
+	uint16 len;
+	uint32 flags;
+	struct ether_addr addr;
+	chanspec_t chspec;
+} BWL_POST_PACKED_STRUCT wl_aibss_if_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wlc_ipfo_route_entry {
+	struct ipv4_addr ip_addr;
+	struct ether_addr nexthop;
+} BWL_POST_PACKED_STRUCT wlc_ipfo_route_entry_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wlc_ipfo_route_tbl {
+	uint32 num_entry;
+	wlc_ipfo_route_entry_t route_entry[1];
+} BWL_POST_PACKED_STRUCT wlc_ipfo_route_tbl_t;
+#include <packed_section_end.h>
+
+#define WL_IPFO_ROUTE_TBL_FIXED_LEN 4
+#define WL_MAX_IPFO_ROUTE_TBL_ENTRY	64
+
+	/* Global ASSERT Logging */
+#define ASSERTLOG_CUR_VER	0x0100
+#define MAX_ASSRTSTR_LEN	64
+
+	typedef struct assert_record {
+		uint32 time;
+		uint8 seq_num;
+		int8 str[MAX_ASSRTSTR_LEN];
+	} assert_record_t;
+
+	typedef struct assertlog_results {
+		uint16 version;
+		uint16 record_len;
+		uint32 num;
+		assert_record_t logs[1];
+	} assertlog_results_t;
+
+#define LOGRRC_FIX_LEN	8
+#define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type))
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#ifdef BCMWAPI_WAI
+#define IV_LEN 16
+	struct wapi_sta_msg_t
+	{
+		uint16	msg_type;
+		uint16	datalen;
+		uint8	vap_mac[6];
+		uint8	reserve_data1[2];
+		uint8	sta_mac[6];
+		uint8	reserve_data2[2];
+		uint8	gsn[IV_LEN];
+		uint8	wie[256];
+	};
+#endif /* BCMWAPI_WAI */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+	/* chanim acs record */
+	typedef struct {
+		uint8 valid;
+		uint8 trigger;
+		chanspec_t selected_chspc;
+		int8 bgnoise;
+		uint32 glitch_cnt;
+		uint8 ccastats;
+		uint8 chan_idle;
+		uint32 timestamp;
+	} chanim_acs_record_t;
+
+	typedef struct {
+		chanim_acs_record_t acs_record[CHANIM_ACS_RECORD];
+		uint8 count;
+		uint32 timestamp;
+	} wl_acs_record_t;
+
+#define WL_CHANIM_STATS_V2 2
+#define CCASTATS_V2_MAX 9
+typedef struct chanim_stats_v2 {
+	uint32 glitchcnt;               /**< normalized as per second count */
+	uint32 badplcp;                 /**< normalized as per second count */
+	uint8 ccastats[CCASTATS_V2_MAX];   /**< normalized as 0-255 */
+	int8 bgnoise;                   /**< background noise level (in dBm) */
+	chanspec_t chanspec;            /**< ctrl chanspec of the interface */
+	uint32 timestamp;               /**< time stamp at which the stats are collected */
+	uint32 bphy_glitchcnt;          /**< normalized as per second count */
+	uint32 bphy_badplcp;            /**< normalized as per second count */
+	uint8 chan_idle;                /**< normalized as 0~255 */
+} chanim_stats_v2_t;
+
+typedef struct chanim_stats {
+	uint32 glitchcnt;               /**< normalized as per second count */
+	uint32 badplcp;                 /**< normalized as per second count */
+	uint8 ccastats[CCASTATS_MAX];   /**< normalized as 0-255 */
+	int8 bgnoise;                   /**< background noise level (in dBm) */
+	uint8 pad_1;
+	chanspec_t chanspec;            /**< ctrl chanspec of the interface */
+	uint8 pad_2[2];
+	uint32 timestamp;               /**< time stamp at which the stats are collected */
+	uint32 bphy_glitchcnt;          /**< normalized as per second count */
+	uint32 bphy_badplcp;            /**< normalized as per second count */
+	uint8 chan_idle;                /**< normalized as 0~255 */
+} chanim_stats_t;
+
+#define WL_CHANIM_STATS_VERSION 3
+typedef struct {
+	uint32 buflen;
+	uint32 version;
+	uint32 count;
+	chanim_stats_t stats[1];
+} wl_chanim_stats_t;
+
+#define WL_CHANIM_STATS_FIXED_LEN OFFSETOF(wl_chanim_stats_t, stats)
+
+/** Noise measurement metrics. */
+#define NOISE_MEASURE_KNOISE	0x1
+
+/** scb probe parameter */
+typedef struct {
+	uint32 scb_timeout;
+	uint32 scb_activity_time;
+	uint32 scb_max_probe;
+} wl_scb_probe_t;
+
+/* structure/defines for selective mgmt frame (smf) stats support */
+
+#define SMFS_VERSION 1
+/** selected mgmt frame (smf) stats element */
+typedef struct wl_smfs_elem {
+	uint32 count;
+	uint16 code;  /**< SC or RC code */
+} wl_smfs_elem_t;
+
+typedef struct wl_smf_stats {
+	uint32 version;
+	uint16 length;	/**< reserved for future usage */
+	uint8 type;
+	uint8 codetype;
+	uint32 ignored_cnt;
+	uint32 malformed_cnt;
+	uint32 count_total; /**< count included the interested group */
+	wl_smfs_elem_t elem[1];
+} wl_smf_stats_t;
+
+#define WL_SMFSTATS_FIXED_LEN OFFSETOF(wl_smf_stats_t, elem);
+
+enum {
+	SMFS_CODETYPE_SC,
+	SMFS_CODETYPE_RC
+};
+
+typedef enum smfs_type {
+	SMFS_TYPE_AUTH,
+	SMFS_TYPE_ASSOC,
+	SMFS_TYPE_REASSOC,
+	SMFS_TYPE_DISASSOC_TX,
+	SMFS_TYPE_DISASSOC_RX,
+	SMFS_TYPE_DEAUTH_TX,
+	SMFS_TYPE_DEAUTH_RX,
+	SMFS_TYPE_MAX
+} smfs_type_t;
+
+#ifdef PHYMON
+
+#define PHYMON_VERSION 1
+
+typedef struct wl_phycal_core_state {
+	/* Tx IQ/LO calibration coeffs */
+	int16 tx_iqlocal_a;
+	int16 tx_iqlocal_b;
+	int8 tx_iqlocal_ci;
+	int8 tx_iqlocal_cq;
+	int8 tx_iqlocal_di;
+	int8 tx_iqlocal_dq;
+	int8 tx_iqlocal_ei;
+	int8 tx_iqlocal_eq;
+	int8 tx_iqlocal_fi;
+	int8 tx_iqlocal_fq;
+
+	/** Rx IQ calibration coeffs */
+	int16 rx_iqcal_a;
+	int16 rx_iqcal_b;
+
+	uint8 tx_iqlocal_pwridx; /**< Tx Power Index for Tx IQ/LO calibration */
+	uint32 papd_epsilon_table[64]; /**< PAPD epsilon table */
+	int16 papd_epsilon_offset; /**< PAPD epsilon offset */
+	uint8 curr_tx_pwrindex; /**< Tx power index */
+	int8 idle_tssi; /**< Idle TSSI */
+	int8 est_tx_pwr; /**< Estimated Tx Power (dB) */
+	int8 est_rx_pwr; /**< Estimated Rx Power (dB) from RSSI */
+	uint16 rx_gaininfo; /**< Rx gain applied on last Rx pkt */
+	uint16 init_gaincode; /**< initgain required for ACI */
+	int8 estirr_tx;
+	int8 estirr_rx;
+
+} wl_phycal_core_state_t;
+
+typedef struct wl_phycal_state {
+	int32 version;
+	int8 num_phy_cores; /**< number of cores */
+	int8 curr_temperature; /**< on-chip temperature sensor reading */
+	chanspec_t chspec; /**< channspec for this state */
+	uint8 aci_state; /**< ACI state: ON/OFF */
+	uint16 crsminpower; /**< crsminpower required for ACI */
+	uint16 crsminpowerl; /**< crsminpowerl required for ACI */
+	uint16 crsminpoweru; /**< crsminpoweru required for ACI */
+	wl_phycal_core_state_t phycal_core[1];
+} wl_phycal_state_t;
+
+#define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core)
+#endif /* PHYMON */
+
+/** discovery state */
+typedef struct wl_p2p_disc_st {
+	uint8 state;	/**< see state */
+	chanspec_t chspec;	/**< valid in listen state */
+	uint16 dwell;	/**< valid in listen state, in ms */
+} wl_p2p_disc_st_t;
+
+/** scan request */
+typedef struct wl_p2p_scan {
+	uint8 type;		/**< 'S' for WLC_SCAN, 'E' for "escan" */
+	uint8 reserved[3];
+	/* scan or escan parms... */
+} wl_p2p_scan_t;
+
+/** i/f request */
+typedef struct wl_p2p_if {
+	struct ether_addr addr;
+	uint8 type;	/**< see i/f type */
+	chanspec_t chspec;	/**< for p2p_ifadd GO */
+} wl_p2p_if_t;
+
+/** i/f query */
+typedef struct wl_p2p_ifq {
+	uint32 bsscfgidx;
+	char ifname[BCM_MSG_IFNAME_MAX];
+} wl_p2p_ifq_t;
+
+/** OppPS & CTWindow */
+typedef struct wl_p2p_ops {
+	uint8 ops;	/**< 0: disable 1: enable */
+	uint8 ctw;	/**< >= 10 */
+} wl_p2p_ops_t;
+
+/** absence and presence request */
+typedef struct wl_p2p_sched_desc {
+	uint32 start;
+	uint32 interval;
+	uint32 duration;
+	uint32 count;	/**< see count */
+} wl_p2p_sched_desc_t;
+
+typedef struct wl_p2p_sched {
+	uint8 type;	/**< see schedule type */
+	uint8 action;	/**< see schedule action */
+	uint8 option;	/**< see schedule option */
+	wl_p2p_sched_desc_t desc[1];
+} wl_p2p_sched_t;
+
+typedef struct wl_p2p_wfds_hash {
+	uint32	advt_id;
+	uint16	nw_cfg_method;
+	uint8	wfds_hash[6];
+	uint8	name_len;
+	uint8	service_name[MAX_WFDS_SVC_NAME_LEN];
+} wl_p2p_wfds_hash_t;
+
+typedef struct wl_bcmdcs_data {
+	uint32 reason;
+	chanspec_t chspec;
+} wl_bcmdcs_data_t;
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/* ifdef EXT_STA */
+/**
+ * Format of IHV data passed to OID_DOT11_NIC_SPECIFIC_EXTENSION.
+ */
+typedef struct _IHV_NIC_SPECIFIC_EXTENSION {
+	uint8			oui[4];     /**< vendor specific OUI value */
+	uint32			event;      /**< event code */
+	uint8			ihvData[1];    /**< ihv data */
+} IHV_NIC_SPECIFIC_EXTENSION, *PIHV_NIC_SPECIFIC_EXTENSION;
+#define IHV_NIC_SPECIFIC_EXTENTION_HEADER	OFFSETOF(IHV_NIC_SPECIFIC_EXTENSION, ihvData[0])
+/* EXT_STA */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/** NAT configuration */
+typedef struct {
+	uint32 ipaddr;		/**< interface ip address */
+	uint32 ipaddr_mask;	/**< interface ip address mask */
+	uint32 ipaddr_gateway;	/**< gateway ip address */
+	uint8 mac_gateway[6];	/**< gateway mac address */
+	uint32 ipaddr_dns;	/**< DNS server ip address, valid only for public if */
+	uint8 mac_dns[6];	/**< DNS server mac address,  valid only for public if */
+	uint8 GUID[38];		/**< interface GUID */
+} nat_if_info_t;
+
+typedef struct {
+	uint32 op;		/**< operation code */
+	uint8 pub_if;		/**< set for public if, clear for private if */
+	nat_if_info_t if_info;	/**< interface info */
+} nat_cfg_t;
+
+typedef struct {
+	int32 state;	/**< NAT state returned */
+} nat_state_t;
+
+typedef struct flush_txfifo {
+	uint32 txfifobmp;
+	uint32 hwtxfifoflush;
+	struct ether_addr ea;
+} flush_txfifo_t;
+
+enum {
+	SPATIAL_MODE_2G_IDX = 0,
+	SPATIAL_MODE_5G_LOW_IDX,
+	SPATIAL_MODE_5G_MID_IDX,
+	SPATIAL_MODE_5G_HIGH_IDX,
+	SPATIAL_MODE_5G_UPPER_IDX,
+	SPATIAL_MODE_MAX_IDX
+};
+
+#define WLC_TXCORE_MAX		4	/**< max number of txcore supports */
+#define WLC_TXCORE_MAX_OLD	2	/**< backward compatibilty for TXCAL */
+#define WLC_SUBBAND_MAX		4	/**< max number of sub-band supports */
+typedef struct {
+	uint8	band2g[WLC_TXCORE_MAX];
+	uint8	band5g[WLC_SUBBAND_MAX][WLC_TXCORE_MAX];
+} sar_limit_t;
+
+#define MAX_NUM_TXCAL_MEAS 128
+#define MAX_NUM_PWR_STEP 40
+#define TXCAL_IOVAR_VERSION	0x1
+typedef struct wl_txcal_meas_percore {
+	uint16 tssi[MAX_NUM_TXCAL_MEAS];
+	int16 pwr[MAX_NUM_TXCAL_MEAS];
+} wl_txcal_meas_percore_t;
+
+typedef struct wl_txcal_meas_ncore {
+	uint16 version;
+	uint8 valid_cnt;
+	uint8 num_core;
+	wl_txcal_meas_percore_t txcal_percore[1];
+} wl_txcal_meas_ncore_t;
+
+typedef struct wl_txcal_power_tssi_percore {
+	int16 tempsense;
+	int16 pwr_start;
+	uint8 pwr_start_idx;
+	uint8 num_entries;
+	uint16 pad;
+	uint8 tssi[MAX_NUM_PWR_STEP];
+} wl_txcal_power_tssi_percore_t;
+
+typedef struct wl_txcal_power_tssi_ncore {
+	uint16 version;
+	uint8 set_core;
+	uint8 channel;
+	uint8 num_core;
+	uint8 gen_tbl;
+	uint16 pad;
+	wl_txcal_power_tssi_percore_t tssi_percore[1];
+} wl_txcal_power_tssi_ncore_t;
+
+typedef struct wl_txcal_meas {
+	uint16 tssi[WLC_TXCORE_MAX][MAX_NUM_TXCAL_MEAS];
+	int16 pwr[WLC_TXCORE_MAX][MAX_NUM_TXCAL_MEAS];
+	uint8 valid_cnt;
+} wl_txcal_meas_t;
+
+typedef struct wl_txcal_meas_old {
+	uint16 tssi[WLC_TXCORE_MAX_OLD][MAX_NUM_TXCAL_MEAS];
+	int16 pwr[WLC_TXCORE_MAX_OLD][MAX_NUM_TXCAL_MEAS];
+	uint8 valid_cnt;
+} wl_txcal_meas_old_t;
+
+typedef struct wl_txcal_power_tssi {
+	uint8 set_core;
+	uint8 channel;
+	int16 tempsense[WLC_TXCORE_MAX];
+	int16 pwr_start[WLC_TXCORE_MAX];
+	uint8 pwr_start_idx[WLC_TXCORE_MAX];
+	uint8 num_entries[WLC_TXCORE_MAX];
+	uint8 tssi[WLC_TXCORE_MAX][MAX_NUM_PWR_STEP];
+	uint8 gen_tbl;
+} wl_txcal_power_tssi_t;
+
+typedef struct wl_txcal_power_tssi_old {
+	uint8 set_core;
+	uint8 channel;
+	int16 tempsense[WLC_TXCORE_MAX_OLD];
+	int16 pwr_start[WLC_TXCORE_MAX_OLD];
+	uint8 pwr_start_idx[WLC_TXCORE_MAX_OLD];
+	uint8 num_entries[WLC_TXCORE_MAX_OLD];
+	uint8 tssi[WLC_TXCORE_MAX_OLD][MAX_NUM_PWR_STEP];
+	uint8 gen_tbl;
+} wl_txcal_power_tssi_old_t;
+
+typedef struct wl_olpc_pwr {
+	uint16 version;
+	uint8 core;
+	uint8 channel;
+	int16 tempsense;
+	uint8 olpc_idx;
+	uint8 pad;
+} wl_olpc_pwr_t;
+
+/** IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */
+typedef struct wl_mempool_stats {
+	int32 num;		/**< Number of memory pools */
+	bcm_mp_stats_t s[1];	/**< Variable array of memory pool stats. */
+} wl_mempool_stats_t;
+
+typedef struct {
+	uint32 ipaddr;
+	uint32 ipaddr_netmask;
+	uint32 ipaddr_gateway;
+} nwoe_ifconfig_t;
+
+/** Traffic management priority classes */
+typedef enum trf_mgmt_priority_class {
+	trf_mgmt_priority_low           = 0,        /**< Maps to 802.1p BK */
+	trf_mgmt_priority_medium        = 1,        /**< Maps to 802.1p BE */
+	trf_mgmt_priority_high          = 2,        /**< Maps to 802.1p VI */
+	trf_mgmt_priority_nochange	= 3,	    /**< do not update the priority */
+	trf_mgmt_priority_invalid       = (trf_mgmt_priority_nochange + 1)
+} trf_mgmt_priority_class_t;
+
+/** Traffic management configuration parameters */
+typedef struct trf_mgmt_config {
+	uint32  trf_mgmt_enabled;                           /**< 0 - disabled, 1 - enabled */
+	uint32  flags;                                      /**< See TRF_MGMT_FLAG_xxx defines */
+	uint32  host_ip_addr;                              /**< My IP address to determine subnet */
+	uint32  host_subnet_mask;                           /**< My subnet mask */
+	uint32  downlink_bandwidth;                         /**< In units of kbps */
+	uint32  uplink_bandwidth;                           /**< In units of kbps */
+	uint32  min_tx_bandwidth[TRF_MGMT_MAX_PRIORITIES];  /**< Minimum guaranteed tx bandwidth */
+	uint32  min_rx_bandwidth[TRF_MGMT_MAX_PRIORITIES];  /**< Minimum guaranteed rx bandwidth */
+} trf_mgmt_config_t;
+
+/** Traffic management filter */
+typedef struct trf_mgmt_filter {
+	struct ether_addr           dst_ether_addr;         /**< His L2 address */
+	uint32                      dst_ip_addr;            /**< His IP address */
+	uint16                      dst_port;               /**< His L4 port */
+	uint16                      src_port;               /**< My L4 port */
+	uint16                      prot;                   /**< L4 protocol (only TCP or UDP) */
+	uint16                      flags;                  /**< TBD. For now, this must be zero. */
+	trf_mgmt_priority_class_t   priority;               /**< Priority for filtered packets */
+	uint32                      dscp;                   /**< DSCP */
+} trf_mgmt_filter_t;
+
+/** Traffic management filter list (variable length) */
+typedef struct trf_mgmt_filter_list     {
+	uint32              num_filters;
+	trf_mgmt_filter_t   filter[1];
+} trf_mgmt_filter_list_t;
+
+/** Traffic management global info used for all queues */
+typedef struct trf_mgmt_global_info {
+	uint32  maximum_bytes_per_second;
+	uint32  maximum_bytes_per_sampling_period;
+	uint32  total_bytes_consumed_per_second;
+	uint32  total_bytes_consumed_per_sampling_period;
+	uint32  total_unused_bytes_per_sampling_period;
+} trf_mgmt_global_info_t;
+
+/** Traffic management shaping info per priority queue */
+typedef struct trf_mgmt_shaping_info {
+	uint32  gauranteed_bandwidth_percentage;
+	uint32  guaranteed_bytes_per_second;
+	uint32  guaranteed_bytes_per_sampling_period;
+	uint32  num_bytes_produced_per_second;
+	uint32  num_bytes_consumed_per_second;
+	uint32  num_queued_packets;                         /**< Number of packets in queue */
+	uint32  num_queued_bytes;                           /**< Number of bytes in queue */
+} trf_mgmt_shaping_info_t;
+
+/** Traffic management shaping info array */
+typedef struct trf_mgmt_shaping_info_array {
+	trf_mgmt_global_info_t   tx_global_shaping_info;
+	trf_mgmt_shaping_info_t  tx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES];
+	trf_mgmt_global_info_t   rx_global_shaping_info;
+	trf_mgmt_shaping_info_t  rx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES];
+} trf_mgmt_shaping_info_array_t;
+
+
+/** Traffic management statistical counters */
+typedef struct trf_mgmt_stats {
+	uint32  num_processed_packets;      /**< Number of packets processed */
+	uint32  num_processed_bytes;        /**< Number of bytes processed */
+	uint32  num_discarded_packets;      /**< Number of packets discarded from queue */
+} trf_mgmt_stats_t;
+
+/** Traffic management statistics array */
+typedef struct trf_mgmt_stats_array {
+	trf_mgmt_stats_t  tx_queue_stats[TRF_MGMT_MAX_PRIORITIES];
+	trf_mgmt_stats_t  rx_queue_stats[TRF_MGMT_MAX_PRIORITIES];
+} trf_mgmt_stats_array_t;
+
+/* Both powersel_params and lpc_params are used by IOVAR lpc_params.
+ * The powersel_params is replaced by lpc_params in later WLC versions.
+ */
+typedef struct powersel_params {
+	/* LPC Params exposed via IOVAR */
+	int32		tp_ratio_thresh;  /**< Throughput ratio threshold */
+	uint8		rate_stab_thresh; /**< Thresh for rate stability based on nupd */
+	uint8		pwr_stab_thresh; /**< Number of successes before power step down */
+	uint8		pwr_sel_exp_time; /**< Time lapse for expiry of database */
+} powersel_params_t;
+
+#define WL_LPC_PARAMS_VER_2	2
+#define WL_LPC_PARAMS_CURRENT_VERSION WL_LPC_PARAMS_VER_2
+
+typedef struct lpc_params {
+	uint16		version;
+	uint16		length;
+	/* LPC Params exposed via IOVAR */
+	uint8		rate_stab_thresh; /**< Thresh for rate stability based on nupd */
+	uint8		pwr_stab_thresh; /**< Number of successes before power step down */
+	uint8		lpc_exp_time; /**< Time lapse for expiry of database */
+	uint8		pwrup_slow_step; /**< Step size for slow step up */
+	uint8		pwrup_fast_step; /**< Step size for fast step up */
+	uint8		pwrdn_slow_step; /**< Step size for slow step down */
+} lpc_params_t;
+
+/* tx pkt delay statistics */
+#define	SCB_RETRY_SHORT_DEF	7	/**< Default Short retry Limit */
+#define WLPKTDLY_HIST_NBINS	16	/**< number of bins used in the Delay histogram */
+
+/** structure to store per-AC delay statistics */
+typedef struct scb_delay_stats {
+	uint32 txmpdu_lost;	/**< number of MPDUs lost */
+	uint32 txmpdu_cnt[SCB_RETRY_SHORT_DEF]; /**< retry times histogram */
+	uint32 delay_sum[SCB_RETRY_SHORT_DEF]; /**< cumulative packet latency */
+	uint32 delay_min;	/**< minimum packet latency observed */
+	uint32 delay_max;	/**< maximum packet latency observed */
+	uint32 delay_avg;	/**< packet latency average */
+	uint32 delay_hist[WLPKTDLY_HIST_NBINS];	/**< delay histogram */
+	uint32 delay_count;	/**< minimum number of time period units before
+				consequent packet delay events can be generated
+				*/
+	uint32 prev_txmpdu_cnt;	/**< Previous value of txmpdu_cnt[] during last iteration */
+	uint32 prev_delay_sum;	/**< Previous value of delay_sum[] during last iteration */
+} scb_delay_stats_t;
+
+/** structure for txdelay event */
+typedef struct txdelay_event {
+	uint8	status;
+	int32		rssi;
+	chanim_stats_t		chanim_stats;
+	scb_delay_stats_t	delay_stats[AC_COUNT];
+} txdelay_event_t;
+
+/** structure for txdelay parameters */
+typedef struct txdelay_params {
+	uint16	ratio;	/**< Avg Txdelay Delta */
+	uint8	cnt;	/**< Sample cnt */
+	uint8	period;	/**< Sample period */
+	uint8	tune;	/**< Debug */
+} txdelay_params_t;
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define MAX_TXDELAY_STATS_SCBS 6
+#define TXDELAY_STATS_VERSION 1
+
+enum {
+	TXDELAY_STATS_PARTIAL_RESULT = 0,
+	TXDELAY_STATS_FULL_RESULT = 1
+};
+
+typedef struct scb_total_delay_stats {
+	struct  ether_addr ea;
+	uint8   pad[2];
+	scb_delay_stats_t dlystats[AC_COUNT];
+} scb_total_delay_stats_t;
+
+typedef struct txdelay_stats {
+	uint32  version;
+	uint32  full_result;    /* 0:Partial, 1:full */
+	uint32  scb_cnt;        /* in:requested, out:returned */
+	scb_total_delay_stats_t scb_delay_stats[1];
+} txdelay_stats_t;
+
+#define WL_TXDELAY_STATS_FIXED_SIZE \
+	(sizeof(txdelay_stats_t)+(MAX_TXDELAY_STATS_SCBS-1)*sizeof(scb_total_delay_stats_t))
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+enum {
+	WNM_SERVICE_DMS = 1,
+	WNM_SERVICE_FMS = 2,
+	WNM_SERVICE_TFS = 3
+};
+
+/** Definitions for WNM/NPS TCLAS */
+typedef struct wl_tclas {
+	uint8 user_priority;
+	uint8 fc_len;
+	dot11_tclas_fc_t fc;
+} wl_tclas_t;
+
+#define WL_TCLAS_FIXED_SIZE	OFFSETOF(wl_tclas_t, fc)
+
+typedef struct wl_tclas_list {
+	uint32 num;
+	wl_tclas_t tclas[1];
+} wl_tclas_list_t;
+
+/** Definitions for WNM/NPS Traffic Filter Service */
+typedef struct wl_tfs_req {
+	uint8 tfs_id;
+	uint8 tfs_actcode;
+	uint8 tfs_subelem_id;
+	uint8 send;
+} wl_tfs_req_t;
+
+typedef struct wl_tfs_filter {
+	uint8 status;			/**< Status returned by the AP */
+	uint8 tclas_proc;		/**< TCLAS processing value (0:and, 1:or)  */
+	uint8 tclas_cnt;		/**< count of all wl_tclas_t in tclas array */
+	uint8 tclas[1];			/**< VLA of wl_tclas_t */
+} wl_tfs_filter_t;
+#define WL_TFS_FILTER_FIXED_SIZE	OFFSETOF(wl_tfs_filter_t, tclas)
+
+typedef struct wl_tfs_fset {
+	struct ether_addr ea;		/**< Address of AP/STA involved with this filter set */
+	uint8 tfs_id;			/**< TFS ID field chosen by STA host */
+	uint8 status;			/**< Internal status TFS_STATUS_xxx */
+	uint8 actcode;			/**< Action code DOT11_TFS_ACTCODE_xxx */
+	uint8 token;			/**< Token used in last request frame */
+	uint8 notify;			/**< Notify frame sent/received because of this set */
+	uint8 filter_cnt;		/**< count of all wl_tfs_filter_t in filter array */
+	uint8 filter[1];		/**< VLA of wl_tfs_filter_t */
+} wl_tfs_fset_t;
+#define WL_TFS_FSET_FIXED_SIZE		OFFSETOF(wl_tfs_fset_t, filter)
+
+enum {
+	TFS_STATUS_DISABLED = 0,	/**< TFS filter set disabled by user */
+	TFS_STATUS_DISABLING = 1,	/**< Empty request just sent to AP */
+	TFS_STATUS_VALIDATED = 2,	/**< Filter set validated by AP (but maybe not enabled!) */
+	TFS_STATUS_VALIDATING = 3,	/**< Filter set just sent to AP */
+	TFS_STATUS_NOT_ASSOC = 4,	/**< STA not associated */
+	TFS_STATUS_NOT_SUPPORT = 5,	/**< TFS not supported by AP */
+	TFS_STATUS_DENIED = 6,		/**< Filter set refused by AP (=> all sets are disabled!) */
+};
+
+typedef struct wl_tfs_status {
+	uint8 fset_cnt;			/**< count of all wl_tfs_fset_t in fset array */
+	wl_tfs_fset_t fset[1];		/**< VLA of wl_tfs_fset_t */
+} wl_tfs_status_t;
+
+typedef struct wl_tfs_set {
+	uint8 send;		/**< Immediatly register registered sets on AP side */
+	uint8 tfs_id;		/**< ID of a specific set (existing or new), or nul for all */
+	uint8 actcode;		/**< Action code for this filter set */
+	uint8 tclas_proc;	/**< TCLAS processing operator for this filter set */
+} wl_tfs_set_t;
+
+typedef struct wl_tfs_term {
+	uint8 del;			/**< Delete internal set once confirmation received */
+	uint8 tfs_id;			/**< ID of a specific set (existing), or nul for all */
+} wl_tfs_term_t;
+
+
+#define DMS_DEP_PROXY_ARP (1 << 0)
+
+/* Definitions for WNM/NPS Directed Multicast Service */
+enum {
+	DMS_STATUS_DISABLED = 0,	/**< DMS desc disabled by user */
+	DMS_STATUS_ACCEPTED = 1,	/**< Request accepted by AP */
+	DMS_STATUS_NOT_ASSOC = 2,	/**< STA not associated */
+	DMS_STATUS_NOT_SUPPORT = 3,	/**< DMS not supported by AP */
+	DMS_STATUS_DENIED = 4,		/**< Request denied by AP */
+	DMS_STATUS_TERM = 5,		/**< Request terminated by AP */
+	DMS_STATUS_REMOVING = 6,	/**< Remove request just sent */
+	DMS_STATUS_ADDING = 7,		/**< Add request just sent */
+	DMS_STATUS_ERROR = 8,		/**< Non compliant AP behvior */
+	DMS_STATUS_IN_PROGRESS = 9,	/**< Request just sent */
+	DMS_STATUS_REQ_MISMATCH = 10	/**< Conditions for sending DMS req not met */
+};
+
+typedef struct wl_dms_desc {
+	uint8 user_id;
+	uint8 status;
+	uint8 token;
+	uint8 dms_id;
+	uint8 tclas_proc;
+	uint8 mac_len;		/**< length of all ether_addr in data array, 0 if STA */
+	uint8 tclas_len;	/**< length of all wl_tclas_t in data array */
+	uint8 data[1];		/**< VLA of 'ether_addr' and 'wl_tclas_t' (in this order ) */
+} wl_dms_desc_t;
+
+#define WL_DMS_DESC_FIXED_SIZE	OFFSETOF(wl_dms_desc_t, data)
+
+typedef struct wl_dms_status {
+	uint32 cnt;
+	wl_dms_desc_t desc[1];
+} wl_dms_status_t;
+
+typedef struct wl_dms_set {
+	uint8 send;
+	uint8 user_id;
+	uint8 tclas_proc;
+} wl_dms_set_t;
+
+typedef struct wl_dms_term {
+	uint8 del;
+	uint8 user_id;
+} wl_dms_term_t;
+
+typedef struct wl_service_term {
+	uint8 service;
+	union {
+		wl_dms_term_t dms;
+	} u;
+} wl_service_term_t;
+
+/** Definitions for WNM/NPS BSS Transistion */
+typedef struct wl_bsstrans_req {
+	uint16 tbtt;			/**< time of BSS to end of life, in unit of TBTT */
+	uint16 dur;			/**< time of BSS to keep off, in unit of minute */
+	uint8 reqmode;			/**< request mode of BSS transition request */
+	uint8 unicast;			/**< request by unicast or by broadcast */
+} wl_bsstrans_req_t;
+
+enum {
+	BSSTRANS_RESP_AUTO = 0,		/**< Currently equivalent to ENABLE */
+	BSSTRANS_RESP_DISABLE = 1,	/**< Never answer BSS Trans Req frames */
+	BSSTRANS_RESP_ENABLE = 2,	/**< Always answer Req frames with preset data */
+	BSSTRANS_RESP_WAIT = 3,		/**< Send ind, wait and/or send preset data (NOT IMPL) */
+	BSSTRANS_RESP_IMMEDIATE = 4	/**< After an ind, set data and send resp (NOT IMPL) */
+};
+
+typedef struct wl_bsstrans_resp {
+	uint8 policy;
+	uint8 status;
+	uint8 delay;
+	struct ether_addr target;
+} wl_bsstrans_resp_t;
+
+/* "wnm_bsstrans_policy" argument programs behavior after BSSTRANS Req reception.
+ * BSS-Transition feature is used by multiple programs such as NPS-PF, VE-PF,
+ * Band-steering, Hotspot 2.0 and customer requirements. Each PF and its test plan
+ * mandates different behavior on receiving BSS-transition request. To accomodate
+ * such divergent behaviors these policies have been created.
+ */
+typedef enum {
+	WL_BSSTRANS_POLICY_ROAM_ALWAYS = 0,	/**< Roam (or disassociate) in all cases */
+	WL_BSSTRANS_POLICY_ROAM_IF_MODE = 1,	/**< Roam only if requested by Request Mode field */
+	WL_BSSTRANS_POLICY_ROAM_IF_PREF = 2,	/**< Roam only if Preferred BSS provided */
+	WL_BSSTRANS_POLICY_WAIT = 3,		/**< Wait for deauth and send Accepted status */
+	WL_BSSTRANS_POLICY_PRODUCT = 4,	/**< Policy for real product use cases (Olympic) */
+	WL_BSSTRANS_POLICY_PRODUCT_WBTEXT = 5,	/**< Policy for real product use cases (SS) */
+	WL_BSSTRANS_POLICY_MAX = 6
+} wnm_bsstrans_policy_type_t;
+
+/** Definitions for WNM/NPS TIM Broadcast */
+typedef struct wl_timbc_offset {
+	int16 offset;		/**< offset in us */
+	uint16 fix_intv;	/**< override interval sent from STA */
+	uint16 rate_override;	/**< use rate override to send high rate TIM broadcast frame */
+	uint8 tsf_present;	/**< show timestamp in TIM broadcast frame */
+} wl_timbc_offset_t;
+
+typedef struct wl_timbc_set {
+	uint8 interval;		/**< Interval in DTIM wished or required. */
+	uint8 flags;		/**< Bitfield described below */
+	uint16 rate_min;	/**< Minimum rate required for High/Low TIM frames. Optionnal */
+	uint16 rate_max;	/**< Maximum rate required for High/Low TIM frames. Optionnal */
+} wl_timbc_set_t;
+
+enum {
+	WL_TIMBC_SET_TSF_REQUIRED = 1,	/**< Enable TIMBC only if TSF in TIM frames */
+	WL_TIMBC_SET_NO_OVERRIDE = 2,	/**< ... if AP does not override interval */
+	WL_TIMBC_SET_PROXY_ARP = 4,	/**< ... if AP support Proxy ARP */
+	WL_TIMBC_SET_DMS_ACCEPTED = 8	/**< ... if all DMS desc have been accepted */
+};
+
+typedef struct wl_timbc_status {
+	uint8 status_sta;		/**< Status from internal state machine (check below) */
+	uint8 status_ap;		/**< From AP response frame (check 8.4.2.86 from 802.11) */
+	uint8 interval;
+	uint8 pad;
+	int32 offset;
+	uint16 rate_high;
+	uint16 rate_low;
+} wl_timbc_status_t;
+
+enum {
+	WL_TIMBC_STATUS_DISABLE = 0,		/**< TIMBC disabled by user */
+	WL_TIMBC_STATUS_REQ_MISMATCH = 1,	/**< AP settings do no match user requirements */
+	WL_TIMBC_STATUS_NOT_ASSOC = 2,		/**< STA not associated */
+	WL_TIMBC_STATUS_NOT_SUPPORT = 3,	/**< TIMBC not supported by AP */
+	WL_TIMBC_STATUS_DENIED = 4,		/**< Req to disable TIMBC sent to AP */
+	WL_TIMBC_STATUS_ENABLE = 5		/**< TIMBC enabled */
+};
+
+/** Definitions for PM2 Dynamic Fast Return To Sleep */
+typedef struct wl_pm2_sleep_ret_ext {
+	uint8 logic;			/**< DFRTS logic: see WL_DFRTS_LOGIC_* below */
+	uint16 low_ms;			/**< Low FRTS timeout */
+	uint16 high_ms;			/**< High FRTS timeout */
+	uint16 rx_pkts_threshold;	/**< switching threshold: # rx pkts */
+	uint16 tx_pkts_threshold;	/**< switching threshold: # tx pkts */
+	uint16 txrx_pkts_threshold;	/**< switching threshold: # (tx+rx) pkts */
+	uint32 rx_bytes_threshold;	/**< switching threshold: # rx bytes */
+	uint32 tx_bytes_threshold;	/**< switching threshold: # tx bytes */
+	uint32 txrx_bytes_threshold;	/**< switching threshold: # (tx+rx) bytes */
+} wl_pm2_sleep_ret_ext_t;
+
+#define WL_DFRTS_LOGIC_OFF	0	/**< Feature is disabled */
+#define WL_DFRTS_LOGIC_OR	1	/**< OR all non-zero threshold conditions */
+#define WL_DFRTS_LOGIC_AND	2	/**< AND all non-zero threshold conditions */
+
+/* Values for the passive_on_restricted_mode iovar.  When set to non-zero, this iovar
+ * disables automatic conversions of a channel from passively scanned to
+ * actively scanned.  These values only have an effect for country codes such
+ * as XZ where some 5 GHz channels are defined to be passively scanned.
+ */
+#define WL_PASSACTCONV_DISABLE_NONE	0	/**< Enable permanent and temporary conversions */
+#define WL_PASSACTCONV_DISABLE_ALL	1	/**< Disable permanent and temporary conversions */
+#define WL_PASSACTCONV_DISABLE_PERM	2	/**< Disable only permanent conversions */
+
+/* Definitions for Reliable Multicast */
+#define WL_RMC_CNT_VERSION	   1
+#define WL_RMC_TR_VERSION	   1
+#define WL_RMC_MAX_CLIENT	   32
+#define WL_RMC_FLAG_INBLACKLIST	   1
+#define WL_RMC_FLAG_ACTIVEACKER	   2
+#define WL_RMC_FLAG_RELMCAST	   4
+#define WL_RMC_MAX_TABLE_ENTRY     4
+
+#define WL_RMC_VER		   1
+#define WL_RMC_INDEX_ACK_ALL       255
+#define WL_RMC_NUM_OF_MC_STREAMS   4
+#define WL_RMC_MAX_TRS_PER_GROUP   1
+#define WL_RMC_MAX_TRS_IN_ACKALL   1
+#define WL_RMC_ACK_MCAST0          0x02
+#define WL_RMC_ACK_MCAST_ALL       0x01
+#define WL_RMC_ACTF_TIME_MIN       300		/**< time in ms */
+#define WL_RMC_ACTF_TIME_MAX       20000	/**< time in ms */
+#define WL_RMC_MAX_NUM_TRS	   32		/**< maximun transmitters allowed */
+#define WL_RMC_ARTMO_MIN           350		/**< time in ms */
+#define WL_RMC_ARTMO_MAX           40000	/**< time in ms */
+
+/* RMC events in action frames */
+enum rmc_opcodes {
+	RELMCAST_ENTRY_OP_DISABLE = 0,   /**< Disable multi-cast group */
+	RELMCAST_ENTRY_OP_DELETE  = 1,   /**< Delete multi-cast group */
+	RELMCAST_ENTRY_OP_ENABLE  = 2,   /**< Enable multi-cast group */
+	RELMCAST_ENTRY_OP_ACK_ALL = 3    /**< Enable ACK ALL bit in AMT */
+};
+
+/* RMC operational modes */
+enum rmc_modes {
+	WL_RMC_MODE_RECEIVER    = 0,	 /**< Receiver mode by default */
+	WL_RMC_MODE_TRANSMITTER = 1,	 /**< Transmitter mode using wl ackreq */
+	WL_RMC_MODE_INITIATOR   = 2	 /**< Initiator mode using wl ackreq */
+};
+
+/** Each RMC mcast client info */
+typedef struct wl_relmcast_client {
+	uint8 flag;			/**< status of client such as AR, R, or blacklisted */
+	int16 rssi;			/**< rssi value of RMC client */
+	struct ether_addr addr;		/**< mac address of RMC client */
+} wl_relmcast_client_t;
+
+/** RMC Counters */
+typedef struct wl_rmc_cnts {
+	uint16  version;		/**< see definition of WL_CNT_T_VERSION */
+	uint16  length;			/**< length of entire structure */
+	uint16	dupcnt;			/**< counter for duplicate rmc MPDU */
+	uint16	ackreq_err;		/**< counter for wl ackreq error    */
+	uint16	af_tx_err;		/**< error count for action frame transmit   */
+	uint16	null_tx_err;		/**< error count for rmc null frame transmit */
+	uint16	af_unicast_tx_err;	/**< error count for rmc unicast frame transmit */
+	uint16	mc_no_amt_slot;		/**< No mcast AMT entry available */
+	/* Unused. Keep for rom compatibility */
+	uint16	mc_no_glb_slot;		/**< No mcast entry available in global table */
+	uint16	mc_not_mirrored;	/**< mcast group is not mirrored */
+	uint16	mc_existing_tr;		/**< mcast group is already taken by transmitter */
+	uint16	mc_exist_in_amt;	/**< mcast group is already programmed in amt */
+	/* Unused. Keep for rom compatibility */
+	uint16	mc_not_exist_in_gbl;	/**< mcast group is not in global table */
+	uint16	mc_not_exist_in_amt;	/**< mcast group is not in AMT table */
+	uint16	mc_utilized;		/**< mcast addressed is already taken */
+	uint16	mc_taken_other_tr;	/**< multi-cast addressed is already taken */
+	uint32	rmc_rx_frames_mac;      /**< no of mc frames received from mac */
+	uint32	rmc_tx_frames_mac;      /**< no of mc frames transmitted to mac */
+	uint32	mc_null_ar_cnt;         /**< no. of times NULL AR is received */
+	uint32	mc_ar_role_selected;	/**< no. of times took AR role */
+	uint32	mc_ar_role_deleted;	/**< no. of times AR role cancelled */
+	uint32	mc_noacktimer_expired;  /**< no. of times noack timer expired */
+	uint16  mc_no_wl_clk;           /**< no wl clk detected when trying to access amt */
+	uint16  mc_tr_cnt_exceeded;     /**< No of transmitters in the network exceeded */
+} wl_rmc_cnts_t;
+
+/** RMC Status */
+typedef struct wl_relmcast_st {
+	uint8         ver;		/**< version of RMC */
+	uint8         num;		/**< number of clients detected by transmitter */
+	wl_relmcast_client_t clients[WL_RMC_MAX_CLIENT];
+	uint16        err;		/**< error status (used in infra) */
+	uint16        actf_time;	/**< action frame time period */
+} wl_relmcast_status_t;
+
+/** Entry for each STA/node */
+typedef struct wl_rmc_entry {
+	/* operation on multi-cast entry such add,
+	 * delete, ack-all
+	 */
+	int8    flag;
+	struct ether_addr addr;		/**< multi-cast group mac address */
+} wl_rmc_entry_t;
+
+/** RMC table */
+typedef struct wl_rmc_entry_table {
+	uint8   index;			/**< index to a particular mac entry in table */
+	uint8   opcode;			/**< opcodes or operation on entry */
+	wl_rmc_entry_t entry[WL_RMC_MAX_TABLE_ENTRY];
+} wl_rmc_entry_table_t;
+
+typedef struct wl_rmc_trans_elem {
+	struct ether_addr tr_mac;	/**< transmitter mac */
+	struct ether_addr ar_mac;	/**< ar mac */
+	uint16 artmo;			/**< AR timeout */
+	uint8 amt_idx;			/**< amt table entry */
+	uint16 flag;			/**< entry will be acked, not acked, programmed, full etc */
+} wl_rmc_trans_elem_t;
+
+/** RMC transmitters */
+typedef struct wl_rmc_trans_in_network {
+	uint8         ver;		/**< version of RMC */
+	uint8         num_tr;		/**< number of transmitters in the network */
+	wl_rmc_trans_elem_t trs[WL_RMC_MAX_NUM_TRS];
+} wl_rmc_trans_in_network_t;
+
+/** To update vendor specific ie for RMC */
+typedef struct wl_rmc_vsie {
+	uint8	oui[DOT11_OUI_LEN];
+	uint16	payload;	/**< IE Data Payload */
+} wl_rmc_vsie_t;
+
+
+/* structures  & defines for proximity detection  */
+enum proxd_method {
+	PROXD_UNDEFINED_METHOD = 0,
+	PROXD_RSSI_METHOD = 1,
+	PROXD_TOF_METHOD = 2
+};
+
+/* structures for proximity detection device role */
+#define WL_PROXD_MODE_DISABLE	0
+#define WL_PROXD_MODE_NEUTRAL	1
+#define WL_PROXD_MODE_INITIATOR	2
+#define WL_PROXD_MODE_TARGET	3
+
+#define WL_PROXD_ACTION_STOP		0
+#define WL_PROXD_ACTION_START		1
+
+#define WL_PROXD_FLAG_TARGET_REPORT	0x1
+#define WL_PROXD_FLAG_REPORT_FAILURE	0x2
+#define WL_PROXD_FLAG_INITIATOR_REPORT	0x4
+#define WL_PROXD_FLAG_NOCHANSWT		0x8
+#define WL_PROXD_FLAG_NETRUAL		0x10
+#define WL_PROXD_FLAG_INITIATOR_RPTRTT	0x20
+#define WL_PROXD_FLAG_ONEWAY		0x40
+#define WL_PROXD_FLAG_SEQ_EN		0x80
+
+#define WL_PROXD_SETFLAG_K		0x1
+#define WL_PROXD_SETFLAG_N		0x2
+#define WL_PROXD_SETFLAG_S		0x4
+
+#define WL_PROXD_SETFLAG_K		0x1
+#define WL_PROXD_SETFLAG_N		0x2
+#define WL_PROXD_SETFLAG_S		0x4
+
+#define WL_PROXD_RANDOM_WAKEUP	0x8000
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_PROXD_MAXREPORT	8
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+typedef struct wl_proxd_iovar {
+	uint16	method;		/**< Proximity Detection method */
+	uint16	mode;		/**< Mode (neutral, initiator, target) */
+} wl_proxd_iovar_t;
+
+/*
+ * structures for proximity detection parameters
+ * consists of two parts, common and method specific params
+ * common params should be placed at the beginning
+ */
+
+typedef struct wl_proxd_params_common	{
+	chanspec_t	chanspec;	/**< channel spec */
+	int16		tx_power;	/**< tx power of Proximity Detection(PD) frames (in dBm) */
+	uint16		tx_rate;	/**< tx rate of PD rames  (in 500kbps units) */
+	uint16		timeout;	/**< timeout value */
+	uint16		interval;	/**< interval between neighbor finding attempts (in TU) */
+	uint16		duration;	/**< duration of neighbor finding attempts (in ms) */
+} wl_proxd_params_common_t;
+
+typedef struct wl_proxd_params_rssi_method {
+	chanspec_t	chanspec;	/**< chanspec for home channel */
+	int16		tx_power;	/**< tx power of Proximity Detection frames (in dBm) */
+	uint16		tx_rate;	/**< tx rate of PD frames, 500kbps units */
+	uint16		timeout;	/**< state machine wait timeout of the frames (in ms) */
+	uint16		interval;	/**< interval between neighbor finding attempts (in TU) */
+	uint16		duration;	/**< duration of neighbor finding attempts (in ms) */
+					/* method specific ones go after this line */
+	int16		rssi_thresh;	/**< RSSI threshold (in dBm) */
+	uint16		maxconvergtmo;	/**< max wait converge timeout (in ms) */
+} wl_proxd_params_rssi_method_t;
+
+#define Q1_NS			25	/**< Q1 time units */
+
+#define TOF_BW_NUM		3	/**< number of bandwidth that the TOF can support */
+#define TOF_BW_SEQ_NUM		(TOF_BW_NUM+2)	/* number of total index */
+enum tof_bw_index {
+	TOF_BW_20MHZ_INDEX = 0,
+	TOF_BW_40MHZ_INDEX = 1,
+	TOF_BW_80MHZ_INDEX = 2,
+	TOF_BW_SEQTX_INDEX = 3,
+	TOF_BW_SEQRX_INDEX = 4
+};
+
+#define BANDWIDTH_BASE	20	/**< base value of bandwidth */
+#define TOF_BW_20MHZ    (BANDWIDTH_BASE << TOF_BW_20MHZ_INDEX)
+#define TOF_BW_40MHZ    (BANDWIDTH_BASE << TOF_BW_40MHZ_INDEX)
+#define TOF_BW_80MHZ    (BANDWIDTH_BASE << TOF_BW_80MHZ_INDEX)
+#define TOF_BW_10MHZ    10
+
+#define NFFT_BASE		64	/**< base size of fft */
+#define TOF_NFFT_20MHZ  (NFFT_BASE << TOF_BW_20MHZ_INDEX)
+#define TOF_NFFT_40MHZ  (NFFT_BASE << TOF_BW_40MHZ_INDEX)
+#define TOF_NFFT_80MHZ  (NFFT_BASE << TOF_BW_80MHZ_INDEX)
+
+typedef struct wl_proxd_params_tof_method {
+	chanspec_t	chanspec;	/**< chanspec for home channel */
+	int16		tx_power;	/**< tx power of Proximity Detection(PD) frames (in dBm) */
+	uint16		tx_rate;	/**< tx rate of PD rames  (in 500kbps units) */
+	uint16		timeout;	/**< state machine wait timeout of the frames (in ms) */
+	uint16		interval;	/**< interval between neighbor finding attempts (in TU) */
+	uint16		duration;	/**< duration of neighbor finding attempts (in ms) */
+	/* specific for the method go after this line */
+	struct ether_addr tgt_mac;	/**< target mac addr for TOF method */
+	uint16		ftm_cnt;	/**< number of the frames txed by initiator */
+	uint16		retry_cnt;	/**< number of retransmit attampts for ftm frames */
+	int16		vht_rate;	/**< ht or vht rate */
+	/* add more params required for other methods can be added here  */
+} wl_proxd_params_tof_method_t;
+
+typedef struct wl_proxd_seq_config
+{
+	int16 N_tx_log2;
+	int16 N_rx_log2;
+	int16 N_tx_scale;
+	int16 N_rx_scale;
+	int16 w_len;
+	int16 w_offset;
+} wl_proxd_seq_config_t;
+
+#define WL_PROXD_TUNE_VERSION_1		1
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_tof_tune {
+	uint32		version;
+	uint32		Ki;			/**< h/w delay K factor for initiator */
+	uint32		Kt;			/**< h/w delay K factor for target */
+	int16		vhtack;			/**< enable/disable VHT ACK */
+	int16		N_log2[TOF_BW_SEQ_NUM]; /**< simple threshold crossing */
+	int16		w_offset[TOF_BW_NUM];	/**< offset of threshold crossing window(per BW) */
+	int16		w_len[TOF_BW_NUM];	/**< length of threshold crossing window(per BW) */
+	int32		maxDT;			/**< max time difference of T4/T1 or T3/T2 */
+	int32		minDT;			/**< min time difference of T4/T1 or T3/T2 */
+	uint8		totalfrmcnt;	/**< total count of transfered measurement frames */
+	uint16		rsv_media;		/**< reserve media value for TOF */
+	uint32		flags;			/**< flags */
+	uint8		core;			/**< core to use for tx */
+	uint8		setflags;		/* set flags of K, N. S values  */
+	int16		N_scale[TOF_BW_SEQ_NUM]; /**< simple threshold crossing */
+	uint8		sw_adj;			/**< enable sw assisted timestamp adjustment */
+	uint8		hw_adj;			/**< enable hw assisted timestamp adjustment */
+	uint8		seq_en;			/**< enable ranging sequence */
+	uint8		ftm_cnt[TOF_BW_SEQ_NUM]; /**< number of ftm frames based on bandwidth */
+	int16		N_log2_2g;		/**< simple threshold crossing for 2g channel */
+	int16		N_scale_2g;		/**< simple threshold crossing for 2g channel */
+	wl_proxd_seq_config_t seq_5g20;
+	wl_proxd_seq_config_t seq_2g20;		/* Thresh crossing params for 2G Sequence */
+	uint16          bitflip_thresh;		/* bitflip threshold */
+	uint16          snr_thresh;		/* SNR threshold */
+	int8            recv_2g_thresh;		/* 2g recieve sensitivity threshold */
+	uint32          acs_gdv_thresh;
+	int8            acs_rssi_thresh;
+	uint8           smooth_win_en;
+	int32		acs_gdmm_thresh;
+} BWL_POST_PACKED_STRUCT wl_proxd_params_tof_tune_t;
+#include <packed_section_end.h>
+
+typedef struct wl_proxd_params_iovar {
+	uint16	method;			/**< Proximity Detection method */
+	union {
+		/* common params for pdsvc */
+		wl_proxd_params_common_t	cmn_params;	/**< common parameters */
+		/*  method specific */
+		wl_proxd_params_rssi_method_t	rssi_params;	/**< RSSI method parameters */
+		wl_proxd_params_tof_method_t	tof_params;	/**< TOF method parameters */
+		/* tune parameters */
+		wl_proxd_params_tof_tune_t	tof_tune;	/**< TOF tune parameters */
+	} u;				/**< Method specific optional parameters */
+} wl_proxd_params_iovar_t;
+
+#define PROXD_COLLECT_GET_STATUS	0
+#define PROXD_COLLECT_SET_STATUS	1
+#define PROXD_COLLECT_QUERY_HEADER	2
+#define PROXD_COLLECT_QUERY_DATA	3
+#define PROXD_COLLECT_QUERY_DEBUG	4
+#define PROXD_COLLECT_REMOTE_REQUEST	5
+#define PROXD_COLLECT_DONE		6
+
+typedef enum {
+	WL_PROXD_COLLECT_METHOD_TYPE_DISABLE		= 0x0,
+	WL_PROXD_COLLECT_METHOD_TYPE_IOVAR		= 0x1,
+	WL_PROXD_COLLECT_METHOD_TYPE_EVENT		= 0x2,
+	WL_PROXD_COLLECT_METHOD_TYPE_EVENT_LOG		= 0x4
+} wl_proxd_collect_method_type_t;
+
+typedef uint16 wl_proxd_collect_method_t;	/* query status: method to send proxd collect */
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_query {
+	uint32		method;		/**< method */
+	uint8		request;	/**< Query request. */
+	uint8		status;		/**< bitmask 0 -- disable, 0x1 -- enable collection, */
+					/* 0x2 -- Use generic event, 0x4 -- use event log */
+	uint16		index;		/**< The current frame index [0 to total_frames - 1]. */
+	uint16		mode;		/**< Initiator or Target */
+	uint8		busy;		/**< tof sm is busy */
+	uint8		remote;		/**< Remote collect data */
+} BWL_POST_PACKED_STRUCT wl_proxd_collect_query_t;
+#include <packed_section_end.h>
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_header {
+	uint16		total_frames;			/**< The total frames for this collect. */
+	uint16		nfft;				/**< nfft value */
+	uint16		bandwidth;			/**< bandwidth */
+	uint16		channel;			/**< channel number */
+	uint32		chanspec;			/**< channel spec */
+	uint32		fpfactor;			/**< avb timer value factor */
+	uint16		fpfactor_shift;			/**< avb timer value shift bits */
+	int32		distance;			/**< distance calculated by fw */
+	uint32		meanrtt;			/**< mean of RTTs */
+	uint32		modertt;			/**< mode of RTTs */
+	uint32		medianrtt;			/**< median of RTTs */
+	uint32		sdrtt;				/**< standard deviation of RTTs */
+	uint32		clkdivisor;			/**< clock divisor */
+	uint16		chipnum;			/**< chip type */
+	uint8		chiprev;			/**< chip revision */
+	uint8		phyver;				/**< phy version */
+	struct ether_addr	localMacAddr;		/**< local mac address */
+	struct ether_addr	remoteMacAddr;		/**< remote mac address */
+	wl_proxd_params_tof_tune_t params;
+} BWL_POST_PACKED_STRUCT wl_proxd_collect_header_t;
+#include <packed_section_end.h>
+
+
+#ifdef WL_NAN
+/*  ********************** NAN wl interface struct types and defs ******************** */
+/*
+ * Uses new common IOVAR batch processing mechanism
+ */
+
+/*
+ * Common macros
+ */
+#define WL_NAN_IOCTL_VERSION			0x2
+/* < some sufficient ioc buff size for our module */
+#define WL_NAN_IOC_BUFSZ			256
+/* some sufficient ioc buff size for dump commands */
+#define WL_NAN_IOC_BUFSZ_EXT			1024
+#define WL_NAN_MAX_SIDS_IN_BEACONS		127 /* Max allowed SIDs */
+#define WL_NAN_MASTER_RANK_LEN			8
+#define WL_NAN_RANGE_LIMITED			0x0040 /* Publish/Subscribe flags */
+
+/** Event generation indicator (default is continuous) */
+#define WL_NAN_MATCH_ONCE			0x100000
+#define WL_NAN_MATCH_NEVER			0x200000
+
+/* Bits specific to Publish */
+#define WL_NAN_PUB_UNSOLICIT			0x1000 /** Unsolicited transmissions */
+#define WL_NAN_PUB_SOLICIT			0x2000 /** Solicited transmissions */
+#define WL_NAN_PUB_BOTH				0x3000
+
+/**
+ * Set for broadcast solicited transmission.
+ * Do not set for unicast solicited transmission
+ */
+#define WL_NAN_PUB_BCAST			0x4000
+#define WL_NAN_PUB_EVENT			0x8000 /** Generate event on each solicited tx */
+#define WL_NAN_PUB_SOLICIT_PENDING		0x10000 /** solicited publish tx */
+
+/** Follow-up frames */
+#define WL_NAN_FOLLOWUP				0x20000
+
+/** Bits specific to Subscribe */
+/** Active subscribe mode (Leave unset for passive) */
+#define WL_NAN_SUB_ACTIVE			0x1000
+/** Service info in publish required for Match event */
+#define WL_NAN_SUB_MATCH_IF_SVC_INFO		0x2000
+
+/** Special values for time to live (ttl) parameter */
+#define WL_NAN_TTL_UNTIL_CANCEL			0xFFFFFFFF
+/* Publish -  runs until first transmission
+ * Subscribe - runs until first  DiscoveryResult event
+ */
+#define WL_NAN_TTL_FIRST			0
+
+/** The service hash (service id) is exactly this many bytes. */
+#define WL_NAN_SVC_HASH_LEN			6
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_NAN_HASHES_PER_BLOOM			4 /** Number of hash functions per bloom filter */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* no. of max last disc results */
+#define WL_NAN_MAX_DISC_RESULTS			3
+
+/* Max len of Rx and Tx filters */
+#define WL_NAN_MAX_SVC_MATCH_FILTER_LEN	255
+
+/* Max service name len */
+#define WL_NAN_MAX_SVC_NAME_LEN	32
+
+/* Type of Data path connection */
+#define WL_NAN_DP_TYPE_UNICAST			0
+#define WL_NAN_DP_TYPE_MULTICAST		1
+
+/* Post disc attr ID type */
+typedef uint8 wl_nan_post_disc_attr_id_t;
+
+/*
+ * Component IDs
+ */
+typedef enum {
+	WL_NAN_COMPID_CONFIG = 1,
+	WL_NAN_COMPID_ELECTION = 2,
+	WL_NAN_COMPID_SD = 3,
+	WL_NAN_COMPID_TIMESYNC = 4,
+	WL_NAN_COMPID_DATA_PATH = 5,
+	WL_NAN_COMPID_DEBUG = 15 /* Keep this at the end */
+} wl_nan_comp_id_t;
+
+#define WL_NAN_COMP_SHIFT	8
+#define WL_NAN_COMP_MASK(_c)	(0x0F & ((uint8)(_c)))
+#define WL_NAN_COMP_ID(_c)	(WL_NAN_COMP_MASK(_c) << WL_NAN_COMP_SHIFT)
+
+/* NAN Events */
+
+#define WLC_E_NAN_CRITICAL	1
+#define WLC_E_NAN_NON_CRITICAL	2
+
+/** Instance ID type (unique identifier) */
+typedef uint8 wl_nan_instance_id_t;
+
+/* Publish sent for a subscribe */
+/* WL_NAN_EVENT_REPLIED */
+
+typedef struct wl_nan_ev_replied {
+	struct ether_addr	sub_mac; /* Subscriber MAC */
+	wl_nan_instance_id_t	pub_id; /* Publisher Instance ID */
+	uint8			sub_id; /* Subscriber ID */
+	int8			sub_rssi; /* Subscriber RSSI */
+	uint8			pad[3];
+} wl_nan_ev_replied_t;
+
+/* Subscribe or Publish instance Terminated */
+
+/* WL_NAN_EVENT_TERMINATED */
+
+#define	NAN_SD_TERM_REASON_TIMEOUT	1
+#define	NAN_SD_TERM_REASON_HOSTREQ	2
+#define	NAN_SD_TERM_REASON_FWTERM	3
+#define	NAN_SD_TERM_REASON_FAIL		4
+
+typedef struct wl_nan_ev_terminated {
+	uint8 instance_id;	/* publish / subscribe instance id */
+	uint8 reason;		/* 1=timeout, 2=Host/IOVAR, 3=FW Terminated 4=Failure */
+	uint8 svctype;		/* 0 - Publish, 0x1 - Subscribe */
+	uint8 pad;		/* Align */
+} wl_nan_ev_terminated_t;
+
+/* Follow up received against a pub / subscr */
+/* WL_NAN_EVENT_RECEIVE */
+
+typedef struct wl_nan_ev_receive {
+	struct ether_addr remote_addr;	/* Peer NAN device MAC */
+	uint8	local_id;		/* Local subscribe or publish ID */
+	uint8	remote_id;		/* Remote subscribe or publish ID */
+	int8	fup_rssi;
+	uint8	pad[3];
+} wl_nan_ev_receive_t;
+
+/*
+ * TLV IDs
+ */
+enum wl_nan_cmd_xtlv_id {
+	WL_NAN_XTLV_MAC_ADDR = 0x120,
+	WL_NAN_XTLV_MATCH_RX = 0x121,
+	WL_NAN_XTLV_MATCH_TX = 0x122,
+	WL_NAN_XTLV_SVC_INFO = 0x123,
+	WL_NAN_XTLV_SVC_NAME = 0x124,
+	WL_NAN_XTLV_SR_FILTER = 0x125,
+	WL_NAN_XTLV_FOLLOWUP = 0x126,
+	WL_NAN_XTLV_SVC_LIFE_COUNT = 0x127,
+	WL_NAN_XTLV_AVAIL = 0x128,
+	WL_NAN_XTLV_SDF_RX = 0x129,
+	WL_NAN_XTLV_SDE_CONTROL = 0x130,
+	WL_NAN_XTLV_SDE_RANGE_LIMIT = 0x131,
+	WL_NAN_XTLV_NAN_AF = 0x132,
+	WL_NAN_XTLV_SD_TERMINATE = 0x133,
+	WL_NAN_XTLV_CLUSTER_ID = 0x134,
+	WL_NAN_XTLV_PEER_RSSI = 0x135,
+	WL_NAN_XTLV_BCN_RX = 0x136,
+	WL_NAN_XTLV_REPLIED = 0x137, /* Publish sent for a subscribe */
+	WL_NAN_XTLV_RECEIVED = 0x138 /* FUP Received */
+};
+
+#define WL_NAN_CMD_CFG_COMP_ID		0x01
+#define WL_NAN_CMD_ELECTION_COMP_ID	0x02
+#define WL_NAN_CMD_SD_COMP_ID		0x03
+#define WL_NAN_CMD_SYNC_COMP_ID		0x04
+#define WL_NAN_CMD_DATA_COMP_ID		0x05
+#define WL_NAN_CMD_DAM_COMP_ID		0x06
+#define WL_NAN_CMD_RANGE_COMP_ID	0x07
+#define WL_NAN_CMD_DBG_COMP_ID		0x0f
+
+#define WL_NAN_CMD_COMP_SHIFT         8
+#define NAN_CMD(x, y)  (((x) << WL_NAN_CMD_COMP_SHIFT) | (y))
+
+enum wl_nan_sub_cmd_xtlv_id {
+	 /* nan cfg sub-commands */
+	WL_NAN_CMD_CFG_ENABLE = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x01),
+	WL_NAN_CMD_CFG_STATE = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x02),
+	WL_NAN_CMD_CFG_HOP_CNT = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x03),
+	WL_NAN_CMD_CFG_HOP_LIMIT = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x04),
+	WL_NAN_CMD_CFG_WARMUP_TIME = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x05),
+	WL_NAN_CMD_CFG_RSSI_THRESHOLD = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x06),
+	WL_NAN_CMD_CFG_STATUS = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x07),
+	WL_NAN_CMD_CFG_OUI = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x08),
+	WL_NAN_CMD_CFG_COUNT = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x09),
+	WL_NAN_CMD_CFG_CLEARCOUNT = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0a),
+	WL_NAN_CMD_CFG_CHANNEL = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0b),
+	WL_NAN_CMD_CFG_BAND = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0c),
+	WL_NAN_CMD_CFG_CID = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0d),
+	WL_NAN_CMD_CFG_IF_ADDR = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0e),
+	WL_NAN_CMD_CFG_BCN_INTERVAL = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0f),
+	WL_NAN_CMD_CFG_SDF_TXTIME = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x10),
+	WL_NAN_CMD_CFG_STOP_BCN_TX = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x11),
+	WL_NAN_CMD_CFG_SID_BEACON = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x12),
+	WL_NAN_CMD_CFG_DW_LEN = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x13),
+	WL_NAN_CMD_CFG_AVAIL = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x14),
+	WL_NAN_CMD_CFG_AWAKE_DW = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x15),
+	WL_NAN_CMD_CFG_WFA_TM = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x16),
+	WL_NAN_CMD_CFG_MAX = WL_NAN_CMD_CFG_WFA_TM, /* Add new commands before and update */
+
+	/* nan election sub-commands */
+	WL_NAN_CMD_ELECTION_HOST_ENABLE = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x01),
+	WL_NAN_CMD_ELECTION_METRICS_CONFIG = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x02),
+	WL_NAN_CMD_ELECTION_METRICS_STATE = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x03),
+	WL_NAN_CMD_ELECTION_JOIN = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x04),
+	WL_NAN_CMD_ELECTION_LEAVE = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x05),
+	WL_NAN_CMD_ELECTION_MERGE = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x06),
+	WL_NAN_CMD_ELECTION_STOP = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x07),
+	WL_NAN_CMD_ELECTION_MAX = WL_NAN_CMD_ELECTION_STOP, /* New commands go before and update */
+
+	/* nan SD sub-commands */
+	WL_NAN_CMD_SD_PARAMS = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x01),
+	WL_NAN_CMD_SD_PUBLISH = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x02),
+	WL_NAN_CMD_SD_PUBLISH_LIST = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x03),
+	WL_NAN_CMD_SD_CANCEL_PUBLISH = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x04),
+	WL_NAN_CMD_SD_SUBSCRIBE = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x05),
+	WL_NAN_CMD_SD_SUBSCRIBE_LIST = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x06),
+	WL_NAN_CMD_SD_CANCEL_SUBSCRIBE = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x07),
+	WL_NAN_CMD_SD_VND_INFO = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x08),
+	WL_NAN_CMD_SD_STATS = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x09),
+	WL_NAN_CMD_SD_TRANSMIT = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x0a),
+	WL_NAN_CMD_SD_FUP_TRANSMIT = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x0b),
+	WL_NAN_CMD_SD_CONNECTION = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x0c),
+	WL_NAN_CMD_SD_SHOW = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x0d),
+	WL_NAN_CMD_SD_MAX = WL_NAN_CMD_SD_SHOW, /* New commands go before and update */
+
+	/* nan time sync sub-commands */
+	WL_NAN_CMD_SYNC_TSRESERVE = NAN_CMD(WL_NAN_CMD_SYNC_COMP_ID, 0x01),
+	WL_NAN_CMD_SYNC_TSSCHEDULE = NAN_CMD(WL_NAN_CMD_SYNC_COMP_ID, 0x01),
+	WL_NAN_CMD_SYNC_TSRELEASE = NAN_CMD(WL_NAN_CMD_SYNC_COMP_ID, 0x01),
+	WL_NAN_CMD_SYNC_MAX = WL_NAN_CMD_SYNC_TSRELEASE, /* New ones before and update */
+
+	/* nan2 commands */
+	WL_NAN_CMD_DATA_CONFIG = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x01),
+	WL_NAN_CMD_DATA_AUTOCONN = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x02),
+	WL_NAN_CMD_DATA_RSVD03 = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x03),
+	WL_NAN_CMD_DATA_DATAREQ = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x04),
+	WL_NAN_CMD_DATA_DATARESP = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x05),
+	WL_NAN_CMD_DATA_DATAEND = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x06),
+	WL_NAN_CMD_DATA_SCHEDUPD = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x07),
+	WL_NAN_CMD_DATA_RSVD08 = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x08),
+	WL_NAN_CMD_DATA_CAP = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x9),
+	WL_NAN_CMD_DATA_STATUS = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x0a),
+	WL_NAN_CMD_DATA_STATS = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x0b),
+	WL_NAN_CMD_DATA_RSVD0C = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x0c),
+	WL_NAN_CMD_DATA_NDP_SHOW = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x0d),
+	WL_NAN_CMD_DATA_DATACONF = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x0e),
+	WL_NAN_CMD_DATA_PATH_MAX = WL_NAN_CMD_DATA_DATACONF, /* New ones before and update */
+
+	/* nan dam sub-commands */
+	WL_NAN_CMD_DAM_CFG = NAN_CMD(WL_NAN_CMD_DAM_COMP_ID, 0x01),
+	WL_NAN_CMD_DAM_MAX = WL_NAN_CMD_DAM_CFG,  /* New ones before and update */
+
+	/* nan2.0 ranging commands */
+	WL_NAN_CMD_RANGE_REQUEST = NAN_CMD(WL_NAN_CMD_RANGE_COMP_ID, 0x01),
+	WL_NAN_CMD_RANGE_AUTO = NAN_CMD(WL_NAN_CMD_RANGE_COMP_ID, 0x02),
+	WL_NAN_CMD_RANGE_RESPONSE = NAN_CMD(WL_NAN_CMD_RANGE_COMP_ID, 0x03),
+	WL_NAN_CMD_RANGE_CANCEL = NAN_CMD(WL_NAN_CMD_RANGE_COMP_ID, 0x04),
+
+	/*  nan debug sub-commands  */
+	WL_NAN_CMD_DBG_SCAN_PARAMS = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x01),
+	WL_NAN_CMD_DBG_SCAN = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x02),
+	WL_NAN_CMD_DBG_SCAN_RESULTS =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x03),
+	WL_NAN_CMD_DBG_EVENT_MASK =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x04),
+	WL_NAN_CMD_DBG_EVENT_CHECK =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x05),
+	WL_NAN_CMD_DBG_DUMP =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x06),
+	WL_NAN_CMD_DBG_CLEAR =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x07),
+	WL_NAN_CMD_DBG_RSSI =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x08),
+	WL_NAN_CMD_DBG_DEBUG =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x09),
+	WL_NAN_CMD_DBG_TEST1 =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x0a),
+	WL_NAN_CMD_DBG_TEST2 =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x0b),
+	WL_NAN_CMD_DBG_TEST3 =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x0c),
+	WL_NAN_CMD_DBG_DISC_RESULTS =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x0d),
+	WL_NAN_CMD_DBG_STATS =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x0e),
+	WL_NAN_CMD_DBG_LEVEL =  NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x0f),
+	WL_NAN_CMD_DBG_MAX = WL_NAN_CMD_DBG_LEVEL /* New ones before and update */
+};
+
+/** status - TBD BCME_ vs NAN status - range reserved for BCME_ */
+enum {
+	/* add new status here... */
+
+	WL_NAN_E_INVALID_STARTOFFSET	= -2061,
+	WL_NAN_E_BAD_NA_ENTRY_TYPE	= -2060,
+	WL_NAN_E_INVALID_CHANBMP	= -2059,
+	WL_NAN_E_INVALID_OP_CLASS	= -2058,
+	WL_NAN_E_NO_IES			= -2057,
+	WL_NAN_E_NO_PEER_ENTRY_AVAIL	= -2056,
+	WL_NAN_E_INVALID_PEER		= -2055,
+	WL_NAN_E_PEER_EXISTS		= -2054,
+	WL_NAN_E_PEER_NOTFOUND		= -2053,
+	WL_NAN_E_NO_MEM			= -2052,
+	WL_NAN_E_INVALID_OPTION		= -2051,
+	WL_NAN_E_INVALID_BAND		= -2050,
+	WL_NAN_E_INVALID_MAC		= -2049,
+	WL_NAN_E_BAD_INSTANCE		= -2048,
+	WL_NAN_E_NDC_EXISTS		= -2047,
+	WL_NAN_E_NO_NDC_ENTRY_AVAIL	= -2046,
+	WL_NAN_E_INVALID_NDC_ENTRY = -2045,
+	WL_NAN_E_ERROR			= -1,
+	WL_NAN_E_OK			= 0
+};
+
+typedef int32 wl_nan_status_t;
+
+/** nan cmd list entry  */
+enum wl_nan_sub_cmd_input_flags {
+	WL_NAN_SUB_CMD_FLAG_NONE = 0,
+	WL_NAN_SUB_CMD_FLAG_SKIP = 1, /* Skip to next sub-command on error */
+	WL_NAN_SUB_CMD_FLAG_TERMINATE = 2, /* Terminate processing and return */
+	WL_NAN_SUB_CMD_FLAG_LAST /* Keep this at the end */
+};
+
+/** container for nan events */
+typedef struct wl_nan_ioc {
+	uint16	version;	/**< interface command or event version */
+	uint16	id;			/**< nan ioctl cmd  ID  */
+	uint16	len;		/**< total length of all tlv records in data[]  */
+	uint16	pad;		/**< pad to be 32 bit aligment */
+	uint8	data [1];	/**< var len payload of bcm_xtlv_t type */
+} wl_nan_ioc_t;
+
+/*
+ * NAN sub-command data structures
+ */
+
+/*
+ * Config component WL_NAN_CMD_CFG_XXXX sub-commands
+ * WL_NAN_CMD_CFG_ENABLE
+ */
+enum wl_nan_config_state {
+	WL_NAN_CONFIG_STATE_DISABLE = 0,
+	WL_NAN_CONFIG_STATE_ENABLE = 1
+};
+
+typedef int8 wl_nan_config_state_t;
+
+/*
+ * WL_NAN_CMD_CFG_BAND, WL_NAN_CMD_CFG_RSSI_THRESHOLD(Get only)
+ */
+typedef uint8 wl_nan_band_t;
+
+/*
+ * WL_NAN_CMD_CFG_STATE
+ */
+enum wl_nan_role {
+	WL_NAN_ROLE_AUTO = 0,
+	WL_NAN_ROLE_NON_MASTER_NON_SYNC = 1,
+	WL_NAN_ROLE_NON_MASTER_SYNC = 2,
+	WL_NAN_ROLE_MASTER = 3,
+	WL_NAN_ROLE_ANCHOR_MASTER = 4
+};
+
+typedef uint8 wl_nan_role_t;
+
+typedef struct wl_nan_device_state
+{
+	wl_nan_role_t role;		/* Sync Master, Non-Sync Master */
+	uint8 state;	/* TBD  */
+	uint8 hopcount;	/* Hops to the Anchor Master */
+	struct ether_addr immediate_master; /* Master MAC */
+	struct ether_addr anchor_master;	/* Anchor Master MAC */
+	struct ether_addr cluster_id; /* Cluster ID to which this device belongs to */
+	uint32 tsf_high;  /* NAN Cluster TSFs */
+	uint32 tsf_low;
+} wl_nan_device_state_t;
+
+/*
+ * WL_NAN_CMD_CFG_HOP_CNT, WL_NAN_CMD_CFG_HOP_LIMIT
+ */
+typedef uint8 wl_nan_hop_count_t;
+
+/*
+ * WL_NAN_CMD_CFG_WARMUP_TIME
+ */
+typedef uint32 wl_nan_warmup_time_ticks_t;
+
+/*
+ * WL_NAN_CMD_CFG_RSSI_THRESHOLD
+ * rssi_close and rssi_mid are used to transition master to non-master
+ * role by NAN state machine. rssi thresholds corresponding to the band
+ * will be updated.
+ */
+typedef struct wl_nan_rssi_threshold {
+	wl_nan_band_t band;
+	int8 rssi_close;
+	int8 rssi_mid;
+	uint8 pad;
+} wl_nan_rssi_threshold_t;
+
+/*
+ * WL_NAN_CMD_CFG_STATUS
+ */
+typedef struct wl_nan_cfg_status {
+	uint8 enabled;
+	uint8 inited;
+	uint8 joined;
+	uint8 merged;
+	uint8 role;
+	uint32 chspec[2];
+	uint8 mr[8];                    /**< Master Rank */
+	uint8 amr[8];			/**< Anchor Master Rank */
+	uint32 cnt_pend_txfrm;		/**< pending TX frames */
+	uint32 cnt_bcn_tx;		/**< TX disc/sync beacon count */
+	uint32 cnt_bcn_rx;		/**< RX disc/sync beacon count */
+	uint32 cnt_svc_disc_tx;		/**< TX svc disc frame count */
+	uint32 cnt_svc_disc_rx;		/**< RX svc disc frame count */
+	uint32 ambtt;                   /**< Anchor master beacon target time */
+	struct ether_addr cid;          /**< Cluster id */
+	uint8 hop_count;                /**< Hop count */
+} wl_nan_cfg_status_t;
+
+/*
+ * WL_NAN_CMD_CFG_OUI
+ */
+typedef struct wl_nan_oui_type {
+	uint8 nan_oui[DOT11_OUI_LEN];
+	uint8 type;
+} wl_nan_oui_type_t;
+
+/*
+ * WL_NAN_CMD_CFG_COUNT
+ */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+typedef struct wl_nan_count {
+	uint32 cnt_bcn_tx;		/**< TX disc/sync beacon count */
+	uint32 cnt_bcn_rx;		/**< RX disc/sync beacon count */
+	uint32 cnt_svc_disc_tx;		/**< TX svc disc frame count */
+	uint32 cnt_svc_disc_rx;		/**< RX svc disc frame count */
+} wl_nan_count_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/*
+ * Election component WL_NAN_CMD_ELECTION_XXXX sub-commands
+ * WL_NAN_CMD_ELECTION_HOST_ENABLE
+ */
+enum wl_nan_enable_flags {
+	WL_NAN_DISABLE_FLAG_HOST_ELECTION = 0,
+	WL_NAN_ENABLE_FLAG_HOST_ELECTION = 1
+};
+
+/*
+ * 0 - disable host based election
+ * 1 - enable host based election
+ */
+typedef uint8 wl_nan_host_enable_t;
+
+/*
+ * WL_NAN_CMD_ELECTION_METRICS_CONFIG
+ */
+/* Set only */
+typedef struct wl_nan_election_metric_config {
+	uint8 random_factor; /* Configured random factor */
+	uint8 master_pref;	/* configured master preference */
+	uint8 pad[2];
+} wl_nan_election_metric_config_t;
+
+/*
+ * WL_NAN_CMD_ELECTION_METRICS_STATE
+ */
+/* Get only */
+typedef struct wl_nan_election_metric_state {
+	uint8 random_factor; /* random factor used in MIs */
+	uint8 master_pref;	 /* Master advertised in MIs */
+	uint8 pad[2];
+} wl_nan_election_metric_state_t;
+
+/*
+ * WL_NAN_CMD_ELECTION_LEAVE
+ * WL_NAN_CMD_ELECTION_STOP
+ */
+typedef struct ether_addr wl_nan_cluster_id_t;
+
+/*
+ * WL_NAN_CMD_ELECTION_JOIN
+ */
+typedef struct wl_nan_join {
+	uint8 start_cluster;	/* Start a cluster */
+	uint8 pad[3];
+	wl_nan_cluster_id_t cluster_id;	/* Cluster ID to join */
+} wl_nan_join_t;
+
+/*
+ * WL_NAN_CMD_ELECTION_MERGE
+ * 0 - disable cluster merge
+ * 1 - enable cluster merge
+ */
+typedef uint8 wl_nan_merge_enable_t;
+
+/*
+ * WL_NAN_CMD_CFG_STATE
+ * role = 0 means configuration by firmware; otherwise by host
+ * when host configures role, also need target master address to sync to
+ */
+typedef struct wl_nan_role_config {
+	wl_nan_role_t role;
+	struct ether_addr target_master;
+	uint8 pad;
+} wl_nan_role_config_t;
+
+/*
+ * Service Discovery component WL_NAN_CMD_SD_XXXX sub-commands
+ * WL_NAN_CMD_SD_PUBLISH
+ * WL_NAN_CMD_SD_SUBSCRIBE
+ */
+#define WL_NAN_SD_PUB_UNSOLICIT 0x0001 /* Unsolicited transmissions */
+#define WL_NAN_SD_PUB_SOLICIT   0x0002 /* Solicited transmissions */
+#define WL_NAN_SD_PUB_BCAST     0x0004 /* for solicited 1= broadcast, 0=unicast */
+#define WL_NAN_SD_PUB_EVENT     0x0008 /* Generate event on solicited transmission */
+enum wl_nan_sd_optional_field_types
+{
+	NAN_SD_FIELD_MATCH_FILTER_SERVICE_INFO = 1,
+	NAN_SD_FIELD_MATCH_FILTER_TX = 2,
+	NAN_SD_FIELD_MATCH_FILTER_RX = 3,
+	NAN_SD_FIELD_MATCH_FILTER_SRF = 4
+};
+
+typedef int8 wl_nan_sd_optional_field_types_t;
+
+/*
+ * WL_NAN_CMD_SD_PARAMS
+ */
+typedef struct wl_nan_sd_params
+{
+	uint16	length; /* length including options */
+	uint16	flags; /* bitmap representing aforesaid optional flags */
+	uint8	svc_hash[WL_NAN_SVC_HASH_LEN]; /* Hash for the service name */
+	uint8	instance_id; /* Instance of the current service */
+	int8	proximity_rssi; /* RSSI limit to Rx subscribe or pub SDF 0 no effect */
+	uint8	period; /* period of the unsolicited SDF xmission in DWs */
+	int32	ttl; /* TTL for this instance id, -1 will run till cancelled */
+	tlv_t	optional[1]; /* optional fields in the SDF  as appropriate */
+} wl_nan_sd_params_t;
+
+/*
+ * WL_NAN_CMD_SD_PUBLISH_LIST
+ * WL_NAN_CMD_SD_SUBSCRIBE_LIST
+ */
+typedef struct wl_nan_service_info
+{
+	uint8 instance_id;	/* Publish instance ID */
+	uint8 service_hash[WL_NAN_SVC_HASH_LEN]; /* Hash for service name */
+} wl_nan_service_info_t;
+
+typedef struct wl_nan_service_list
+{
+	uint16 id_count; /* Number of registered publish/subscribe services */
+	wl_nan_service_info_t list[1]; /* service info defined by nan_service instance */
+} wl_nan_service_list_t;
+
+/*
+ * WL_NAN_CMD_CFG_BCN_INTERVAL
+ */
+typedef uint16 wl_nan_disc_bcn_interval_t;
+
+/*
+ * WL_NAN_CMD_CFG_SDF_TXTIME
+ */
+typedef uint16 wl_nan_svc_disc_txtime_t;
+
+/*
+ * WL_NAN_CMD_CFG_STOP_BCN_TX
+ */
+typedef uint16 wl_nan_stop_bcn_tx_t;
+
+/*
+ * WL_NAN_CMD_CFG_SID_BEACON
+ */
+typedef struct wl_nan_sid_beacon_control {
+	uint8 sid_enable;	/* Flag to indicate the inclusion of Service IDs in Beacons */
+	uint8 sid_count;	/* Limit for number of SIDs to be included in Beacons */
+	uint8 pad[2];
+} wl_nan_sid_beacon_control_t;
+
+/*
+ * WL_NAN_CMD_CFG_DW_LEN
+ */
+typedef uint16 wl_nan_dw_len_t;
+
+/*
+ * WL_NAN_CMD_CFG_AWAKE_DW
+ */
+typedef struct wl_nan_awake_dw {
+	wl_nan_band_t band;	/* 0 - b mode 1- a mode */;
+	uint8 interval;		/* 1 or 2 or 4 or 8 or 16 */
+	uint16 pad;
+} wl_nan_awake_dw_t;
+
+/*
+ * WL_NAN_CMD_SD_CANCEL_PUBLISH
+ * WL_NAN_CMD_SD_CANCEL_SUBSCRIBE
+ */
+typedef uint8 wl_nan_instance_id; /* Instance ID of an active publish instance */
+
+/*
+ * WL_NAN_CMD_SD_VND_INFO
+ */
+typedef struct wl_nan_sd_vendor_info
+{
+	uint16 length; /* Size in bytes of the payload following this field */
+	uint8 data[1];	/* Vendor Information */
+} wl_nan_sd_vendor_info_t;
+
+/*
+ * WL_NAN_CMD_SD_STATS
+ */
+typedef struct wl_nan_sd_stats {
+	uint32  sdftx;
+	uint32  sdfrx;
+	uint32  sdsrffail;
+	uint32  sdrejrssi;
+	uint32  sdfollowuprx;
+	uint32  sdsubmatch;
+	uint32  sdpubreplied;
+	uint32  sdmftfail1;
+	uint32  sdmftfail2;
+	uint32  sdmftfail3;
+	uint32  sdmftfail4;
+}  wl_nan_sd_stats_t;
+
+/*
+ * WL_NAN_CMD_SD_TRANSMIT
+ * WL_NAN_CMD_SD_FUP_TRANSMIT
+ */
+typedef struct wl_nan_sd_transmit {
+	uint8 local_service_id; /* Sender Service ID */
+	uint8 requestor_service_id; /* Destination Service ID */
+	struct ether_addr destination_addr; /* Destination MAC */
+	uint16 token; /* follow_up_token when a follow-up msg is queued successfully */
+	uint8 priority; /* requested relative prio */
+	uint8 service_info_len; /* size in bytes of the service info payload */
+	wl_nan_service_info_t service_info[1]; /* Service Info payload */
+} wl_nan_sd_transmit_t;
+
+/*
+ * WL_NAN_CMD_SYNC_TSRESERVE
+ */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/** time slot */
+#define NAN_MAX_TIMESLOT	32
+typedef struct wl_nan_timeslot {
+	uint32	abitmap; /**< available bitmap */
+	uint32 chanlist[NAN_MAX_TIMESLOT];
+} wl_nan_timeslot_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/*
+ * WL_NAN_CMD_SYNC_TSRELEASE
+ */
+typedef uint32 wl_nan_ts_bitmap_t;
+
+/* nan passive scan params */
+#define NAN_SCAN_MAX_CHCNT 8
+typedef struct wl_nan_scan_params {
+	uint16 scan_time;
+	uint16 home_time;
+	uint16 ms_intvl; /**< interval between merge scan */
+	uint16 ms_dur;  /**< duration of merge scan */
+	uint16 chspec_num;
+	uint8 pad[2];
+	chanspec_t chspec_list[NAN_SCAN_MAX_CHCNT]; /**< act. used 3, 5 rfu */
+} wl_nan_scan_params_t;
+
+/*
+ * WL_NAN_CMD_DBG_SCAN
+ */
+typedef struct wl_nan_dbg_scan {
+	struct ether_addr cid;
+	uint8 pad[2];
+} wl_nan_dbg_scan_t;
+
+/* NAN_DBG_LEVEL */
+typedef struct wl_nan_dbg_level {
+	uint32 nan_err_level; /* for Error levels */
+	uint32 nan_dbg_level; /* for bebug logs and trace */
+	uint32 nan_info_level; /* for dumps like prhex */
+} wl_nan_dbg_level_t;
+
+/*
+ * WL_NAN_CMD_DBG_EVENT_MASK
+ */
+typedef uint32 wl_nan_event_mask_t;
+
+/*
+ * WL_NAN_CMD_DBG_EVENT_CHECK
+ */
+typedef uint8 wl_nan_dbg_ifname[BCM_MSG_IFNAME_MAX];
+
+/*
+ * WL_NAN_CMD_DBG_DUMP
+ * WL_NAN_CMD_DBG_CLEAR
+ */
+enum wl_nan_dbg_dump_type {
+	WL_NAN_DBG_DT_RSSI_DATA = 1,
+	WL_NAN_DBG_DT_STATS_DATA = 2,
+	/*
+	 * Additional enums before this line
+	 */
+	WL_NAN_DBG_DT_INVALID
+};
+typedef int8 wl_nan_dbg_dump_type_t;
+
+/** various params and ctl swithce for nan_debug instance  */
+/*
+ * WL_NAN_CMD_DBG_DEBUG
+ */
+typedef struct wl_nan_debug_params {
+	uint16	cmd;	/**< debug cmd to perform a debug action */
+	uint16	status;
+	uint32	msglevel; /**< msg level if enabled */
+	uint8	enabled; /**< runtime debuging enabled */
+	uint8 collect;
+} wl_nan_debug_params_t;
+
+
+typedef struct wl_nan_sched_svc_timeslot_s {
+	uint32 abitmap; /* availability bitmap */
+	uint32 chanlist[NAN_MAX_TIMESLOT];
+	uint8  res; /* resolution: 0 = 16ms, 1 = 32ms, 2 = 64ms 3 = reserved. REfer NAN spec */
+	uint8  mapid; /* mapid from NAN spec. Used to differentiate 2G Vs 5G band */
+} wl_nan_sched_svc_timeslot_t;
+
+
+/* nan passive scan params */
+#define NAN_SCAN_MAX_CHCNT 8
+typedef struct nan_scan_params {
+	uint16 scan_time;
+	uint16 home_time;
+	uint16 ms_intvl; /**< interval between merge scan */
+	uint16 ms_dur;  /**< duration of merge scan */
+	uint16 chspec_num;
+	uint8 pad[2];
+	chanspec_t chspec_list[NAN_SCAN_MAX_CHCNT]; /**< act. used 3, 5 rfu */
+} nan_scan_params_t;
+
+#define NAN_MASTER_RANK_LEN 8
+/* nan cmd IDs */
+enum wl_nan_cmds {
+	 /* nan cfg /disc & dbg ioctls */
+	WL_NAN_CMD_ENABLE = 1,
+	WL_NAN_CMD_ATTR = 2,
+	WL_NAN_CMD_NAN_JOIN = 3,
+	WL_NAN_CMD_LEAVE = 4,
+	WL_NAN_CMD_MERGE = 5,
+	WL_NAN_CMD_STATUS = 6,
+	WL_NAN_CMD_TSRESERVE = 7,
+	WL_NAN_CMD_TSSCHEDULE = 8,
+	WL_NAN_CMD_TSRELEASE = 9,
+	WL_NAN_CMD_OUI = 10,
+	WL_NAN_CMD_OOB_AF = 11,
+
+	WL_NAN_CMD_COUNT = 15,
+	WL_NAN_CMD_CLEARCOUNT = 16,
+
+	/*  discovery engine commands */
+	WL_NAN_CMD_PUBLISH = 20,
+	WL_NAN_CMD_SUBSCRIBE = 21,
+	WL_NAN_CMD_CANCEL_PUBLISH = 22,
+	WL_NAN_CMD_CANCEL_SUBSCRIBE = 23,
+	WL_NAN_CMD_TRANSMIT = 24,
+	WL_NAN_CMD_CONNECTION = 25,
+	WL_NAN_CMD_SHOW = 26,
+	WL_NAN_CMD_STOP = 27,	/* stop nan for a given cluster ID  */
+	/*  nan debug iovars & cmds  */
+	WL_NAN_CMD_SCAN_PARAMS = 46,
+	WL_NAN_CMD_SCAN = 47,
+	WL_NAN_CMD_SCAN_RESULTS = 48,
+	WL_NAN_CMD_EVENT_MASK = 49,
+	WL_NAN_CMD_EVENT_CHECK = 50,
+	WL_NAN_CMD_DUMP = 51,
+	WL_NAN_CMD_CLEAR = 52,
+	WL_NAN_CMD_RSSI = 53,
+
+	WL_NAN_CMD_DEBUG = 60,
+	WL_NAN_CMD_TEST1 = 61,
+	WL_NAN_CMD_TEST2 = 62,
+	WL_NAN_CMD_TEST3 = 63,
+	WL_NAN_CMD_DISC_RESULTS = 64,
+	/* nan 2.0 data path commands */
+	WL_NAN_CMD_DATAPATH = 65
+};
+
+/*   NAN DP interface commands  */
+enum wl_nan_dp_cmds {
+	/* nan 2.0 ioctls */
+	WL_NAN_CMD_DP_CAP = 1000,
+	WL_NAN_CMD_DP_CONFIG = 1001,
+	WL_NAN_CMD_DP_CREATE = 1002,
+	WL_NAN_CMD_DP_AUTO_CONNECT = 1003,
+	WL_NAN_CMD_DP_DATA_REQ = 1004,
+	WL_NAN_CMD_DP_DATA_RESP = 1005,
+	WL_NAN_CMD_DP_SCHED_UPD = 1006,
+	WL_NAN_CMD_DP_END = 1007,
+	WL_NAN_CMD_DP_CONNECT = 1008,
+	WL_NAN_CMD_DP_STATUS = 1009
+};
+
+/* TODO Should remove this fixed length */
+#define WL_NAN_DATA_SVC_SPEC_INFO_LEN 32 /* arbitrary */
+#define WL_NAN_DP_MAX_SVC_INFO	      0xFF
+#define WL_NAN_DATA_NDP_INST_SUPPORT 16
+
+/* Nan flags */
+#define WL_NAN_DP_FLAG_SVC_INFO	      (1 << 0)
+#define WL_NAN_DP_FLAG_CONFIRM	      (1 << 1)
+#define WL_NAN_DP_FLAG_EXPLICIT_CFM   (1 << 2)
+
+/* to be done */
+typedef struct wl_nan_dp_cap {
+	uint8 tbd;
+} wl_nan_dp_cap_t;
+
+/** Flag bits for Publish and Subscribe (wl_nan_disc_params_t flags) */
+#define WL_NAN_RANGE_LIMITED           0x0040
+/** Event generation indicator (default is continuous) */
+#define WL_NAN_MATCH_ONCE              0x100000
+#define WL_NAN_MATCH_NEVER             0x200000
+/* Bits specific to Publish */
+/** Unsolicited transmissions */
+#define WL_NAN_PUB_UNSOLICIT           0x1000
+/** Solicited transmissions */
+#define WL_NAN_PUB_SOLICIT             0x2000
+#define WL_NAN_PUB_BOTH                0x3000
+/** Set for broadcast solicited transmission. Do not set for unicast solicited transmission */
+#define WL_NAN_PUB_BCAST               0x4000
+/** Generate event on each solicited transmission */
+#define WL_NAN_PUB_EVENT               0x8000
+/** Used for one-time solicited Publish functions to indicate transmision occurred */
+#define WL_NAN_PUB_SOLICIT_PENDING	0x10000
+/** Follow-up frames */
+#define WL_NAN_FOLLOWUP			0x20000
+/** Bits specific to Subscribe */
+/** Active subscribe mode (Leave unset for passive) */
+#define WL_NAN_SUB_ACTIVE              0x1000
+/** Service info in publish required for Match event */
+#define WL_NAN_SUB_MATCH_IF_SVC_INFO   0x2000
+
+/** Special values for time to live (ttl) parameter */
+#define WL_NAN_TTL_UNTIL_CANCEL	0xFFFFFFFF
+/* Publish -  runs until first transmission
+ * Subscribe - runs until first  DiscoveryResult event
+ */
+#define WL_NAN_TTL_FIRST	0
+
+/** The service hash (service id) is exactly this many bytes. */
+#define WL_NAN_SVC_HASH_LEN	6
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/** Number of hash functions per bloom filter */
+#define WL_NAN_HASHES_PER_BLOOM 4
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/* no. of max last disc results */
+#define WL_NAN_MAX_DISC_RESULTS	3
+
+/** Mandatory parameters for publish/subscribe iovars - NAN_TLV_SVC_PARAMS */
+typedef struct wl_nan_disc_params_s {
+	/** Periodicity of unsolicited/query transmissions, in DWs */
+	uint32 period;
+	/** Time to live in DWs */
+	uint32 ttl;
+	/** Flag bits */
+	uint32 flags;
+	/** Publish or subscribe service id, i.e. hash of the service name */
+	uint8 svc_hash[WL_NAN_SVC_HASH_LEN];
+	/** pad to make 4 byte alignment, can be used for something else in the future */
+	uint8 pad;
+	/** Publish or subscribe id */
+	wl_nan_instance_id_t instance_id;
+} wl_nan_disc_params_t;
+
+/* recent discovery results */
+typedef struct wl_nan_disc_result_s
+{
+	wl_nan_instance_id_t instance_id;	/* instance id of pub/sub req */
+	wl_nan_instance_id_t peer_instance_id;	/* peer instance id of pub/sub req/resp */
+	uint8 svc_hash[WL_NAN_SVC_HASH_LEN];	/* service descp string */
+	struct ether_addr peer_mac;	/* peer mac address */
+} wl_nan_disc_result_t;
+
+/* list of recent discovery results */
+typedef struct wl_nan_disc_results_s
+{
+	wl_nan_disc_result_t disc_result[WL_NAN_MAX_DISC_RESULTS];
+} wl_nan_disc_results_list_t;
+
+/* nan 1.0 events */
+typedef struct wl_nan_ev_disc_result {
+	wl_nan_instance_id_t pub_id;
+	wl_nan_instance_id_t sub_id;
+	struct ether_addr pub_mac;
+	uint8 opt_tlvs[0];
+} wl_nan_ev_disc_result_t;
+
+typedef struct wl_nan_ev_p2p_avail {
+	struct ether_addr sender;
+	struct ether_addr p2p_dev_addr;
+	uint8 dev_role;
+	uint8 resolution;
+	uint8 repeat;
+	uint8 pad[3];
+	chanspec_t chanspec;
+	uint32 avail_bmap;
+} wl_nan_ev_p2p_avail_t;
+
+/*
+* discovery interface event structures *
+*/
+
+/* mandatory parameters for OOB action frame */
+/* single-shot when bitmap and offset are set to 0; periodic otherwise */
+typedef struct wl_nan_oob_af_params_s
+{
+	/* bitmap for the 32 timeslots in 512TU dw interval */
+	uint32 ts_map;
+	/* offset from start of dw, in us */
+	uint32 tx_offset;
+	struct ether_addr bssid;
+	struct ether_addr dest;
+	uint32 pkt_lifetime;
+	uint16 payload_len;
+	uint8 payload[1];
+} wl_nan_oob_af_params_t;
+
+/* NAN Ranging */
+
+/* Bit defines for global flags */
+#define WL_NAN_RANGING_ENABLE		1 /**< enable RTT */
+#define WL_NAN_RANGING_RANGED		2 /**< Report to host if ranged as target */
+typedef struct nan_ranging_config {
+	uint32 chanspec;		/**< Ranging chanspec */
+	uint16 timeslot;		/**< NAN RTT start time slot  1-511 */
+	uint16 duration;		/**< NAN RTT duration in ms */
+	struct ether_addr allow_mac;	/**< peer initiated ranging: the allowed peer mac
+					 * address, a unicast (for one peer) or
+					 * a broadcast for all. Setting it to all zeros
+					 * means responding to none,same as not setting
+					 * the flag bit NAN_RANGING_RESPOND
+					 */
+	uint16 flags;
+} wl_nan_ranging_config_t;
+
+/** list of peers for self initiated ranging */
+/** Bit defines for per peer flags */
+#define WL_NAN_RANGING_REPORT (1<<0)	/**< Enable reporting range to target */
+typedef struct nan_ranging_peer {
+	uint32 chanspec;		/**< desired chanspec for this peer */
+	uint32 abitmap;			/**< available bitmap */
+	struct ether_addr ea;		/**< peer MAC address */
+	uint8 frmcnt;			/**< frame count */
+	uint8 retrycnt;			/**< retry count */
+	uint16 flags;			/**< per peer flags, report or not */
+} wl_nan_ranging_peer_t;
+typedef struct nan_ranging_list {
+	uint8 count;			/**< number of MAC addresses */
+	uint8 num_peers_done;		/**< host set to 0, when read, shows number of peers
+					 * completed, success or fail
+					 */
+	uint8 num_dws;			/**< time period to do the ranging, specified in dws */
+	uint8 reserve;			/**< reserved field */
+	wl_nan_ranging_peer_t rp[1];	/**< variable length array of peers */
+} wl_nan_ranging_list_t;
+
+/* ranging results, a list for self initiated ranging and one for peer initiated ranging */
+/* There will be one structure for each peer */
+#define WL_NAN_RANGING_STATUS_SUCCESS		1
+#define WL_NAN_RANGING_STATUS_FAIL		2
+#define WL_NAN_RANGING_STATUS_TIMEOUT		3
+#define WL_NAN_RANGING_STATUS_ABORT		4 /**< with partial results if sounding count > 0 */
+typedef struct nan_ranging_result {
+	uint8 status;			/**< 1: Success, 2: Fail 3: Timeout 4: Aborted */
+	uint8 sounding_count;		/**< number of measurements completed (0 = failure) */
+	struct ether_addr ea;		/**< initiator MAC address */
+	uint32 chanspec;		/**< Chanspec where the ranging was done */
+	uint32 timestamp;		/**< 32bits of the TSF timestamp ranging was completed at */
+	uint32 distance;		/**< mean distance in meters expressed as Q4 number.
+					 * Only valid when sounding_count > 0. Examples:
+					 * 0x08 = 0.5m
+					 * 0x10 = 1m
+					 * 0x18 = 1.5m
+					 * set to 0xffffffff to indicate invalid number
+					 */
+	int32 rtt_var;			/**< standard deviation in 10th of ns of RTTs measured.
+					 * Only valid when sounding_count > 0
+					 */
+	struct ether_addr tgtea;	/**< target MAC address */
+} wl_nan_ranging_result_t;
+typedef struct nan_ranging_event_data {
+	uint8 mode;			/**< 1: Result of host initiated ranging */
+					/* 2: Result of peer initiated ranging */
+	uint8 reserved;
+	uint8 success_count;		/**< number of peers completed successfully */
+	uint8 count;			/**< number of peers in the list */
+	wl_nan_ranging_result_t rr[1];	/**< variable array of ranging peers */
+} wl_nan_ranging_event_data_t;
+
+enum {
+	WL_NAN_STATS_RSSI = 1,
+	WL_NAN_STATS_DATA = 2,
+	WL_NAN_STATS_DP = 3,
+/*
+ * ***** ADD before this line ****
+ */
+	WL_NAN_STATS_INVALID
+};
+typedef struct wl_nan_dp_stats {
+	uint32 tbd; /* TBD */
+} wl_nan_dp_stats_t;
+
+typedef struct wl_nan_stats {
+	/* general */
+	uint32 cnt_dw; /* DW slots */
+	uint32 cnt_disc_bcn_sch; /* disc beacon slots */
+	uint32 cnt_amr_exp; /* count of ambtt expiries resetting roles */
+	uint32 cnt_bcn_upd; /* count of beacon template updates */
+	uint32 cnt_bcn_tx; /* count of sync & disc bcn tx */
+	uint32 cnt_bcn_rx; /* count of sync & disc bcn rx */
+	uint32 cnt_sync_bcn_tx; /* count of sync bcn tx within DW */
+	uint32 cnt_disc_bcn_tx; /* count of disc bcn tx */
+	uint32 cnt_sdftx_bcmc; /* count of bcast/mcast sdf tx */
+	uint32 cnt_sdftx_uc; /* count of unicast sdf tx */
+	uint32 cnt_sdftx_fail; /* count of unicast sdf tx fails */
+	uint32 cnt_sdf_rx; /* count of  sdf rx */
+	/* NAN roles */
+	uint32 cnt_am; /* anchor master */
+	uint32 cnt_master; /* master */
+	uint32 cnt_nms; /* non master sync */
+	uint32 cnt_nmns; /* non master non sync */
+	/* TX */
+	uint32 cnt_err_txtime; /* txtime in sync bcn frame not a multiple of dw intv */
+	uint32 cnt_err_unsch_tx; /* tx while not in DW/ disc bcn slot */
+	uint32 cnt_err_bcn_tx; /*  beacon tx error */
+	uint32 cnt_sync_bcn_tx_miss; /* no. of times time delta between 2 cosequetive
+						* sync beacons is more than expected
+						*/
+	/* MSCH */
+	uint32 cnt_err_msch_reg; /* error is Dw/disc reg with msch */
+	uint32 cnt_err_wrong_ch_cb; /* count of msch calbacks in wrong channel */
+	uint32 cnt_dw_skip;	/* count of DW rejected */
+	uint32 cnt_disc_skip; /* count of disc bcn rejected */
+	uint32 cnt_dw_start_early; /* msch cb not at registered time */
+	uint32 cnt_dw_start_late; /* no. of delays in slot start */
+	/* SCANS */
+	uint32 cnt_mrg_scan; /* count of merge scans completed */
+	uint32 cnt_err_ms_rej; /* number of merge scan failed */
+	uint32 cnt_scan_results; /* no. of nan beacons scanned */
+	uint32 cnt_join_scan_rej; /* no. of join scans rejected */
+	uint32 cnt_nan_scan_abort; /* no. of join scans rejected */
+	/* enable/disable */
+	uint32 cnt_nan_enab; /* no. of times nan feature got enabled */
+	uint32 cnt_nan_disab; /* no. of times nan feature got disabled */
+	uint32 cnt_sync_bcn_rx; /* count of sync bcn rx within DW */
+} wl_nan_stats_t;
+
+#define WL_NAN_MAC_MAX_NAN_PEERS 6
+#define WL_NAN_MAC_MAX_RSSI_DATA_PER_PEER  10
+
+typedef struct wl_nan_nbr_rssi {
+	uint8 rx_chan; /* channel number on which bcn rcvd */
+	int32 rssi_raw;  /* received rssi value */
+	int32 rssi_avg;  /* normalized rssi value */
+} wl_nan_peer_rssi_t;
+
+typedef struct wl_nan_peer_rssi_entry {
+	struct ether_addr mac;  /* peer mac address */
+	uint8 flags;   /* TODO:rssi data order: latest first, oldest first etc */
+	uint8 rssi_cnt;   /* rssi data sample present */
+	wl_nan_peer_rssi_t rssi[WL_NAN_MAC_MAX_RSSI_DATA_PER_PEER]; /* RSSI data frm peer */
+} wl_nan_peer_rssi_entry_t;
+
+#define WL_NAN_PEER_RSSI      0x1
+#define WL_NAN_PEER_RSSI_LIST 0x2
+
+typedef struct wl_nan_nbr_rssi_data {
+	uint8 flags;   /* this is a list or single rssi data */
+	uint8 peer_cnt; /* number of peers */
+	uint16 pad; /* padding */
+	wl_nan_peer_rssi_entry_t peers[1]; /* peers data list */
+} wl_nan_peer_rssi_data_t;
+
+/* WL_NAN_CMD_DBG_DUMP, GET Resp */
+typedef struct wl_nan_dbg_dump_rsp {
+	wl_nan_dbg_dump_type_t dump_type; /* dump data type */
+	uint8 pad[3];
+	union {
+		wl_nan_peer_rssi_data_t peer_rssi;
+		wl_nan_stats_t		nan_stats;
+	} u;
+} wl_nan_dbg_dump_rsp_t;
+
+enum nan_termination_status {
+	NAN_TERM_REASON_INVALID = 1,
+	NAN_TERM_REASON_TIMEOUT = 2,
+	NAN_TERM_REASON_USER_REQ = 3,
+	NAN_TERM_REASON_FAILURE = 4,
+	NAN_TERM_REASON_COUNT_REACHED = 5,
+	NAN_TERM_REASON_DE_SHUTDOWN = 6,
+	NAN_TERM_REASON_DISABLE_IN_PROGRESS = 7
+};
+
+/* nan2 data iovar */
+/* nan2 qos */
+typedef struct wl_nan_dp_qos
+{
+	uint8 tid;
+	uint8 pad;
+	uint16 pkt_size;
+	uint16 mean_rate;
+	uint16 svc_interval;
+} wl_nan_dp_qos_t;
+/* ndp config */
+typedef struct wl_nan_ndp_config
+{
+	uint8 ndp_id;
+	uint8 pub_id;
+	struct ether_addr pub_addr;
+	struct ether_addr data_addr;	/* configure local data addr */
+	struct ether_addr init_data_addr;	/* initiator data addr */
+	uint8 svc_spec_info[WL_NAN_DATA_SVC_SPEC_INFO_LEN];
+	wl_nan_dp_qos_t qos;
+	uint16 avail_len;
+	uint8 pad[3];
+	uint8 data[1];
+} wl_nan_ndp_config_t;
+
+/* nan2 device capabilities */
+typedef struct wl_nan_ndp_oper_cfg {
+	uint8 awake_dw_2g;
+	uint8 awake_dw_5g;
+	uint8 bands_supported;
+	uint8 op_mode;
+} wl_nan_ndp_oper_cfg_t;
+
+typedef uint8 wl_nan_ndp_ndpid_t;
+typedef uint8 wl_nan_ndp_conn_t;
+
+#define WL_NAN_AUTO_DPRESP		1
+#define WL_NAN_AUTO_DPCONF		2
+
+typedef uint8 wl_nan_dp_autoconn_t;
+typedef uint8 wl_nan_dp_schedupd_t;
+
+typedef struct wl_nan_dp_req {
+	uint8 type;		    /* 0- unicast 1 - multicast */
+	uint8 pub_id;		    /* Publisher ID */
+	uint8 security;		    /* 0- open security 1-CSID 2-MKID */
+	uint8 flag;
+	struct ether_addr peer_mac; /* Peer's NMI addr */
+	struct ether_addr mcast_mac; /* Multicast addr */
+	wl_nan_dp_qos_t qos;
+	uint8 svc_spec_info[];
+} wl_nan_dp_req_t;
+
+/* TODO  Need to replace ndp_id with lndp_id */
+/* Return structure to data req IOVAR */
+typedef struct wl_nan_dp_req_ret {
+	struct ether_addr indi;	    /* Initiators data mac addr */
+	uint8 ndp_id;		    /* Initiators ndpid */
+	uint8 pad;
+} wl_nan_dp_req_ret_t;
+
+typedef struct wl_nan_dp_resp {
+	uint8 type;		    /* 0- unicast 1 - multicast */
+	uint8 status;		    /* Accepted or Rejected */
+	uint8 reason_code;
+	/* Local NDP ID for unicast, mc_id for multicast, 0 for implicit NMSG */
+	uint8 ndp_id;
+	wl_nan_dp_qos_t qos;
+	/* Initiator data address for unicast or multicast address for multicast */
+	struct ether_addr mac_addr;
+	uint8 security;		    /* 0- open security 1-CSID 2-MKID */
+	uint8 flag;
+	uint8 svc_spec_info[];	    /* NDP service specific info */
+} wl_nan_dp_resp_t;
+
+/* Return structure to data resp IOVAR */
+typedef struct wl_nan_dp_resp_ret {
+	uint8 nmsgid;		    /* NMSG ID or for multicast else 0 */
+	uint8 pad[3];
+} wl_nan_dp_resp_ret_t;
+
+typedef struct wl_nan_dp_conf {
+	uint8 lndp_id;
+	uint8 status;		    /* Accepted or Rejected */
+	uint8 pad[2];
+} wl_nan_dp_conf_t;
+
+typedef struct wl_nan_dp_end
+{
+	uint8 lndp_id;
+	uint8 status;
+	uint8 pad[2];
+} wl_nan_dp_end_t;
+
+/* list ndp ids */
+typedef struct wl_nan_ndp_id_list {
+	uint16 ndp_count;
+	uint8 lndp_id[];
+} wl_nan_ndp_id_list_t;
+
+/* nan2 status */
+typedef struct ndp_session {
+	uint8 lndp_id;
+	uint8 state;
+	uint8 pub_id;
+	uint8 pad;
+} ndp_session_t;
+
+typedef struct wl_nan_ndp_status {
+	struct ether_addr peer_nmi;
+	struct ether_addr peer_ndi;
+	ndp_session_t session;
+	uint8 pad;
+} wl_nan_ndp_status_t;
+
+/* events */
+#define NAN_DP_SESSION_UNICAST         0
+#define NAN_DP_SESSION_MULTICAST       1
+#define NAN_DP_SECURITY_NONE           0
+#define NAN_DP_SECURITY_CSID           1
+#define NAN_DP_SECURITY_MK             2
+
+/* Following datastructure will be removed once source code is committed */
+typedef struct wl_nan_ev_data_conf {
+	uint8 ndp_id;
+	uint8 status;
+	struct ether_addr peer_data_addr;
+	struct ether_addr local_data_addr;
+	uint8 svc_spec_info[WL_NAN_DATA_SVC_SPEC_INFO_LEN];
+	uint8 pad[2];
+} wl_nan_ev_data_conf_t;
+
+/* Following datastructure will be removed once source code is committed */
+typedef struct wl_nan_ev_data_ind {
+	uint8 ndp_id;
+	uint8 pub_id;
+	struct ether_addr peer_data_addr;
+	struct ether_addr local_data_addr;
+	uint8 svc_spec_info[WL_NAN_DATA_SVC_SPEC_INFO_LEN];
+	uint8 pad[2];
+} wl_nan_ev_data_ind_t;
+
+/* Following datastructure will be removed once source code is committed */
+typedef struct wl_nan_ev_data_conf_new {
+	/* Following three fields are valid only if type is unicast */
+	struct ether_addr initiator_ndi;
+	struct ether_addr responder_ndi;
+	uint8 ndp_id;
+	/* Following two fields are valid only if type is multicast */
+	uint8 mc_id;
+	uint8 nmsg_id;
+	uint8 type;
+	uint8 status;
+	uint8 pad[3];
+	uint8 svc_spec_info[];
+} wl_nan_ev_data_conf_new_t;
+
+/* Following datastructure will be removed once source code is committed */
+typedef struct wl_nan_ev_data_ind_new {
+	uint8 type;
+	uint8 ndp_id;
+	uint8 pub_id;
+	uint8 security;
+	struct ether_addr initiator_ndi;
+	struct ether_addr responder_ndi;
+	uint8 svc_spec_info[];
+} wl_nan_ev_data_ind_new_t;
+
+/* Following datastructure will be removed once source code is committed */
+typedef struct wl_nan_ev_data_end {
+	uint8 ndp_id;
+	uint8 status;
+	uint8 pad[2];
+} wl_nan_ev_data_end_t;
+
+#define WL_NAN_DATA_NMSGID_LEN    8 /* 8 bytes as per nan spec */
+
+typedef struct wl_nan_ev_datapath_cmn {
+	uint8 type;
+	/* ndp_id is valid only if type is unicast */
+	uint8 ndp_id;
+	uint8 pub_id;
+	uint8 security;
+	/* Following two fields are valid only if type is unicast */
+	struct ether_addr initiator_ndi;
+	struct ether_addr responder_ndi;
+	/* Following two fields are valid only if type is multicast */
+	uint8 nmsg_id[WL_NAN_DATA_NMSGID_LEN];
+	uint8 mc_id;
+	uint8 status;
+	uint8 pad[2];
+	uint8 opt_tlvs[];
+} wl_nan_ev_datapath_cmn_t;
+
+typedef struct wl_nan_ev_datapath_end {
+	uint8 ndp_id;
+	uint8 status;
+	uint8 pad[2];
+} wl_nan_ev_datapath_end_t;
+
+/* NAN2.0 Ranging definitions */
+
+/* result indication bit map */
+#define NAN_RANGE_INDICATION_CONT		(1<<0)
+#define NAN_RANGE_INDICATION_INGRESS		(1<<1)
+#define NAN_RANGE_INIDICATION_EGRESS		(1<<2)
+
+/* responder flags */
+#define NAN_RANGE_FLAG_AUTO_ACCEPT	(1 << 0)
+#define NAN_RANGE_FLAG_RESULT_REQUIRED	(1 << 1)
+
+typedef struct wl_nan_range_req {
+	struct ether_addr peer;
+	uint8 publisher_id;
+	uint8 indication; /* bit map for result event */
+	uint32 resolution; /* default millimeters */
+	uint32 ingress; /* ingress limit in mm */
+	uint32 egress; /* egress limit in mm */
+	uint32 interval; /* max interval(in TU) b/w two ranging measurements */
+} wl_nan_range_req_t;
+
+#define NAN_RNG_REQ_IOV_LEN	24
+
+typedef uint8 wl_nan_range_id;
+
+typedef struct wl_nan_range_resp {
+	wl_nan_range_id range_id;
+	uint8 flags; /* auto response, range result required */
+	uint8 status; /* accept, reject */
+	uint8 indication; /* bit map for result event */
+	uint32 resolution; /* default millimeters */
+	uint32 ingress; /* ingress limit in mm */
+	uint32 egress; /* egress limit in mm */
+	uint32 interval; /* max interval(in TU) b/w two ranging measurements */
+} wl_nan_range_resp_t;
+
+#define NAN_RNG_RESP_IOV_LEN	20
+
+#define NAN_RNG_MAX_IOV_LEN	255
+
+typedef struct wl_nan_ev_rng_req_ind {
+	struct ether_addr peer_m_addr;
+	uint8 rng_id;
+	/* ftm parameters */
+	uint8 max_burst_dur;
+	uint8 min_ftm_delta;
+	uint8 max_num_ftm;
+	uint8 ftm_format_bw;
+	/* location info availability bit map */
+	uint8 lc_info_avail;
+	/* Last movement indication */
+	uint16 last_movement;
+	uint8 pad[2];
+} wl_nan_ev_rng_req_ind_t;
+
+#define NAN_RNG_REQ_IND_SIZE 14
+
+typedef struct wl_nan_ev_rng_rpt_ind {
+	uint32 dist_mm; /* in millimeter */
+	struct ether_addr peer_m_addr;
+	uint8 indication; /* indication definitions mentioned above */
+	uint8 pad;
+} wl_nan_ev_rng_rpt_ind_t;
+
+#define NAN_RNG_RPT_IND_SIZE 11
+
+typedef struct wl_nan_ev_rng_term_ind {
+	struct ether_addr peer_m_addr;
+	uint8 reason_code;
+	uint8 pad;
+} wl_nan_ev_rng_term_ind_t;
+
+#define NAN_RNG_TERM_IND_SIZE 7
+
+/* ********************* end of NAN section ******************************** */
+#endif /* WL_NAN */
+
+#define P2P_NAN_IOC_BUFSZ  512 /* some sufficient ioc buff size */
+#define WL_P2P_NAN_IOCTL_VERSION    0x1
+
+/* container for p2p nan iovtls & events */
+typedef struct wl_p2p_nan_ioc {
+	uint16  version;    /* interface command or event version */
+	uint16  id;     /* p2p nan ioctl cmd  ID  */
+	uint16  len;        /* total length of data[]  */
+	uint16  pad;        /* padding */
+	uint8   data [1];   /* var len payload of bcm_xtlv_t type */
+} wl_p2p_nan_ioc_t;
+
+/* p2p nan cmd IDs */
+enum wl_p2p_nan_cmds {
+	/* p2p nan cfg ioctls */
+	WL_P2P_NAN_CMD_ENABLE = 1,
+	WL_P2P_NAN_CMD_CONFIG = 2,
+	WL_P2P_NAN_CMD_DEL_CONFIG = 3,
+	WL_P2P_NAN_CMD_GET_INSTS = 4
+};
+
+#define WL_P2P_NAN_CONFIG_VERSION       1
+
+#define WL_P2P_NAN_DEVICE_P2P  0x0
+#define WL_P2P_NAN_DEVICE_GO   0x1
+#define WL_P2P_NAN_DEVICE_GC   0x2
+#define WL_P2P_NAN_DEVICE_INVAL   0xFF
+
+/* NAN P2P operation */
+typedef struct p2p_nan_config {
+	uint16 version;            /* wl_p2p_nan_config_t structure version */
+	uint16 len;                /* total length including version and variable IE */
+	uint32 flags;              /* 0x1 to NEW, 0x2 to ADD, 0x4 to DEL */
+	uint8  inst_id;            /* publisher/subscriber id */
+	uint8  inst_type;          /* publisher/subscriber */
+	uint8  dev_role;           /* P2P device role: 'P2P','GO' or 'GC' */
+	uint8  pad1;               /* padding */
+	uint8  resolution;         /* Availability bitmap resolution */
+	uint8  repeat;             /* Whether Availabilty repeat across DW */
+	uint16 ie_len;             /* variable ie len */
+	struct ether_addr dev_mac; /* P2P device addres */
+	uint16 pad2;               /* Padding */
+	uint32 avail_bmap;         /* availability interval bitmap */
+	uint32 chanspec;           /* Chanspec */
+	uint8  ie[1];              /* hex ie data */
+} wl_p2p_nan_config_t;
+
+#define WL_P2P_NAN_SERVICE_LIST_VERSION 1
+typedef enum wl_nan_service_type {
+	WL_NAN_SVC_INST_PUBLISHER = 1,
+	WL_NAN_SVC_INST_SUBSCRIBER = 2
+} wl_nan_service_type_t;
+
+#define WL_P2P_NAN_CONFIG_NEW   0x1
+#define WL_P2P_NAN_CONFIG_ADD   0x2
+#define WL_P2P_NAN_CONFIG_DEL   0x4
+
+typedef struct wl_nan_svc_inst {
+	uint8  inst_id;      /* publisher/subscriber id */
+	uint8  inst_type;    /* publisher/subscriber */
+} wl_nan_svc_inst_t;
+
+typedef struct wl_nan_svc_inst_list {
+	uint16 version;           /* this structure version */
+	uint16 len;               /* total length including version and variable svc list */
+	uint16 count;             /* service instance count */
+	uint16 pad;               /* padding */
+	wl_nan_svc_inst_t svc[1]; /* service instance list */
+} wl_nan_svc_inst_list_t;
+
+#define NAN_POST_DISC_P2P_DATA_VER  1
+/* This structure will be used send peer p2p data with
+ * NAN discovery result
+ */
+typedef struct nan_post_disc_p2p_data {
+	uint8 ver;                 /* this structure version */
+	uint8 dev_role;            /* P2P Device role */
+	uint8 resolution;          /* Availability bitmap resolution */
+	uint8 repeat;              /* Whether Availabilty repeat across DW */
+	struct ether_addr dev_mac; /* P2P device addres */
+	uint16 pad1;               /* Padding */
+	uint32 chanspec;           /* Chanspec */
+	uint32 avl_bmp;				/* availability interval bitmap */
+} nan_post_disc_p2p_data_t;
+
+/* timeslot etc for NAN */
+enum {
+	WL_TMU_TU            = 0,
+	WL_TMU_SEC           = 1,
+	WL_TMU_MILLI_SEC     = 2,
+	WL_TMU_MICRO_SEC     = 3,
+	WL_TMU_NANO_SEC      = 4,
+	WL_TMU_PICO_SEC      = 5
+};
+typedef int16 wl_tmu_t;
+
+typedef struct {
+	uint32   intvl;               /* time interval */
+	wl_tmu_t tmu;                 /* time unit */
+	uint8    pad[2];              /* padding */
+} wl_time_interval_t;
+
+/* availabiloty slot flags */
+enum {
+	WL_AVAIL_SLOT_NONE		= 0x0000,
+	WL_AVAIL_SLOT_COM		= 0x0001,		/* committed */
+	WL_AVAIL_SLOT_POT		= 0x0002,		/* potential */
+	WL_AVAIL_SLOT_PROP		= 0x0004,	/* proposed -  note: not configurable */
+	WL_AVAIL_SLOT_PAGED		= 0x0008	/* P-NDL */
+	/* 0x0030 - resrved for NDC index */
+	/* 0x00c0 - resrved for usage preference */
+};
+typedef int16 wl_avail_slot_flags_t;
+
+#define WL_AVAIL_SLOT_NDC_MASK 0x0030 /* up to 4 NDCs */
+#define WL_AVAIL_SLOT_NDC_SHIFT 4
+#define WL_AVAIL_SLOT_NDC(_flags)  ((_flags) & WL_AVAIL_SLOT_NDC_MASK) \
+	 >> WL_AVAIL_SLOT_NDC_SHIFT
+#define WL_AVAIL_SLOT_SET_NDC(_flags, _ndc_idx) (((_flags) & ~WL_AVAIL_SLOT_NDC_MASK) |\
+	((_ndc_idx) << WL_AVAIL_SLOT_NDC_SHIFT))
+
+#define WL_AVAIL_SLOT_UPREF_MASK 0x00c0 /* up to 4 usage preferences */
+#define WL_AVAIL_SLOT_UPREF_SHIFT 6
+#define WL_AVAIL_SLOT_UPREF(_flags)  ((_flags) & WL_AVAIL_SLOT_UPREF_MASK) \
+	 >> WL_AVAIL_SLOT_UPREF_SHIFT
+#define WL_AVAIL_SLOT_SET_UPREF(_flags, _pref) (((_flags) & ~WL_AVAIL_SLOT_UPREF_MASK) |\
+	((_pref) << WL_AVAIL_SLOT_UPREF_SHIFT))
+
+typedef struct wl_avail_slot {
+	wl_avail_slot_flags_t flags;
+	wl_time_interval_t    start;        /* from time ref */
+	wl_time_interval_t    duration;     /* from start */
+	uint32                chanspec;     /* channel spec */
+} wl_avail_slot_t;
+
+/* time reference */
+enum {
+	WL_TIME_REF_NONE        = 0,
+	WL_TIME_REF_DEV_TSF     = 1,
+	WL_TIME_REF_NAN_DW      = 2,
+	WL_TIME_REF_TBTT        = 3,
+	WL_TIME_REF_NAN_DW0     = 4
+};
+typedef int16 wl_time_ref_t;
+
+enum {
+	WL_AVAIL_NONE		= 0x0000,
+	WL_AVAIL_LOCAL		= 0x0001,
+	WL_AVAIL_PEER		= 0x0002,
+	WL_AVAIL_NDC		= 0x0003,
+	WL_AVAIL_IMMUTABLE	= 0x0004,
+	WL_AVAIL_RESPONSE	= 0x0005,
+	WL_AVAIL_COUNTER	= 0x0006,
+	WL_AVAIL_RANGING	= 0x0007,
+	WL_AVAIL_TYPE_MAX	= WL_AVAIL_RANGING /* New ones before and update */
+};
+typedef int16 wl_avail_flags_t;
+
+/* note: slots_off is offset to slots from beginning. It is
+ * initialized with sizeof(wl_avail_t), but processing should allow
+ * and ignore any extensions beyond (its) wl_avail_t size.
+ * slot_size is initialized with sizeof(wl_avail_slot_t), but processing
+ * should use the slot size from wl_avail_t so extensions to wl_avail_slot_t
+ * should be possible without changing wl_avail_t processing
+ */
+typedef struct wl_avail {
+	uint16					version;
+	uint16 					length;
+	wl_avail_flags_t 		flags;
+	wl_time_ref_t			time_ref;
+	wl_time_interval_t		repeat;
+	uint16					slots_off;
+	uint8					slot_size;
+	uint8					num_slots;
+
+	/* add additional fields above this line */
+
+	wl_avail_slot_t slots[0]; /* nominal: at slots_off from start of struct */
+} wl_avail_t;
+
+/* get ptr to start of slot index in wl_avail */
+#define WL_AVAIL_SLOT(_avail, _slot_idx) (wl_avail_slot_t *) (\
+	(uint8 *)(_avail) + slots_off + ((_avail)->slot_size * (_slot_idx)))
+
+/* get ptr to first slot */
+#define WL_AVAIL_SLOTS(_avail) WL_AVAIL_SLOT(_avail, 0)
+
+/* determine allocation size for a given number slots */
+#define WL_AVAIL_ALLOC_SIZE(_num_slots) (sizeof(wl_avail_t) + \
+	sizeof(wl_avail_slot_t) * (_num_slots))
+
+/* availability entry flags */
+enum {
+	WL_AVAIL_ENTRY_NONE		= 0x0000,
+	WL_AVAIL_ENTRY_COM		= 0x0001,		/* committed */
+	WL_AVAIL_ENTRY_POT		= 0x0002,		/* potential */
+	WL_AVAIL_ENTRY_COND		= 0x0004,	/* conditional */
+	WL_AVAIL_ENTRY_PAGED		= 0x0008,	/* P-NDL */
+	WL_AVAIL_ENTRY_USAGE		= 0x0030,	/* usage preference */
+	WL_AVAIL_ENTRY_BIT_DUR		= 0x00c0,	/* bit duration */
+	WL_AVAIL_ENTRY_BAND_PRESENT	= 0x0100,	/* band present */
+	WL_AVAIL_ENTRY_CHAN_PRESENT	= 0x0200,	/* channel information present */
+	WL_AVAIL_ENTRY_CHAN_ENTRY_PRESENT	= 0x0400,	/* channel entry (opclass+bitmap) */
+};
+
+/* bit duration */
+enum {
+	WL_AVAIL_BIT_DUR_16	= 0,	/* 16TU */
+	WL_AVAIL_BIT_DUR_32	= 1,	/* 32TU */
+	WL_AVAIL_BIT_DUR_64	= 2,	/* 64TU */
+	WL_AVAIL_BIT_DUR_128	= 3,	/* 128TU */
+};
+
+/* period */
+enum {
+	WL_AVAIL_PERIOD_0	= 0,	/* 0TU */
+	WL_AVAIL_PERIOD_128	= 1,	/* 128TU */
+	WL_AVAIL_PERIOD_256	= 2,	/* 256TU */
+	WL_AVAIL_PERIOD_512	= 3,	/* 512TU */
+	WL_AVAIL_PERIOD_1024	= 4,	/* 1024TU */
+	WL_AVAIL_PERIOD_2048	= 5,	/* 2048TU */
+	WL_AVAIL_PERIOD_4096	= 6,	/* 4096TU */
+	WL_AVAIL_PERIOD_8192	= 7,	/* 8192TU */
+};
+
+/* band */
+enum {
+	WL_AVAIL_BAND_NONE	= 0,	/* reserved */
+	WL_AVAIL_BAND_SUB1G	= 1,	/* sub-1 GHz */
+	WL_AVAIL_BAND_2G	= 2,	/* 2.4 GHz */
+	WL_AVAIL_BAND_3G	= 3,	/* reserved (for 3.6 GHz) */
+	WL_AVAIL_BAND_5G	= 4,	/* 4.9 and 5 GHz */
+	WL_AVAIL_BAND_60G	= 5,	/* reserved (for 60 GHz) */
+};
+
+#define WL_AVAIL_ENTRY_TYPE_MASK 0x0F
+#define WL_AVAIL_ENTRY_USAGE_MASK 0x0030 /* up to 4 usage preferences */
+#define WL_AVAIL_ENTRY_USAGE_SHIFT 4
+#define WL_AVAIL_ENTRY_USAGE_VAL(_flags)  ((_flags) & WL_AVAIL_ENTRY_USAGE_MASK) \
+	>> WL_AVAIL_ENTRY_USAGE_SHIFT
+
+#define WL_AVAIL_ENTRY_BIT_DUR_MASK 0x00c0 /* 0:16TU, 1:32TU, 2:64TU, 3:128TU */
+#define WL_AVAIL_ENTRY_BIT_DUR_SHIFT 6
+#define WL_AVAIL_ENTRY_BIT_DUR_VAL(_flags)  ((_flags) & WL_AVAIL_ENTRY_BIT_DUR_MASK) \
+	>> WL_AVAIL_ENTRY_BIT_DUR_SHIFT
+
+#define WL_AVAIL_ENTRY_BAND_MASK 0x0100 /* 0=band not present, 1=present */
+#define WL_AVAIL_ENTRY_BAND_SHIFT 8
+
+#define WL_AVAIL_ENTRY_CHAN_MASK 0x0200 /* 0=channel info not present, 1=present */
+#define WL_AVAIL_ENTRY_CHAN_SHIFT 9
+
+#define WL_AVAIL_ENTRY_CHAN_ENTRY_MASK 0x0400 /* 0=chanspec, 1=hex channel entry */
+#define WL_AVAIL_ENTRY_CHAN_ENTRY_SHIFT 10
+
+#define WL_AVAIL_ENTRY_OPCLASS_MASK 0xFF
+#define WL_AVAIL_ENTRY_CHAN_BITMAP_MASK 0xFF00
+#define WL_AVAIL_ENTRY_CHAN_BITMAP_SHIFT 8
+#define WL_AVAIL_ENTRY_CHAN_BITMAP_VAL(_info) ((_info) & WL_AVAIL_ENTRY_CHAN_BITMAP_MASK) \
+	>> WL_AVAIL_ENTRY_CHAN_BITMAP_SHIFT
+
+#define WL_AVAIL_TYPE_MASK 0x0F
+
+typedef struct wl_avail_entry {
+	uint16		length;		/* total length */
+	uint16		start_offset;	/* in TUs, multiply by 16 for total offset */
+	union {
+		uint32 channel_info;	/* either chanspec or hex channel entry (opclass +
+					 * bitmap per NAN spec), as indicated by setting
+					 * WL_AVAIL_ENTRY_HEX_CHAN_ENTRY flag
+					 */
+		uint32 band;		/* defined by WL_BAND enum, 2=2.4GHz, 4=5GHz */
+	} u;				/* band or channel value, 0=all band/channels */
+	uint8		period;		/* in TUs, defined by WL_AVAIL_PERIOD enum
+					 * 1:128, 2:256, 3:512, 4:1024, 5:2048, 6:4096,
+					 * 7:8192
+					 */
+	uint8		bitmap_len;
+	uint16		flags;		/* defined by avail entry flags enum:
+					 * type, usage pref, bit duration, band, channel
+					 */
+	uint8		bitmap[];	/* time bitmap */
+} wl_avail_entry_t;
+
+/* Temporarily naming this to wl_avail_new until usage references
+ * to existing wl_avail are resolved.
+ */
+typedef struct wl_avail_new {
+	uint16		version;
+	uint16		length;		/* total length */
+	uint16		flags;		/* defined by WL_AVAIL enum
+					 * 1=local, 2=peer, 3=ndc, 4=immutable,
+					 * 5=response, 6=counter
+					 */
+	uint16		time_ref;	/* defined by WL_TIME_REF enum
+					 * 1=TSF, 2=NANDW, 3=TBTT, 4=NANDW0
+					 */
+	union {
+		uint8	id;		/* local avail id */
+		struct ether_addr addr;	/* peer mac address or ndc id */
+	} u;
+	uint8		num_entries;
+	uint8		entry_offset;
+	/* add additional fields above this line */
+	uint8	entry[];
+} wl_avail_new_t;
+
+#define WL_AVAIL_MIN_LEN(n) n ? OFFSETOF(wl_avail_new_t, entry) + \
+				(n * OFFSETOF(wl_avail_entry_t, bitmap)) : 0
+
+/* unaligned schedule - to be defined later */
+typedef struct wl_avail_ua {
+	uint16		version;
+	uint16		length;
+	uint8		data[0];
+} wl_avail_ua_t;
+
+/* nan wfa testmode operations */
+enum {
+	WL_NAN_WFA_TM_IGNORE_TERMINATE_NAF		= 0x00000001,
+	WL_NAN_WFA_TM_IGNORE_RX_DATA_OUTSIDE_CRB	= 0x00000002,
+	WL_NAN_WFA_TM_ALLOW_TX_DATA_OUTSIDE_CRB		= 0x00000004,
+	WL_NAN_WFA_TM_ENFORCE_NDL_COUNTER		= 0x00000008,
+	WL_NAN_WFA_TM_FLAG_MASK				= 0x0000000f /* add above & update mask */
+};
+typedef uint32 wl_nan_wfa_testmode_t;
+
+#define RSSI_THRESHOLD_SIZE 16
+#define MAX_IMP_RESP_SIZE 256
+
+typedef struct wl_proxd_rssi_bias {
+	int32		version;			/**< version */
+	int32		threshold[RSSI_THRESHOLD_SIZE];	/**< threshold */
+	int32		peak_offset;			/**< peak offset */
+	int32		bias;				/**< rssi bias */
+	int32		gd_delta;			/**< GD - GD_ADJ */
+	int32		imp_resp[MAX_IMP_RESP_SIZE];	/**< (Hi*Hi)+(Hr*Hr) */
+} wl_proxd_rssi_bias_t;
+
+typedef struct wl_proxd_rssi_bias_avg {
+	int32		avg_threshold[RSSI_THRESHOLD_SIZE];	/**< avg threshold */
+	int32		avg_peak_offset;			/**< avg peak offset */
+	int32		avg_rssi;				/**< avg rssi */
+	int32		avg_bias;				/**< avg bias */
+} wl_proxd_rssi_bias_avg_t;
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_info {
+	uint16		type;  /**< type: 0 channel table, 1 channel smoothing table, 2 and 3 seq */
+	uint16		index;		/**< The current frame index, from 1 to total_frames. */
+	uint16		tof_cmd;	/**< M_TOF_CMD      */
+	uint16		tof_rsp;	/**< M_TOF_RSP      */
+	uint16		tof_avb_rxl;	/**< M_TOF_AVB_RX_L */
+	uint16		tof_avb_rxh;	/**< M_TOF_AVB_RX_H */
+	uint16		tof_avb_txl;	/**< M_TOF_AVB_TX_L */
+	uint16		tof_avb_txh;	/**< M_TOF_AVB_TX_H */
+	uint16		tof_id;		/**< M_TOF_ID */
+	uint8		tof_frame_type;
+	uint8		tof_frame_bw;
+	int8		tof_rssi;
+	int32		tof_cfo;
+	int32		gd_adj_ns;	/**< gound delay */
+	int32		gd_h_adj_ns;	/**< group delay + threshold crossing */
+	int16		nfft;		/**< number of samples stored in H */
+	uint8		num_max_cores;
+
+} BWL_POST_PACKED_STRUCT wl_proxd_collect_info_t;
+#include <packed_section_end.h>
+
+#define K_TOF_COLLECT_H_PAD 1
+#define K_TOF_COLLECT_SC_20MHZ (64)
+/* Maximum possible size of sample capture */
+#define K_TOF_COLLECT_SC_80MHZ (2*K_TOF_COLLECT_SC_20MHZ)
+/* Maximum possible size of channel dump */
+#define K_TOF_COLLECT_CHAN_SIZE (2*K_TOF_COLLECT_SC_80MHZ)
+
+/*
+A few extra samples are required to estimate frequency offset
+Right now 16 samples are being used. Can be changed in future.
+*/
+#define K_TOF_COLLECT_SAMP_SIZE_20MHZ (2*(K_TOF_COLLECT_SC_20MHZ)+16+K_TOF_COLLECT_H_PAD)
+#define K_TOF_COLLECT_RAW_SAMP_SIZE_20MHZ (2*K_TOF_COLLECT_SAMP_SIZE_20MHZ)
+#define K_TOF_COLLECT_H_SIZE_20MHZ (K_TOF_COLLECT_SAMP_SIZE_20MHZ)
+#define K_TOF_COLLECT_HRAW_SIZE_20MHZ (K_TOF_COLLECT_RAW_SAMP_SIZE_20MHZ)
+
+#define K_TOF_COLLECT_SAMP_SIZE_80MHZ (2*(K_TOF_COLLECT_SC_80MHZ)+16+K_TOF_COLLECT_H_PAD)
+#define K_TOF_COLLECT_RAW_SAMP_SIZE_80MHZ (2*K_TOF_COLLECT_SAMP_SIZE_80MHZ)
+#define K_TOF_COLLECT_H_SIZE_80MHZ (K_TOF_COLLECT_SAMP_SIZE_80MHZ)
+#define K_TOF_COLLECT_HRAW_SIZE_80MHZ (K_TOF_COLLECT_RAW_SAMP_SIZE_80MHZ)
+
+#define WL_PROXD_COLLECT_DATA_VERSION_1		1
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_data_v1 {
+	wl_proxd_collect_info_t  info;
+	uint8	ri_rr[FTM_TPK_RI_RR_LEN];
+	/**< raw data read from phy used to adjust timestamps */
+	uint32	H[K_TOF_COLLECT_H_SIZE_20MHZ];
+} BWL_POST_PACKED_STRUCT wl_proxd_collect_data_t_v1;
+#include <packed_section_end.h>
+
+#define WL_PROXD_COLLECT_DATA_VERSION_2		2
+typedef struct wl_proxd_collect_data_v2 {
+	uint16			version;
+	uint16			len;
+	wl_proxd_collect_info_t	info;
+	uint8			ri_rr[FTM_TPK_RI_RR_LEN];
+	uint8			pad[3]; /* should be based on FTM_TPK_RI_RR_LEN */
+	/**< raw data read from phy used to adjust timestamps */
+	uint32			H[K_TOF_COLLECT_H_SIZE_20MHZ];
+	uint32			chan[4 * K_TOF_COLLECT_CHAN_SIZE];
+} wl_proxd_collect_data_t_v2;
+#define WL_PROXD_COLLECT_DATA_VERSION_MAX	WL_PROXD_COLLECT_DATA_VERSION_2
+
+typedef struct wl_proxd_debug_data {
+	uint8		count;		/**< number of packets */
+	uint8		stage;		/**< state machone stage */
+	uint8		received;	/**< received or txed */
+	uint8		paket_type;	/**< packet type */
+	uint8		category;	/**< category field */
+	uint8		action;		/**< action field */
+	uint8		token;		/**< token number */
+	uint8		follow_token;	/**< following token number */
+	uint16		index;		/**< index of the packet */
+	uint16		tof_cmd;	/**< M_TOF_CMD */
+	uint16		tof_rsp;	/**< M_TOF_RSP */
+	uint16		tof_avb_rxl;	/**< M_TOF_AVB_RX_L */
+	uint16		tof_avb_rxh;	/**< M_TOF_AVB_RX_H */
+	uint16		tof_avb_txl;	/**< M_TOF_AVB_TX_L */
+	uint16		tof_avb_txh;	/**< M_TOF_AVB_TX_H */
+	uint16		tof_id;		/**< M_TOF_ID */
+	uint16		tof_status0;	/**< M_TOF_STATUS_0 */
+	uint16		tof_status2;	/**< M_TOF_STATUS_2 */
+	uint16		tof_chsm0;	/**< M_TOF_CHNSM_0 */
+	uint16		tof_phyctl0;	/**< M_TOF_PHYCTL0 */
+	uint16		tof_phyctl1;	/**< M_TOF_PHYCTL1 */
+	uint16		tof_phyctl2;	/**< M_TOF_PHYCTL2 */
+	uint16		tof_lsig;	/**< M_TOF_LSIG */
+	uint16		tof_vhta0;	/**< M_TOF_VHTA0 */
+	uint16		tof_vhta1;	/**< M_TOF_VHTA1 */
+	uint16		tof_vhta2;	/**< M_TOF_VHTA2 */
+	uint16		tof_vhtb0;	/**< M_TOF_VHTB0 */
+	uint16		tof_vhtb1;	/**< M_TOF_VHTB1 */
+	uint16		tof_apmductl;	/**< M_TOF_AMPDU_CTL */
+	uint16		tof_apmdudlim;	/**< M_TOF_AMPDU_DLIM */
+	uint16		tof_apmdulen;	/**< M_TOF_AMPDU_LEN */
+} wl_proxd_debug_data_t;
+
+/** version of the wl_wsec_info structure */
+#define WL_WSEC_INFO_VERSION 0x01
+
+/** start enum value for BSS properties */
+#define WL_WSEC_INFO_BSS_BASE 0x0100
+
+/** size of len and type fields of wl_wsec_info_tlv_t struct */
+#define WL_WSEC_INFO_TLV_HDR_LEN OFFSETOF(wl_wsec_info_tlv_t, data)
+
+/** Allowed wl_wsec_info properties; not all of them may be supported. */
+typedef enum {
+	WL_WSEC_INFO_NONE = 0,
+	WL_WSEC_INFO_MAX_KEYS = 1,
+	WL_WSEC_INFO_NUM_KEYS = 2,
+	WL_WSEC_INFO_NUM_HW_KEYS = 3,
+	WL_WSEC_INFO_MAX_KEY_IDX = 4,
+	WL_WSEC_INFO_NUM_REPLAY_CNTRS = 5,
+	WL_WSEC_INFO_SUPPORTED_ALGOS = 6,
+	WL_WSEC_INFO_MAX_KEY_LEN = 7,
+	WL_WSEC_INFO_FLAGS = 8,
+	/* add global/per-wlc properties above */
+	WL_WSEC_INFO_BSS_FLAGS = (WL_WSEC_INFO_BSS_BASE + 1),
+	WL_WSEC_INFO_BSS_WSEC = (WL_WSEC_INFO_BSS_BASE + 2),
+	WL_WSEC_INFO_BSS_TX_KEY_ID = (WL_WSEC_INFO_BSS_BASE + 3),
+	WL_WSEC_INFO_BSS_ALGO = (WL_WSEC_INFO_BSS_BASE + 4),
+	WL_WSEC_INFO_BSS_KEY_LEN = (WL_WSEC_INFO_BSS_BASE + 5),
+	WL_WSEC_INFO_BSS_ALGOS = (WL_WSEC_INFO_BSS_BASE + 6),
+	/* add per-BSS properties above */
+	WL_WSEC_INFO_MAX = 0xffff
+} wl_wsec_info_type_t;
+
+typedef struct {
+	uint32 algos; /* set algos to be enabled/disabled */
+	uint32 mask; /* algos outside mask unaltered */
+} wl_wsec_info_algos_t;
+
+/** tlv used to return wl_wsec_info properties */
+typedef struct {
+	uint16 type;
+	uint16 len;		/**< data length */
+	uint8 data[1];	/**< data follows */
+} wl_wsec_info_tlv_t;
+
+/** input/output data type for wsec_info iovar */
+typedef struct wl_wsec_info {
+	uint8 version; /**< structure version */
+	uint8 pad[2];
+	uint8 num_tlvs;
+	wl_wsec_info_tlv_t tlvs[1]; /**< tlv data follows */
+} wl_wsec_info_t;
+
+/*
+ * randmac definitions
+ */
+#define WL_RANDMAC_MODULE			"randmac"
+#define WL_RANDMAC_API_VERSION		0x0100 /**< version 1.0 */
+#define WL_RANDMAC_API_MIN_VERSION	0x0100 /**< version 1.0 */
+
+/** subcommands that can apply to randmac */
+enum {
+	WL_RANDMAC_SUBCMD_NONE				= 0,
+	WL_RANDMAC_SUBCMD_GET_VERSION			= 1,
+	WL_RANDMAC_SUBCMD_ENABLE			= 2,
+	WL_RANDMAC_SUBCMD_DISABLE			= 3,
+	WL_RANDMAC_SUBCMD_CONFIG			= 4,
+	WL_RANDMAC_SUBCMD_STATS				= 5,
+	WL_RANDMAC_SUBCMD_CLEAR_STATS			= 6,
+
+	WL_RANDMAC_SUBCMD_MAX
+};
+typedef int16 wl_randmac_subcmd_t;
+
+/* Common IOVAR struct */
+typedef struct wl_randmac {
+	uint16 version;
+	uint16 len;			/* total length */
+	wl_randmac_subcmd_t subcmd_id;	/* subcommand id */
+	uint8 data[0];			/* subcommand data */
+} wl_randmac_t;
+
+#define WL_RANDMAC_IOV_HDR_SIZE OFFSETOF(wl_randmac_t, data)
+
+/* randmac version subcommand */
+typedef struct wl_randmac_version {
+	uint16 version;  /* Randmac method version info */
+	uint8 pad[2];    /* Align on 4 byte boundary */
+} wl_randmac_version_t;
+
+/*
+ * Bitmask for methods supporting MAC randomization feature
+ */
+#define WL_RANDMAC_USER_NONE		0x0000
+#define WL_RANDMAC_USER_FTM		0x0001
+#define WL_RANDMAC_USER_NAN		0x0002
+#define WL_RANDMAC_USER_SCAN		0x0004
+#define WL_RANDMAC_USER_ALL		0xFFFF
+typedef uint16 wl_randmac_method_t;
+
+enum {
+	WL_RANDMAC_FLAGS_NONE	= 0x00,
+	WL_RANDMAC_FLAGS_ADDR	= 0x01,
+	WL_RANDMAC_FLAGS_MASK	= 0x02,
+	WL_RANDMAC_FLAGS_METHOD	= 0x04,
+	WL_RANDMAC_FLAGS_ALL	= 0xFF
+};
+typedef uint8 wl_randmac_flags_t;
+
+/* randmac statistics subcommand */
+typedef struct wl_randmac_stats {
+	uint32 set_ok;		/* Set random addr success count */
+	uint32 set_fail;	/* Set random addr failed count */
+	uint32 set_reqs;	/* Set random addr count */
+	uint32 reset_reqs;	/* Restore random addr count */
+	uint32 restore_ok;	/* Restore random addr succes count */
+	uint32 restore_fail;	/* Restore random addr failed count */
+	uint32 events_sent;	/* randmac module events count */
+	uint32 events_rcvd;	/* randmac events received count */
+} wl_randmac_stats_t;
+
+/* randmac config subcommand */
+typedef struct wl_randmac_config {
+	struct ether_addr addr;			/* Randomized MAC address */
+	struct ether_addr addr_mask;		/* bitmask for randomization */
+	wl_randmac_method_t method;		/* Enabled methods */
+	wl_randmac_flags_t flags;		/* What config info changed */
+} wl_randmac_config_t;
+
+enum {
+	WL_RANDMAC_EVENT_NONE			= 0,	/**< not an event, reserved */
+	WL_RANDMAC_EVENT_BSSCFG_ADDR_SET	= 1,	/* bsscfg addr randomized */
+	WL_RANDMAC_EVENT_BSSCFG_ADDR_RESTORE	= 2,	/* bsscfg addr restored */
+	WL_RANDMAC_EVENT_ENABLED		= 3,	/* randmac module enabled */
+	WL_RANDMAC_EVENT_DISABLE		= 4,	/* randmac module disabled */
+	WL_RANDMAC_EVENT_BSSCFG_STATUS	= 5,	/* bsscfg enable/disable */
+
+	WL_RANDMAC_EVENT_MAX
+};
+typedef int16 wl_randmac_event_type_t;
+typedef int32 wl_randmac_status_t;
+typedef uint32 wl_randmac_event_mask_t;
+
+#define WL_RANDMAC_EVENT_MASK_ALL 0xfffffffe
+#define WL_RANDMAC_EVENT_MASK_EVENT(_event_type) (1 << (_event_type))
+#define WL_RANDMAC_EVENT_ENABLED(_mask, _event_type) (\
+	((_mask) & WL_RANDMAC_EVENT_MASK_EVENT(_event_type)) != 0)
+
+/** tlv IDs - data length 4 bytes unless overridden by type, alignment 32 bits */
+enum {
+	WL_RANDMAC_TLV_NONE		= 0,
+	WL_RANDMAC_TLV_METHOD		= 1,
+	WL_RANDMAC_TLV_ADDR		= 2,
+	WL_RANDMAC_TLV_MASK		= 3
+};
+typedef uint16 wl_randmac_tlv_id_t;
+
+typedef struct wl_randmac_tlv {
+	wl_randmac_tlv_id_t id;
+	uint16 len;		/* Length of variable */
+	uint8  data[1];
+} wl_randmac_tlv_t;
+
+/** randmac event */
+typedef struct wl_randmac_event {
+	uint16					version;
+	uint16					len;	/* Length of all variables */
+	wl_randmac_event_type_t			type;
+	wl_randmac_method_t			method;
+	uint8					pad[2];
+	wl_randmac_tlv_t			tlvs[1];	/**< variable */
+} wl_randmac_event_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/*
+ * scan MAC definitions
+ */
+
+/** common iovar struct */
+typedef struct wl_scanmac {
+	uint16 subcmd_id;	/**< subcommand id */
+	uint16 len;		/**< total length of data[] */
+	uint8 data[1];		/**< subcommand data */
+} wl_scanmac_t;
+
+/* subcommand ids */
+#define WL_SCANMAC_SUBCMD_ENABLE   0
+#define WL_SCANMAC_SUBCMD_BSSCFG   1   /**< only GET supported */
+#define WL_SCANMAC_SUBCMD_CONFIG   2
+
+/** scanmac enable data struct */
+typedef struct wl_scanmac_enable {
+	uint8 enable;	/**< 1 - enable, 0 - disable */
+	uint8 pad[3];	/**< 4-byte struct alignment */
+} wl_scanmac_enable_t;
+
+/** scanmac bsscfg data struct */
+typedef struct wl_scanmac_bsscfg {
+	uint32 bsscfg;	/**< bsscfg index */
+} wl_scanmac_bsscfg_t;
+
+/** scanmac config data struct */
+typedef struct wl_scanmac_config {
+	struct ether_addr mac;	/**< 6 bytes of MAC address or MAC prefix (i.e. OUI) */
+	struct ether_addr random_mask;	/**< randomized bits on each scan */
+	uint16 scan_bitmap;	/**< scans to use this MAC address */
+	uint8 pad[2];	/**< 4-byte struct alignment */
+} wl_scanmac_config_t;
+
+/* scan bitmap */
+#define WL_SCANMAC_SCAN_UNASSOC		(0x01 << 0)	/**< unassociated scans */
+#define WL_SCANMAC_SCAN_ASSOC_ROAM	(0x01 << 1)	/**< associated roam scans */
+#define WL_SCANMAC_SCAN_ASSOC_PNO	(0x01 << 2)	/**< associated PNO scans */
+#define WL_SCANMAC_SCAN_ASSOC_HOST	(0x01 << 3)	/**< associated host scans */
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/*
+ * bonjour dongle offload definitions
+ */
+
+/* common iovar struct */
+typedef struct wl_bdo {
+	uint16 subcmd_id;	/* subcommand id */
+	uint16 len;		/* total length of data[] */
+	uint8 data[1];		/* subcommand data */
+} wl_bdo_t;
+
+/* subcommand ids */
+#define WL_BDO_SUBCMD_DOWNLOAD		0	/* Download flattened database  */
+#define WL_BDO_SUBCMD_ENABLE		1	/* Start bonjour after download */
+#define WL_BDO_SUBCMD_MAX_DOWNLOAD	2	/* Get the max download size    */
+
+/* maximum fragment size */
+#define BDO_MAX_FRAGMENT_SIZE	1024
+
+/* download flattened database
+ *
+ * BDO must be disabled before database download else fail.
+ *
+ * If database size is within BDO_MAX_FRAGMENT_SIZE then only a single fragment
+ * is required (i.e. frag_num = 0, total_size = frag_size).
+ * If database size exceeds BDO_MAX_FRAGMENT_SIZE then multiple fragments are required.
+ */
+typedef struct wl_bdo_download {
+	uint16 total_size;	/* total database size */
+	uint16 frag_num;	/* fragment number, 0 for first fragment, N-1 for last fragment */
+	uint16 frag_size;	/* size of fragment (max BDO_MAX_FRAGMENT_SIZE) */
+	uint8 pad[2];		/* 4-byte struct alignment */
+	uint8 fragment[BDO_MAX_FRAGMENT_SIZE];  /* fragment data */
+} wl_bdo_download_t;
+
+/* enable
+ *
+ * Enable requires a downloaded database else fail.
+ */
+typedef struct wl_bdo_enable {
+	uint8 enable;	/* 1 - enable, 0 - disable */
+	uint8 pad[3];	/* 4-byte struct alignment */
+} wl_bdo_enable_t;
+
+/*
+ * Get the max download size for Bonjour Offload.
+ */
+typedef struct wl_bdo_max_download {
+	uint16 size;	/* Max download size in bytes */
+	uint8 pad[2];	/* 4-byte struct alignment    */
+} wl_bdo_max_download_t;
+
+/*
+ * TCP keepalive offload definitions
+ */
+
+/* common iovar struct */
+typedef struct wl_tko {
+	uint16 subcmd_id;	/* subcommand id */
+	uint16 len;		/* total length of data[] */
+	uint8 data[1];		/* subcommand data */
+} wl_tko_t;
+
+/* subcommand ids */
+#define WL_TKO_SUBCMD_MAX_TCP		0	/* max TCP connections supported */
+#define WL_TKO_SUBCMD_PARAM		1	/* configure offload common parameters  */
+#define WL_TKO_SUBCMD_CONNECT		2	/* TCP connection info */
+#define WL_TKO_SUBCMD_ENABLE		3	/* enable/disable */
+#define WL_TKO_SUBCMD_STATUS		4	/* TCP connection status */
+
+/* WL_TKO_SUBCMD_MAX_CONNECT subcommand data */
+typedef struct wl_tko_max_tcp {
+	uint8 max;	/* max TCP connections supported */
+	uint8 pad[3];	/* 4-byte struct alignment */
+} wl_tko_max_tcp_t;
+
+/* WL_TKO_SUBCMD_PARAM subcommand data */
+typedef struct wl_tko_param {
+	uint16 interval;	/* keepalive tx interval (secs) */
+	uint16 retry_interval;	/* keepalive retry interval (secs) */
+	uint16 retry_count;	/* retry_count */
+	uint8 pad[2];		/* 4-byte struct alignment */
+} wl_tko_param_t;
+
+/* WL_TKO_SUBCMD_CONNECT subcommand data
+ * invoke with unique 'index' for each TCP connection
+ */
+typedef struct wl_tko_connect {
+	uint8 index;		/* TCP connection index, 0 to max-1 */
+	uint8 ip_addr_type;	/* 0 - IPv4, 1 - IPv6 */
+	uint16 local_port;	/* local port */
+	uint16 remote_port;	/* remote port */
+	uint32 local_seq;	/* local sequence number */
+	uint32 remote_seq;	/* remote sequence number */
+	uint16 request_len;	/* TCP keepalive request packet length */
+	uint16 response_len;	/* TCP keepalive response packet length */
+	uint8 data[1];		/* variable length field containing local/remote IPv4/IPv6,
+				 * TCP keepalive request packet, TCP keepalive response packet
+				 *    For IPv4, length is 4 * 2 + request_length + response_length
+				 *       offset 0 - local IPv4
+				 *       offset 4 - remote IPv4
+				 *       offset 8 - TCP keepalive request packet
+				 *       offset 8+request_length - TCP keepalive response packet
+				 *    For IPv6, length is 16 * 2 + request_length + response_length
+				 *       offset 0 - local IPv6
+				 *       offset 16 - remote IPv6
+				 *       offset 32 - TCP keepalive request packet
+				 *       offset 32+request_length - TCP keepalive response packet
+				 */
+} wl_tko_connect_t;
+
+/* WL_TKO_SUBCMD_CONNECT subcommand data to GET configured info for specific index */
+typedef struct wl_tko_get_connect {
+	uint8 index;		/* TCP connection index, 0 to max-1 */
+	uint8 pad[3];		/* 4-byte struct alignment */
+} wl_tko_get_connect_t;
+
+typedef struct wl_tko_enable {
+	uint8 enable;	/* 1 - enable, 0 - disable */
+	uint8 pad[3];	/* 4-byte struct alignment */
+} wl_tko_enable_t;
+
+/* WL_TKO_SUBCMD_STATUS subcommand data */
+/* must be invoked before tko is disabled else status is unavailable */
+typedef struct wl_tko_status {
+	uint8 count;		/* number of status entries (i.e. equals
+				 * max TCP connections supported)
+	                         */
+	uint8 status[1];	/* variable length field contain status for
+				 * each TCP connection index
+				 */
+} wl_tko_status_t;
+
+typedef enum {
+	TKO_STATUS_NORMAL			= 0,	/* TCP connection normal, no error */
+	TKO_STATUS_NO_RESPONSE			= 1,	/* no response to TCP keepalive */
+	TKO_STATUS_NO_TCP_ACK_FLAG		= 2,	/* TCP ACK flag not set */
+	TKO_STATUS_UNEXPECT_TCP_FLAG		= 3,	/* unexpect TCP flags set other than ACK */
+	TKO_STATUS_SEQ_NUM_INVALID		= 4,	/* ACK != sequence number */
+	TKO_STATUS_REMOTE_SEQ_NUM_INVALID	= 5,	/* SEQ > remote sequence number */
+	TKO_STATUS_TCP_DATA			= 6,	/* TCP data available */
+	TKO_STATUS_UNAVAILABLE			= 255,	/* not used/configured */
+} tko_status_t;
+
+enum rssi_reason {
+	RSSI_REASON_UNKNOW = 0,
+	RSSI_REASON_LOWRSSI = 1,
+	RSSI_REASON_NSYC = 2,
+	RSSI_REASON_TIMEOUT = 3
+};
+
+enum tof_reason {
+	TOF_REASON_OK = 0,
+	TOF_REASON_REQEND = 1,
+	TOF_REASON_TIMEOUT = 2,
+	TOF_REASON_NOACK = 3,
+	TOF_REASON_INVALIDAVB = 4,
+	TOF_REASON_INITIAL = 5,
+	TOF_REASON_ABORT = 6
+};
+
+enum rssi_state {
+	RSSI_STATE_POLL = 0,
+	RSSI_STATE_TPAIRING = 1,
+	RSSI_STATE_IPAIRING = 2,
+	RSSI_STATE_THANDSHAKE = 3,
+	RSSI_STATE_IHANDSHAKE = 4,
+	RSSI_STATE_CONFIRMED = 5,
+	RSSI_STATE_PIPELINE = 6,
+	RSSI_STATE_NEGMODE = 7,
+	RSSI_STATE_MONITOR = 8,
+	RSSI_STATE_LAST = 9
+};
+
+enum tof_state {
+	TOF_STATE_IDLE	 = 0,
+	TOF_STATE_IWAITM = 1,
+	TOF_STATE_TWAITM = 2,
+	TOF_STATE_ILEGACY = 3,
+	TOF_STATE_IWAITCL = 4,
+	TOF_STATE_TWAITCL = 5,
+	TOF_STATE_ICONFIRM = 6,
+	TOF_STATE_IREPORT = 7
+};
+
+enum tof_mode_type {
+	TOF_LEGACY_UNKNOWN	= 0,
+	TOF_LEGACY_AP		= 1,
+	TOF_NONLEGACY_AP	= 2
+};
+
+enum tof_way_type {
+	TOF_TYPE_ONE_WAY = 0,
+	TOF_TYPE_TWO_WAY = 1,
+	TOF_TYPE_REPORT = 2
+};
+
+enum tof_rate_type {
+	TOF_FRAME_RATE_VHT = 0,
+	TOF_FRAME_RATE_LEGACY = 1
+};
+
+#define TOF_ADJ_TYPE_NUM	4	/**< number of assisted timestamp adjustment */
+enum tof_adj_mode {
+	TOF_ADJ_SOFTWARE = 0,
+	TOF_ADJ_HARDWARE = 1,
+	TOF_ADJ_SEQ = 2,
+	TOF_ADJ_NONE = 3
+};
+
+#define FRAME_TYPE_NUM		4	/**< number of frame type */
+enum frame_type {
+	FRAME_TYPE_CCK	= 0,
+	FRAME_TYPE_OFDM	= 1,
+	FRAME_TYPE_11N	= 2,
+	FRAME_TYPE_11AC	= 3
+};
+
+typedef struct wl_proxd_status_iovar {
+	uint16			method;				/**< method */
+	uint8			mode;				/**< mode */
+	uint8			peermode;			/**< peer mode */
+	uint8			state;				/**< state */
+	uint8			reason;				/**< reason code */
+	uint32			distance;			/**< distance */
+	uint32			txcnt;				/**< tx pkt counter */
+	uint32			rxcnt;				/**< rx pkt counter */
+	struct ether_addr	peer;				/**< peer mac address */
+	int8			avg_rssi;			/**< average rssi */
+	int8			hi_rssi;			/**< highest rssi */
+	int8			low_rssi;			/**< lowest rssi */
+	uint32			dbgstatus;			/**< debug status */
+	uint16			frame_type_cnt[FRAME_TYPE_NUM];	/**< frame types */
+	uint8			adj_type_cnt[TOF_ADJ_TYPE_NUM];	/**< adj types HW/SW */
+} wl_proxd_status_iovar_t;
+
+#ifdef NET_DETECT
+typedef struct net_detect_adapter_features {
+	uint8	wowl_enabled;
+	uint8	net_detect_enabled;
+	uint8	nlo_enabled;
+} net_detect_adapter_features_t;
+
+typedef enum net_detect_bss_type {
+	nd_bss_any = 0,
+	nd_ibss,
+	nd_ess
+} net_detect_bss_type_t;
+
+typedef struct net_detect_profile {
+	wlc_ssid_t		ssid;
+	net_detect_bss_type_t   bss_type;	/**< Ignore for now since Phase 1 is only for ESS */
+	uint32			cipher_type;	/**< DOT11_CIPHER_ALGORITHM enumeration values */
+	uint32			auth_type;	/**< DOT11_AUTH_ALGORITHM enumeration values */
+} net_detect_profile_t;
+
+typedef struct net_detect_profile_list {
+	uint32			num_nd_profiles;
+	net_detect_profile_t	nd_profile[0];
+} net_detect_profile_list_t;
+
+typedef struct net_detect_config {
+	uint8			    nd_enabled;
+	uint32			    scan_interval;
+	uint32			    wait_period;
+	uint8			    wake_if_connected;
+	uint8			    wake_if_disconnected;
+	net_detect_profile_list_t   nd_profile_list;
+} net_detect_config_t;
+
+typedef enum net_detect_wake_reason {
+	nd_reason_unknown,
+	nd_net_detected,
+	nd_wowl_event,
+	nd_ucode_error
+} net_detect_wake_reason_t;
+
+typedef struct net_detect_wake_data {
+	net_detect_wake_reason_t    nd_wake_reason;
+	uint32			    nd_wake_date_length;
+	uint8			    nd_wake_data[0];	    /**< Wake data (currently unused) */
+} net_detect_wake_data_t;
+
+#endif /* NET_DETECT */
+
+
+/* (unversioned, deprecated) */
+typedef struct bcnreq {
+	uint8 bcn_mode;
+	int32 dur;
+	int32 channel;
+	struct ether_addr da;
+	uint16 random_int;
+	wlc_ssid_t ssid;
+	uint16 reps;
+} bcnreq_t;
+
+#define WL_RRM_BCN_REQ_VER		1
+typedef struct bcn_req {
+	uint8 version;
+	uint8 bcn_mode;
+	uint8 pad_1[2];
+	int32 dur;
+	int32 channel;
+	struct ether_addr da;
+	uint16 random_int;
+	wlc_ssid_t ssid;
+	uint16 reps;
+	uint8 req_elements;
+	uint8 pad_2;
+	chanspec_list_t chspec_list;
+} bcn_req_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 wl_rrm_config_ioc {
+	uint16 version; /* command version */
+	uint16 id;      /* subiovar cmd ID */
+	uint16 len;     /* total length of all bytes in data[] */
+	uint16 pad;     /* 4-byte boundary padding */
+	uint8 data[1];  /* payload */
+} wl_rrm_config_ioc_t;
+
+enum {
+	WL_RRM_CONFIG_NONE	= 0,	/* reserved */
+	WL_RRM_CONFIG_GET_LCI	= 1,	/* get LCI */
+	WL_RRM_CONFIG_SET_LCI	= 2,	/* set LCI */
+	WL_RRM_CONFIG_GET_CIVIC	= 3,	/* get civic location */
+	WL_RRM_CONFIG_SET_CIVIC	= 4,	/* set civic location */
+	WL_RRM_CONFIG_MAX		= 5
+};
+
+#define WL_RRM_CONFIG_NAME "rrm_config"
+#define WL_RRM_CONFIG_MIN_LENGTH OFFSETOF(wl_rrm_config_ioc_t, data)
+
+enum {
+	WL_RRM_EVENT_NONE		= 0,	/* not an event, reserved */
+	WL_RRM_EVENT_FRNG_REQ	= 1,	/* Receipt of FRNG request frame */
+	WL_RRM_EVENT_FRNG_REP	= 2,	/* Receipt of FRNG report frame */
+
+	WL_RRM_EVENT_MAX
+};
+typedef int16 wl_rrm_event_type_t;
+
+typedef struct frngreq_target {
+	uint32 bssid_info;
+	uint8 channel;
+	uint8 phytype;
+	uint8 reg;
+	uint8 pad;
+	struct ether_addr bssid;
+	chanspec_t chanspec;
+	uint32 sid;
+} frngreq_target_t;
+
+typedef struct frngreq {
+	wl_rrm_event_type_t event;			/* RRM event type */
+	struct ether_addr da;
+	uint16 max_init_delay;	/* Upper bound of random delay, in TUs */
+	uint8 min_ap_count;		/* Min FTM ranges requested (1-15) */
+	uint8 num_aps;			/* Number of APs to range, at least min_ap_count */
+	uint16 max_age;			/* Max elapsed time before FTM request, 0xFFFF = any */
+	uint16 reps;			/* Number of repetitions of this measurement type */
+	frngreq_target_t targets[1];	/* Target BSSIDs to range */
+} frngreq_t;
+
+typedef struct frngrep_range {
+	uint32 start_tsf;		/* 4 lsb of tsf */
+	struct ether_addr bssid;
+	uint8 pad[2];
+	uint32 range;
+	uint32 max_err;
+	uint8  rsvd;
+	uint8 pad2[3];
+} frngrep_range_t;
+
+typedef struct frngrep_error {
+	uint32 start_tsf;		/* 4 lsb of tsf */
+	struct ether_addr bssid;
+	uint8  code;
+	uint8 pad[1];
+} frngrep_error_t;
+
+typedef struct frngrep {
+	wl_rrm_event_type_t event;			/* RRM event type */
+	struct ether_addr da;
+	uint8 range_entry_count;
+	uint8 error_entry_count;
+	uint16 dialog_token;				/* dialog token */
+	frngrep_range_t range_entries[DOT11_FTM_RANGE_ENTRY_MAX_COUNT];
+	frngrep_error_t error_entries[DOT11_FTM_RANGE_ERROR_ENTRY_MAX_COUNT];
+} frngrep_t;
+
+typedef struct wl_rrm_frng_ioc {
+	uint16 version; /* command version */
+	uint16 id;      /* subiovar cmd ID */
+	uint16 len;     /* total length of all bytes in data[] */
+	uint16 pad;     /* 4-byte boundary padding */
+	uint8 data[1];  /* payload */
+} wl_rrm_frng_ioc_t;
+
+enum {
+	WL_RRM_FRNG_NONE	= 0,	/* reserved */
+	WL_RRM_FRNG_SET_REQ	= 1,	/* send ftm ranging request */
+	WL_RRM_FRNG_MAX		= 2
+};
+
+#define WL_RRM_FRNG_NAME "rrm_frng"
+#define WL_RRM_FRNG_MIN_LENGTH OFFSETOF(wl_rrm_frng_ioc_t, data)
+
+#define WL_RRM_RPT_VER		0
+#define WL_RRM_RPT_MAX_PAYLOAD	256
+#define WL_RRM_RPT_MIN_PAYLOAD	7
+#define WL_RRM_RPT_FALG_ERR	0
+#define WL_RRM_RPT_FALG_GRP_ID_PROPR	(1 << 0)
+#define WL_RRM_RPT_FALG_GRP_ID_0	(1 << 1)
+typedef struct {
+	uint16 ver;		/**< version */
+	struct ether_addr addr;	/**< STA MAC addr */
+	uint32 timestamp;	/**< timestamp of the report */
+	uint16 flag;		/**< flag */
+	uint16 len;		/**< length of payload data */
+	uint8 data[WL_RRM_RPT_MAX_PAYLOAD];
+} statrpt_t;
+
+typedef struct wlc_dwds_config {
+	uint32		enable;
+	uint32		mode; /**< STA/AP interface */
+	struct ether_addr ea;
+} wlc_dwds_config_t;
+
+typedef struct wl_el_set_params_s {
+	uint8 set;	/**< Set number */
+	uint32 size;	/**< Size to make/expand */
+} wl_el_set_params_t;
+
+typedef struct wl_el_tag_params_s {
+	uint16 tag;
+	uint8 set;
+	uint8 flags;
+} wl_el_tag_params_t;
+
+/** Video Traffic Interference Monitor config */
+#define INTFER_VERSION		1
+typedef struct wl_intfer_params {
+	uint16 version;			/**< version */
+	uint8 period;			/**< sample period */
+	uint8 cnt;			/**< sample cnt */
+	uint8 txfail_thresh;	/**< non-TCP txfail threshold */
+	uint8 tcptxfail_thresh;	/**< tcptxfail threshold */
+} wl_intfer_params_t;
+
+typedef struct wl_staprio_cfg {
+	struct ether_addr ea;	/**< mac addr */
+	uint8 prio;		/**< scb priority */
+} wl_staprio_cfg_t;
+
+typedef enum wl_stamon_cfg_cmd_type {
+	STAMON_CFG_CMD_DEL = 0,
+	STAMON_CFG_CMD_ADD = 1,
+	STAMON_CFG_CMD_ENB = 2,
+	STAMON_CFG_CMD_DSB = 3,
+	STAMON_CFG_CMD_CNT = 4,
+	STAMON_CFG_CMD_RSTCNT = 5,
+	STAMON_CFG_CMD_GET_STATS = 6
+} wl_stamon_cfg_cmd_type_t;
+
+typedef struct wlc_stamon_sta_config {
+	wl_stamon_cfg_cmd_type_t cmd; /**< 0 - delete, 1 - add */
+	struct ether_addr ea;
+} wlc_stamon_sta_config_t;
+
+#ifdef SR_DEBUG
+typedef struct /* pmu_reg */{
+	uint32  pmu_control;
+	uint32  pmu_capabilities;
+	uint32  pmu_status;
+	uint32  res_state;
+	uint32  res_pending;
+	uint32  pmu_timer1;
+	uint32  min_res_mask;
+	uint32  max_res_mask;
+	uint32  pmu_chipcontrol1[4];
+	uint32  pmu_regcontrol[5];
+	uint32  pmu_pllcontrol[5];
+	uint32  pmu_rsrc_up_down_timer[31];
+	uint32  rsrc_dep_mask[31];
+} pmu_reg_t;
+#endif /* pmu_reg */
+
+typedef struct wl_taf_define {
+	struct ether_addr ea;	/**< STA MAC or 0xFF... */
+	uint16 version;         /**< version */
+	uint32 sch;             /**< method index */
+	uint32 prio;            /**< priority */
+	uint32 misc;            /**< used for return value */
+	uint8   text[1];         /**< used to pass and return ascii text */
+} wl_taf_define_t;
+
+/** Received Beacons lengths information */
+#define WL_LAST_BCNS_INFO_FIXED_LEN		OFFSETOF(wlc_bcn_len_hist_t, bcnlen_ring)
+typedef struct wlc_bcn_len_hist {
+	uint16	ver;				/**< version field */
+	uint16	cur_index;			/**< current pointed index in ring buffer */
+	uint32	max_bcnlen;		/**< Max beacon length received */
+	uint32	min_bcnlen;		/**< Min beacon length received */
+	uint32	ringbuff_len;		/**< Length of the ring buffer 'bcnlen_ring' */
+	uint32	bcnlen_ring[1];	/**< ring buffer storing received beacon lengths */
+} wlc_bcn_len_hist_t;
+
+/* WDS net interface types */
+#define WL_WDSIFTYPE_NONE  0x0 /**< The interface type is neither WDS nor DWDS. */
+#define WL_WDSIFTYPE_WDS   0x1 /**< The interface is WDS type. */
+#define WL_WDSIFTYPE_DWDS  0x2 /**< The interface is DWDS type. */
+
+typedef struct wl_bssload_static {
+	uint8 is_static;
+	uint16 sta_count;
+	uint8 chan_util;
+	uint16 aac;
+} wl_bssload_static_t;
+
+/* Buffer of size WLC_SAMPLECOLLECT_MAXLEN (=10240 for 4345a0 ACPHY)
+ * gets copied to this, multiple times
+ */
+typedef enum wl_gpaio_option {
+	GPAIO_PMU_AFELDO,
+	GPAIO_PMU_TXLDO,
+	GPAIO_PMU_VCOLDO,
+	GPAIO_PMU_LNALDO,
+	GPAIO_PMU_ADCLDO,
+	GPAIO_ICTAT_CAL,
+	GPAIO_PMU_CLEAR,
+	GPAIO_OFF,
+	GPAIO_PMU_LOGENLDO,
+	GPAIO_PMU_RXLDO2G,
+	GPAIO_PMU_RXLDO5G
+} wl_gpaio_option_t;
+
+/** IO Var Operations - the Value of iov_op In wlc_ap_doiovar */
+typedef enum wlc_ap_iov_bss_operation {
+	WLC_AP_IOV_OP_DELETE                   = -1,
+	WLC_AP_IOV_OP_DISABLE                  = 0,
+	WLC_AP_IOV_OP_ENABLE                   = 1,
+	WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE  = 2,
+	WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE = 3,
+	WLC_AP_IOV_OP_MOVE                     = 4
+} wlc_ap_iov_bss_oper_t;
+
+/* LTE coex info */
+/* Analogue of HCI Set MWS Signaling cmd */
+typedef struct {
+	int16	mws_rx_assert_offset;
+	int16	mws_rx_assert_jitter;
+	int16	mws_rx_deassert_offset;
+	int16	mws_rx_deassert_jitter;
+	int16	mws_tx_assert_offset;
+	int16	mws_tx_assert_jitter;
+	int16	mws_tx_deassert_offset;
+	int16	mws_tx_deassert_jitter;
+	int16	mws_pattern_assert_offset;
+	int16	mws_pattern_assert_jitter;
+	int16	mws_inact_dur_assert_offset;
+	int16	mws_inact_dur_assert_jitter;
+	int16	mws_scan_freq_assert_offset;
+	int16	mws_scan_freq_assert_jitter;
+	int16	mws_prio_assert_offset_req;
+} wci2_config_t;
+
+/** Analogue of HCI MWS Channel Params */
+typedef struct {
+	uint16	mws_rx_center_freq; /**< MHz */
+	uint16	mws_tx_center_freq;
+	uint16	mws_rx_channel_bw;  /**< KHz */
+	uint16	mws_tx_channel_bw;
+	uint8	mws_channel_en;
+	uint8	mws_channel_type;   /**< Don't care for WLAN? */
+} mws_params_t;
+
+#define LTECX_MAX_NUM_PERIOD_TYPES	7
+
+/* LTE Frame params */
+typedef struct {
+	uint16	mws_frame_dur;
+	int16	mws_framesync_assert_offset;
+	uint16	mws_framesync_assert_jitter;
+	uint16  mws_period_dur[LTECX_MAX_NUM_PERIOD_TYPES];
+	uint8	mws_period_type[LTECX_MAX_NUM_PERIOD_TYPES];
+	uint8	mws_num_periods;
+} mws_frame_config_t;
+
+/** MWS wci2 message */
+typedef struct {
+	uint8	mws_wci2_data; /**< BT-SIG msg */
+	uint16	mws_wci2_interval; /**< Interval in us */
+	uint16	mws_wci2_repeat; /**< No of msgs to send */
+} mws_wci2_msg_t;
+/* MWS ANT map */
+typedef struct {
+	uint16	combo1; /* mws ant selection 1 */
+	uint16	combo2; /* mws ant selection 2 */
+	uint16	combo3; /* mws ant selection 3 */
+	uint16	combo4; /* mws ant selection 4 */
+} mws_ant_map_t;
+
+/* MWS SCAN_REQ Bitmap */
+typedef struct mws_scanreq_params {
+	uint16 idx;
+	uint16 bm_2g;
+	uint16 bm_5g_lo;
+	uint16 bm_5g_mid;
+	uint16 bm_5g_hi;
+} mws_scanreq_params_t;
+
+typedef struct {
+	uint32 config;	/**< MODE: AUTO (-1), Disable (0), Enable (1) */
+	uint32 status;	/**< Current state: Disabled (0), Enabled (1) */
+} wl_config_t;
+
+#define WLC_RSDB_MODE_AUTO_MASK 0x80
+#define WLC_RSDB_EXTRACT_MODE(val) ((int8)((val) & (~(WLC_RSDB_MODE_AUTO_MASK))))
+
+typedef struct {
+	uint16  request; /* type of sensor hub request */
+	uint16  enable; /* enable/disable response for specified request */
+	uint16  interval; /* interval between responses to the request */
+} shub_req_t;
+
+#define	WL_IF_STATS_T_VERSION 1	/**< current version of wl_if_stats structure */
+
+/** per interface counters */
+typedef struct wl_if_stats {
+	uint16	version;		/**< version of the structure */
+	uint16	length;			/**< length of the entire structure */
+	uint32	PAD;			/**< padding */
+
+	/* transmit stat counters */
+	uint64	txframe;		/**< tx data frames */
+	uint64	txbyte;			/**< tx data bytes */
+	uint64	txerror;		/**< tx data errors (derived: sum of others) */
+	uint64  txnobuf;		/**< tx out of buffer errors */
+	uint64  txrunt;			/**< tx runt frames */
+	uint64  txfail;			/**< tx failed frames */
+	uint64	txretry;		/**< tx retry frames */
+	uint64	txretrie;		/**< tx multiple retry frames */
+	uint64	txfrmsnt;		/**< tx sent frames */
+	uint64	txmulti;		/**< tx mulitcast sent frames */
+	uint64	txfrag;			/**< tx fragments sent */
+
+	/* receive stat counters */
+	uint64	rxframe;		/**< rx data frames */
+	uint64	rxbyte;			/**< rx data bytes */
+	uint64	rxerror;		/**< rx data errors (derived: sum of others) */
+	uint64	rxnobuf;		/**< rx out of buffer errors */
+	uint64  rxrunt;			/**< rx runt frames */
+	uint64  rxfragerr;		/**< rx fragment errors */
+	uint64	rxmulti;		/**< rx multicast frames */
+
+	uint64	txexptime;		/* DATA Tx frames suppressed due to timer expiration */
+	uint64	txrts;			/* RTS/CTS succeeeded count */
+	uint64	txnocts;		/* RTS/CTS faled count */
+}
+wl_if_stats_t;
+
+typedef struct wl_band {
+	uint16		bandtype;		/**< WL_BAND_2G, WL_BAND_5G */
+	uint16		bandunit;		/**< bandstate[] index */
+	uint16		phytype;		/**< phytype */
+	uint16		phyrev;
+}
+wl_band_t;
+
+#define	WL_WLC_VERSION_T_VERSION 1 /**< current version of wlc_version structure */
+
+/** wlc interface version */
+typedef struct wl_wlc_version {
+	uint16	version;		/**< version of the structure */
+	uint16	length;			/**< length of the entire structure */
+
+	/* epi version numbers */
+	uint16	epi_ver_major;		/**< epi major version number */
+	uint16	epi_ver_minor;		/**< epi minor version number */
+	uint16	epi_rc_num;		/**< epi RC number */
+	uint16	epi_incr_num;		/**< epi increment number */
+
+	/* wlc interface version numbers */
+	uint16	wlc_ver_major;		/**< wlc interface major version number */
+	uint16	wlc_ver_minor;		/**< wlc interface minor version number */
+}
+wl_wlc_version_t;
+
+/* Version of WLC interface to be returned as a part of wl_wlc_version structure.
+ * For the discussion related to versions update policy refer to
+ * http://hwnbu-twiki.broadcom.com/bin/view/Mwgroup/WlShimAbstractionLayer
+ * For now the policy is to increment WLC_VERSION_MAJOR each time
+ * there is a change that involves both WLC layer and per-port layer.
+ * WLC_VERSION_MINOR is currently not in use.
+ */
+#define WLC_VERSION_MAJOR	8
+#define WLC_VERSION_MINOR	0
+
+/* begin proxd definitions */
+#include <packed_section_start.h>
+
+#define WL_PROXD_API_VERSION 0x0300	/**< version 3.0 */
+
+/** Minimum supported API version */
+#define WL_PROXD_API_MIN_VERSION 0x0300
+
+/** proximity detection methods */
+enum {
+	WL_PROXD_METHOD_NONE	= 0,
+	WL_PROXD_METHOD_RSVD1	= 1, /**< backward compatibility - RSSI, not supported */
+	WL_PROXD_METHOD_TOF	= 2,
+	WL_PROXD_METHOD_RSVD2	= 3, /**< 11v only - if needed */
+	WL_PROXD_METHOD_FTM	= 4, /**< IEEE rev mc/2014 */
+	WL_PROXD_METHOD_MAX
+};
+typedef int16 wl_proxd_method_t;
+
+/** global and method configuration flags */
+enum {
+	WL_PROXD_FLAG_NONE			= 0x00000000,
+	WL_PROXD_FLAG_RX_ENABLED		= 0x00000001, /**< respond to requests, per bss */
+	WL_PROXD_FLAG_RX_RANGE_REQ		= 0x00000002, /**< 11mc range requests enabled */
+	WL_PROXD_FLAG_TX_LCI			= 0x00000004, /**< tx lci, if known */
+	WL_PROXD_FLAG_TX_CIVIC			= 0x00000008, /**< tx civic, if known */
+	WL_PROXD_FLAG_RX_AUTO_BURST		= 0x00000010, /**< auto respond w/o host action */
+	WL_PROXD_FLAG_TX_AUTO_BURST		= 0x00000020, /**< continue tx w/o host action */
+	WL_PROXD_FLAG_AVAIL_PUBLISH		= 0x00000040,     /**< publish availability */
+	WL_PROXD_FLAG_AVAIL_SCHEDULE		= 0x00000080,    /**< schedule using availability */
+	WL_PROXD_FLAG_ASAP_CAPABLE		= 0x00000100, /* ASAP capable */
+	WL_PROXD_FLAG_MBURST_FOLLOWUP		= 0x00000200, /* new multi-burst algorithm */
+	WL_PROXD_FLAG_SECURE			= 0x00000400, /* per bsscfg option */
+	WL_PROXD_FLAG_NO_TSF_SYNC		= 0x00000800, /* disable tsf sync */
+	WL_PROXD_FLAG_ALL			= 0xffffffff
+};
+typedef uint32 wl_proxd_flags_t;
+
+#define WL_PROXD_FLAGS_AVAIL (WL_PROXD_FLAG_AVAIL_PUBLISH | \
+	WL_PROXD_FLAG_AVAIL_SCHEDULE)
+
+/** session flags */
+enum {
+	WL_PROXD_SESSION_FLAG_NONE 		= 0x00000000,  /**< no flags */
+	WL_PROXD_SESSION_FLAG_INITIATOR 	= 0x00000001,  /**< local device is initiator */
+	WL_PROXD_SESSION_FLAG_TARGET 		= 0x00000002,  /**< local device is target */
+	WL_PROXD_SESSION_FLAG_ONE_WAY		= 0x00000004,  /**< (initiated) 1-way rtt */
+	WL_PROXD_SESSION_FLAG_AUTO_BURST	= 0x00000008,  /**< created w/ rx_auto_burst */
+	WL_PROXD_SESSION_FLAG_MBURST_NODELAY	= 0x00000010,  /**< good until cancelled */
+	WL_PROXD_SESSION_FLAG_RTT_DETAIL	= 0x00000020,  /**< rtt detail in results */
+	WL_PROXD_SESSION_FLAG_SECURE		= 0x00000040,  /**< sessionis secure */
+	WL_PROXD_SESSION_FLAG_AOA		= 0x00000080,  /**< AOA along w/ RTT */
+	WL_PROXD_SESSION_FLAG_RX_AUTO_BURST	= 0x00000100,  /**< Same as proxd flags above */
+	WL_PROXD_SESSION_FLAG_TX_AUTO_BURST	= 0x00000200,  /**< Same as proxd flags above */
+	WL_PROXD_SESSION_FLAG_NAN_BSS		= 0x00000400,  /**< Use NAN BSS, if applicable */
+	WL_PROXD_SESSION_FLAG_TS1		= 0x00000800,  /**< e.g. FTM1 - ASAP-capable */
+	WL_PROXD_SESSION_FLAG_REPORT_FAILURE	= 0x00002000, /**< report failure to target */
+	WL_PROXD_SESSION_FLAG_INITIATOR_RPT	= 0x00004000, /**< report distance to target */
+	WL_PROXD_SESSION_FLAG_NOCHANSWT		= 0x00008000,
+	WL_PROXD_SESSION_FLAG_NETRUAL		= 0x00010000, /**< netrual mode */
+	WL_PROXD_SESSION_FLAG_SEQ_EN		= 0x00020000, /**< Toast */
+	WL_PROXD_SESSION_FLAG_NO_PARAM_OVRD	= 0x00040000, /**< no param override from target */
+	WL_PROXD_SESSION_FLAG_ASAP		= 0x00080000, /**< ASAP session */
+	WL_PROXD_SESSION_FLAG_REQ_LCI		= 0x00100000, /**< transmit LCI req */
+	WL_PROXD_SESSION_FLAG_REQ_CIV		= 0x00200000, /**< transmit civic loc req */
+	WL_PROXD_SESSION_FLAG_PRE_SCAN		= 0x00400000, /* enable pre-scan for asap=1 */
+	WL_PROXD_SESSION_FLAG_AUTO_VHTACK	= 0x00800000, /* use vhtack based on brcm ie */
+	WL_PROXD_SESSION_FLAG_VHTACK		= 0x01000000, /* vht ack is in use - output only */
+	WL_PROXD_SESSION_FLAG_BDUR_NOPREF	= 0x02000000, /* burst-duration: no preference */
+	WL_PROXD_SESSION_FLAG_NUM_FTM_NOPREF	= 0x04000000, /* num of FTM frames: no preference */
+	WL_PROXD_SESSION_FLAG_FTM_SEP_NOPREF	= 0x08000000, /* time btw FTM frams: no pref */
+	WL_PROXD_SESSION_FLAG_NUM_BURST_NOPREF	= 0x10000000, /* num of bursts: no pref */
+	WL_PROXD_SESSION_FLAG_BURST_PERIOD_NOPREF = 0x20000000, /* burst period: no pref */
+	WL_PROXD_SESSION_FLAG_MBURST_FOLLOWUP	= 0x40000000, /* new mburst algo  - reserved */
+	WL_PROXD_SESSION_FLAG_UNUSED_BIT31	= 0x80000000,
+	WL_PROXD_SESSION_FLAG_ALL		= 0xffffffff
+};
+typedef uint32 wl_proxd_session_flags_t;
+
+/** time units - mc supports up to 0.1ns resolution */
+enum {
+	WL_PROXD_TMU_TU			= 0,		/**< 1024us */
+	WL_PROXD_TMU_SEC		= 1,
+	WL_PROXD_TMU_MILLI_SEC	= 2,
+	WL_PROXD_TMU_MICRO_SEC	= 3,
+	WL_PROXD_TMU_NANO_SEC	= 4,
+	WL_PROXD_TMU_PICO_SEC	= 5
+};
+typedef int16 wl_proxd_tmu_t;
+
+/** time interval e.g. 10ns */
+typedef struct wl_proxd_intvl {
+	uint32 intvl;
+	wl_proxd_tmu_t tmu;
+	uint8	pad[2];
+} wl_proxd_intvl_t;
+
+/** commands that can apply to proxd, method or a session */
+enum {
+	WL_PROXD_CMD_NONE				= 0,
+	WL_PROXD_CMD_GET_VERSION		= 1,
+	WL_PROXD_CMD_ENABLE 			= 2,
+	WL_PROXD_CMD_DISABLE 			= 3,
+	WL_PROXD_CMD_CONFIG 			= 4,
+	WL_PROXD_CMD_START_SESSION 		= 5,
+	WL_PROXD_CMD_BURST_REQUEST 		= 6,
+	WL_PROXD_CMD_STOP_SESSION 		= 7,
+	WL_PROXD_CMD_DELETE_SESSION 	= 8,
+	WL_PROXD_CMD_GET_RESULT 		= 9,
+	WL_PROXD_CMD_GET_INFO 			= 10,
+	WL_PROXD_CMD_GET_STATUS 		= 11,
+	WL_PROXD_CMD_GET_SESSIONS 		= 12,
+	WL_PROXD_CMD_GET_COUNTERS 		= 13,
+	WL_PROXD_CMD_CLEAR_COUNTERS 	= 14,
+	WL_PROXD_CMD_COLLECT 			= 15,	/* not supported, see 'wl proxd_collect' */
+	WL_PROXD_CMD_TUNE 			= 16,	/* not supported, see 'wl proxd_tune' */
+	WL_PROXD_CMD_DUMP 				= 17,
+	WL_PROXD_CMD_START_RANGING		= 18,
+	WL_PROXD_CMD_STOP_RANGING		= 19,
+	WL_PROXD_CMD_GET_RANGING_INFO	= 20,
+	WL_PROXD_CMD_IS_TLV_SUPPORTED	= 21,
+
+	WL_PROXD_CMD_MAX
+};
+typedef int16 wl_proxd_cmd_t;
+
+/* session ids:
+ * id 0 is reserved
+ * ids 1..0x7fff - allocated by host/app
+ * 0x8000-0xffff - allocated by firmware, used for auto/rx
+ */
+enum {
+	 WL_PROXD_SESSION_ID_GLOBAL = 0
+};
+
+/* Externally allocated sids */
+#define WL_PROXD_SID_EXT_MAX 0x7fff
+#define WL_PROXD_SID_EXT_ALLOC(_sid) ((_sid) > 0 && (_sid) <= WL_PROXD_SID_EXT_MAX)
+
+/* block size for reserved sid blocks */
+#define WL_PROXD_SID_EXT_BLKSZ 256
+#define WL_PROXD_SID_EXT_BLK_START(_i) (WL_PROXD_SID_EXT_MAX - (_i) * WL_PROXD_SID_EXT_BLKSZ + 1)
+#define WL_PROXD_SID_EXT_BLK_END(_start) ((_start) + WL_PROXD_SID_EXT_BLKSZ - 1)
+
+/* rrm block */
+#define WL_PROXD_SID_RRM_START WL_PROXD_SID_EXT_BLK_START(1)
+#define WL_PROXD_SID_RRM_END WL_PROXD_SID_EXT_BLK_END(WL_PROXD_SID_RRM_START)
+
+/* nan block */
+#define WL_PROXD_SID_NAN_START WL_PROXD_SID_EXT_BLK_START(2)
+#define WL_PROXD_SID_NAN_END WL_PROXD_SID_EXT_BLK_END(WL_PROXD_SID_NAN_START)
+
+/** maximum number sessions that can be allocated, may be less if tunable */
+#define WL_PROXD_MAX_SESSIONS 16
+
+typedef uint16 wl_proxd_session_id_t;
+
+/** status - TBD BCME_ vs proxd status - range reserved for BCME_ */
+enum {
+	WL_PROXD_E_NOAVAIL		= -1056,
+	WL_PROXD_E_EXT_SCHED		= -1055,
+	WL_PROXD_E_NOT_BCM			= -1054,
+	WL_PROXD_E_FRAME_TYPE		= -1053,
+	WL_PROXD_E_VERNOSUPPORT		= -1052,
+	WL_PROXD_E_SEC_NOKEY		= -1051,
+	WL_PROXD_E_SEC_POLICY		= -1050,
+	WL_PROXD_E_SCAN_INPROCESS	= -1049,
+	WL_PROXD_E_BAD_PARTIAL_TSF	= -1048,
+	WL_PROXD_E_SCANFAIL			= -1047,
+	WL_PROXD_E_NOTSF			= -1046,
+	WL_PROXD_E_POLICY			= -1045,
+	WL_PROXD_E_INCOMPLETE		= -1044,
+	WL_PROXD_E_OVERRIDDEN		= -1043,
+	WL_PROXD_E_ASAP_FAILED		= -1042,
+	WL_PROXD_E_NOTSTARTED		= -1041,
+	WL_PROXD_E_INVALIDMEAS		= -1040,
+	WL_PROXD_E_INCAPABLE		= -1039,
+	WL_PROXD_E_MISMATCH			= -1038,
+	WL_PROXD_E_DUP_SESSION		= -1037,
+	WL_PROXD_E_REMOTE_FAIL		= -1036,
+	WL_PROXD_E_REMOTE_INCAPABLE = -1035,
+	WL_PROXD_E_SCHED_FAIL		= -1034,
+	WL_PROXD_E_PROTO			= -1033,
+	WL_PROXD_E_EXPIRED			= -1032,
+	WL_PROXD_E_TIMEOUT			= -1031,
+	WL_PROXD_E_NOACK			= -1030,
+	WL_PROXD_E_DEFERRED			= -1029,
+	WL_PROXD_E_INVALID_SID		= -1028,
+	WL_PROXD_E_REMOTE_CANCEL 	= -1027,
+	WL_PROXD_E_CANCELED			= -1026,	/**< local */
+	WL_PROXD_E_INVALID_SESSION	= -1025,
+	WL_PROXD_E_BAD_STATE		= -1024,
+	WL_PROXD_E_ERROR			= -1,
+	WL_PROXD_E_OK				= 0
+};
+typedef int32 wl_proxd_status_t;
+
+/* proxd errors from phy */
+#define PROXD_TOF_INIT_ERR_BITS 16
+
+enum {
+	WL_PROXD_PHY_ERR_LB_CORR_THRESH    = (1 << 0), /* Loopback Correlation threshold */
+	WL_PROXD_PHY_ERR_RX_CORR_THRESH    = (1 << 1), /* Received Correlation threshold */
+	WL_PROXD_PHY_ERR_LB_PEAK_POWER     = (1 << 2), /* Loopback Peak power   */
+	WL_PROXD_PHY_ERR_RX_PEAK_POWER     = (1 << 3), /* Received Peak power   */
+	WL_PROXD_PHY_ERR_BITFLIP           = (1 << 4), /* Bitflips */
+	WL_PROXD_PHY_ERR_SNR               = (1 << 5), /* SNR */
+	WL_PROXD_PHY_RX_STRT_WIN_OFF       = (1 << 6), /* Receive start window is off */
+	WL_PROXD_PHY_RX_END_WIN_OFF        = (1 << 7), /* Receive End window is off */
+	WL_PROXD_PHY_ERR_LOW_CONFIDENCE    = (1 << 15), /* Low confidence on meas distance */
+};
+typedef uint32 wl_proxd_phy_error_t;
+
+/** session states */
+enum {
+	WL_PROXD_SESSION_STATE_NONE				= 0,
+	WL_PROXD_SESSION_STATE_CREATED			= 1,
+	WL_PROXD_SESSION_STATE_CONFIGURED		= 2,
+	WL_PROXD_SESSION_STATE_STARTED			= 3,
+	WL_PROXD_SESSION_STATE_DELAY			= 4,
+	WL_PROXD_SESSION_STATE_USER_WAIT		= 5,
+	WL_PROXD_SESSION_STATE_SCHED_WAIT		= 6,
+	WL_PROXD_SESSION_STATE_BURST			= 7,
+	WL_PROXD_SESSION_STATE_STOPPING			= 8,
+	WL_PROXD_SESSION_STATE_ENDED			= 9,
+	WL_PROXD_SESSION_STATE_START_WAIT		= 10,
+	WL_PROXD_SESSION_STATE_DESTROYING		= -1
+};
+typedef int16 wl_proxd_session_state_t;
+
+/** RTT sample flags */
+enum {
+	WL_PROXD_RTT_SAMPLE_NONE = 0x00,
+	WL_PROXD_RTT_SAMPLE_DISCARD	= 0x01
+};
+typedef uint8 wl_proxd_rtt_sample_flags_t;
+typedef int16 wl_proxd_rssi_t;
+typedef uint16 wl_proxd_snr_t;
+typedef uint16 wl_proxd_bitflips_t;
+
+typedef struct wl_proxd_rtt_sample {
+	uint8				id;			/**< id for the sample - non-zero */
+	wl_proxd_rtt_sample_flags_t	flags;
+	wl_proxd_rssi_t			rssi;
+	wl_proxd_intvl_t			rtt;		/**< round trip time */
+	uint32				ratespec;
+	wl_proxd_snr_t                  snr;
+	wl_proxd_bitflips_t             bitflips;
+	wl_proxd_status_t		status;
+	int32				distance;
+	wl_proxd_phy_error_t		tof_phy_error;
+	uint8				coreid;
+} wl_proxd_rtt_sample_t;
+
+/** result flags */
+enum {
+	WL_PRXOD_RESULT_FLAG_NONE	= 0x0000,
+	WL_PROXD_RESULT_FLAG_NLOS	= 0x0001,	/**< LOS - if available */
+	WL_PROXD_RESULT_FLAG_LOS	= 0x0002,	/**< NLOS - if available */
+	WL_PROXD_RESULT_FLAG_FATAL	= 0x0004,	/**< Fatal error during burst */
+	WL_PROXD_RESULT_FLAG_VHTACK	= 0x0008,	/* VHTACK or Legacy ACK used */
+	WL_PROXD_REQUEST_SENT		= 0x0010,	/* FTM request was sent */
+	WL_PROXD_REQUEST_ACKED		= 0x0020,	/* FTM request was acked */
+	WL_PROXD_LTFSEQ_STARTED		= 0x0040,	/* LTF sequence started */
+	WL_PROXD_RESULT_FLAG_ALL 	= 0xffff
+};
+typedef int16 wl_proxd_result_flags_t;
+
+/** rtt measurement result */
+typedef struct wl_proxd_rtt_result {
+	wl_proxd_session_id_t		sid;
+	wl_proxd_result_flags_t		flags;
+	wl_proxd_status_t		status;
+	struct ether_addr		peer;
+	wl_proxd_session_state_t	state;		/**< current state */
+	union {
+		wl_proxd_intvl_t		retry_after;	/* hint for errors */
+		wl_proxd_intvl_t		burst_duration; /* burst duration */
+	} u;
+	wl_proxd_rtt_sample_t		avg_rtt;
+	uint32				avg_dist;	/* 1/256m units */
+	uint16				sd_rtt;		/* RTT standard deviation */
+	uint8				num_valid_rtt;	/* valid rtt cnt */
+	uint8				num_ftm;	/* actual num of ftm cnt (Configured) */
+	uint16				burst_num;	/* in a session */
+	uint16				num_rtt;	/* 0 if no detail */
+	uint16				num_meas;	/* number of ftm frames seen OTA */
+	uint8                           pad[2];
+	wl_proxd_rtt_sample_t		rtt[1];		/* variable */
+} wl_proxd_rtt_result_t;
+
+/** aoa measurement result */
+typedef struct wl_proxd_aoa_result {
+	wl_proxd_session_id_t			sid;
+	wl_proxd_result_flags_t			flags;
+	wl_proxd_status_t				status;
+	struct ether_addr				peer;
+	wl_proxd_session_state_t		state;
+	uint16							burst_num;
+	uint8							pad[2];
+	/* wl_proxd_aoa_sample_t sample_avg; TBD */
+} BWL_POST_PACKED_STRUCT wl_proxd_aoa_result_t;
+#include <packed_section_end.h>
+
+/** global stats */
+typedef struct wl_proxd_counters {
+	uint32 tx;					/**< tx frame count */
+	uint32 rx;					/**< rx frame count */
+	uint32 burst;				/**< total number of burst */
+	uint32 sessions;			/**< total number of sessions */
+	uint32 max_sessions;		/**< max concurrency */
+	uint32 sched_fail;			/**< scheduling failures */
+	uint32 timeouts;			/**< timeouts */
+	uint32 protoerr;			/**< protocol errors */
+	uint32 noack;				/**< tx w/o ack */
+	uint32 txfail;				/**< any tx falure */
+	uint32 lci_req_tx;			/**< tx LCI requests */
+	uint32 lci_req_rx;			/**< rx LCI requests */
+	uint32 lci_rep_tx;			/**< tx LCI reports */
+	uint32 lci_rep_rx;			/**< rx LCI reports */
+	uint32 civic_req_tx;		/**< tx civic requests */
+	uint32 civic_req_rx;		/**< rx civic requests */
+	uint32 civic_rep_tx;		/**< tx civic reports */
+	uint32 civic_rep_rx;		/**< rx civic reports */
+	uint32 rctx;				/**< ranging contexts created */
+	uint32 rctx_done;			/**< count of ranging done */
+	uint32 publish_err;     /**< availability publishing errors */
+	uint32 on_chan;         /**< count of scheduler onchan */
+	uint32 off_chan;        /**< count of scheduler offchan */
+	uint32 tsf_lo;          /* local tsf or session tsf */
+	uint32 tsf_hi;
+	uint32 num_meas;
+} wl_proxd_counters_t;
+
+typedef struct wl_proxd_counters wl_proxd_session_counters_t;
+
+enum {
+	WL_PROXD_CAP_NONE 		= 0x0000,
+	WL_PROXD_CAP_ALL 		= 0xffff
+};
+typedef int16 wl_proxd_caps_t;
+
+/** method capabilities */
+enum {
+	WL_PROXD_FTM_CAP_NONE = 0x0000,
+	WL_PROXD_FTM_CAP_FTM1 = 0x0001
+};
+typedef uint16 wl_proxd_ftm_caps_t;
+
+typedef struct wl_proxd_tlv_id_list {
+	uint16			num_ids;
+	uint16			ids[1];
+} wl_proxd_tlv_id_list_t;
+
+typedef struct wl_proxd_session_id_list {
+	uint16 num_ids;
+	wl_proxd_session_id_t ids[1];
+} wl_proxd_session_id_list_t;
+
+typedef struct wl_proxd_tpk {
+	struct ether_addr	peer;
+	uint8 tpk[TPK_FTM_LEN];
+} wl_proxd_tpk_t;
+
+/* tlvs returned for get_info on ftm method
+ *	configuration:
+ *	proxd flags
+ *	event mask
+ *	debug mask
+ *	session defaults (session tlvs)
+ * status tlv - not supported for ftm method
+ * info tlv
+ */
+typedef struct wl_proxd_ftm_info {
+	wl_proxd_ftm_caps_t caps;
+	uint16 max_sessions;
+	uint16 num_sessions;
+	uint16 rx_max_burst;
+} wl_proxd_ftm_info_t;
+
+enum {
+	WL_PROXD_WAIT_NONE  = 0x0000,
+	WL_PROXD_WAIT_KEY	= 0x0001,
+	WL_PROXD_WAIT_SCHED	= 0x0002,
+	WL_PROXD_WAIT_TSF	= 0x0004
+};
+typedef int16 wl_proxd_wait_reason_t;
+
+/* tlvs returned for get_info on session
+ * session config (tlvs)
+ * session info tlv
+ */
+typedef struct wl_proxd_ftm_session_info {
+	uint16 sid;
+	uint8 bss_index;
+	uint8 pad;
+	struct ether_addr bssid;
+	wl_proxd_session_state_t state;
+	wl_proxd_status_t status;
+	uint16	burst_num;
+	wl_proxd_wait_reason_t wait_reason;
+	uint32	meas_start_lo; /* sn tsf of 1st meas for cur/prev burst */
+	uint32	meas_start_hi;
+} wl_proxd_ftm_session_info_t;
+
+typedef struct wl_proxd_ftm_session_status {
+	uint16 sid;
+	wl_proxd_session_state_t state;
+	wl_proxd_status_t status;
+	uint16	burst_num;
+	uint16	pad;
+} wl_proxd_ftm_session_status_t;
+
+/** rrm range request */
+typedef struct wl_proxd_range_req {
+	uint16 			num_repeat;
+	uint16			init_delay_range;	/**< in TUs */
+	uint8			pad;
+	uint8			num_nbr;		/**< number of (possible) neighbors */
+	nbr_element_t		nbr[1];
+} wl_proxd_range_req_t;
+
+#define WL_PROXD_LCI_LAT_OFF 	0
+#define WL_PROXD_LCI_LONG_OFF 	5
+#define WL_PROXD_LCI_ALT_OFF 	10
+
+#define WL_PROXD_LCI_GET_LAT(_lci, _lat, _lat_err) { \
+	unsigned _off = WL_PROXD_LCI_LAT_OFF; \
+	_lat_err = (_lci)->data[(_off)] & 0x3f; \
+	_lat = (_lci)->data[(_off)+1]; \
+	_lat |= (_lci)->data[(_off)+2] << 8; \
+	_lat |= (_lci)->data[_(_off)+3] << 16; \
+	_lat |= (_lci)->data[(_off)+4] << 24; \
+	_lat <<= 2; \
+	_lat |= (_lci)->data[(_off)] >> 6; \
+}
+
+#define WL_PROXD_LCI_GET_LONG(_lci, _lcilong, _long_err) { \
+	unsigned _off = WL_PROXD_LCI_LONG_OFF; \
+	_long_err = (_lci)->data[(_off)] & 0x3f; \
+	_lcilong = (_lci)->data[(_off)+1]; \
+	_lcilong |= (_lci)->data[(_off)+2] << 8; \
+	_lcilong |= (_lci)->data[_(_off)+3] << 16; \
+	_lcilong |= (_lci)->data[(_off)+4] << 24; \
+	__lcilong <<= 2; \
+	_lcilong |= (_lci)->data[(_off)] >> 6; \
+}
+
+#define WL_PROXD_LCI_GET_ALT(_lci, _alt_type, _alt, _alt_err) { \
+	unsigned _off = WL_PROXD_LCI_ALT_OFF; \
+	_alt_type = (_lci)->data[_off] & 0x0f; \
+	_alt_err = (_lci)->data[(_off)] >> 4; \
+	_alt_err |= ((_lci)->data[(_off)+1] & 0x03) << 4; \
+	_alt = (_lci)->data[(_off)+2]; \
+	_alt |= (_lci)->data[(_off)+3] << 8; \
+	_alt |= (_lci)->data[_(_off)+4] << 16; \
+	_alt <<= 6; \
+	_alt |= (_lci)->data[(_off) + 1] >> 2; \
+}
+
+#define WL_PROXD_LCI_VERSION(_lci) ((_lci)->data[15] >> 6)
+
+/* availability. advertising mechanism bss specific */
+/** availablity flags */
+enum {
+	WL_PROXD_AVAIL_NONE = 0,
+	WL_PROXD_AVAIL_NAN_PUBLISHED = 0x0001,
+	WL_PROXD_AVAIL_SCHEDULED = 0x0002        /**< scheduled by proxd */
+};
+typedef int16 wl_proxd_avail_flags_t;
+
+/** time reference */
+enum {
+	WL_PROXD_TREF_NONE = 0,
+	WL_PROXD_TREF_DEV_TSF = 1,
+	WL_PROXD_TREF_NAN_DW = 2,
+	WL_PROXD_TREF_TBTT = 3,
+	WL_PROXD_TREF_MAX		/* last entry */
+};
+typedef int16 wl_proxd_time_ref_t;
+
+/** proxd channel-time slot */
+typedef struct {
+	wl_proxd_intvl_t start;         /**< from ref */
+	wl_proxd_intvl_t duration;      /**< from start */
+	uint32  chanspec;
+} wl_proxd_time_slot_t;
+
+typedef struct wl_proxd_avail24 {
+	wl_proxd_avail_flags_t flags; /**< for query only */
+	wl_proxd_time_ref_t time_ref;
+	uint16	max_slots; /**< for query only */
+	uint16  num_slots;
+	wl_proxd_time_slot_t slots[1];	/**< ROM compat - not used */
+	wl_proxd_intvl_t 	repeat;
+	wl_proxd_time_slot_t ts0[1];
+} wl_proxd_avail24_t;
+#define WL_PROXD_AVAIL24_TIMESLOT(_avail24, _i) (&(_avail24)->ts0[(_i)])
+#define WL_PROXD_AVAIL24_TIMESLOT_OFFSET(_avail24) OFFSETOF(wl_proxd_avail24_t, ts0)
+#define WL_PROXD_AVAIL24_TIMESLOTS(_avail24) WL_PROXD_AVAIL24_TIMESLOT(_avail24, 0)
+#define WL_PROXD_AVAIL24_SIZE(_avail24, _num_slots) (\
+	WL_PROXD_AVAIL24_TIMESLOT_OFFSET(_avail24) + \
+	(_num_slots) * sizeof(*WL_PROXD_AVAIL24_TIMESLOT(_avail24, 0)))
+
+typedef struct wl_proxd_avail {
+	wl_proxd_avail_flags_t flags; /**< for query only */
+	wl_proxd_time_ref_t time_ref;
+	uint16	max_slots; /**< for query only */
+	uint16  num_slots;
+	wl_proxd_intvl_t 	repeat;
+	wl_proxd_time_slot_t slots[1];
+} wl_proxd_avail_t;
+#define WL_PROXD_AVAIL_TIMESLOT(_avail, _i) (&(_avail)->slots[(_i)])
+#define WL_PROXD_AVAIL_TIMESLOT_OFFSET(_avail) OFFSETOF(wl_proxd_avail_t, slots)
+
+#define WL_PROXD_AVAIL_TIMESLOTS(_avail) WL_PROXD_AVAIL_TIMESLOT(_avail, 0)
+#define WL_PROXD_AVAIL_SIZE(_avail, _num_slots) (\
+	WL_PROXD_AVAIL_TIMESLOT_OFFSET(_avail) + \
+	(_num_slots) * sizeof(*WL_PROXD_AVAIL_TIMESLOT(_avail, 0)))
+
+/* collect support TBD */
+
+/** debugging */
+enum {
+	WL_PROXD_DEBUG_NONE		= 0x00000000,
+	WL_PROXD_DEBUG_LOG		= 0x00000001,
+	WL_PROXD_DEBUG_IOV		= 0x00000002,
+	WL_PROXD_DEBUG_EVENT		= 0x00000004,
+	WL_PROXD_DEBUG_SESSION		= 0x00000008,
+	WL_PROXD_DEBUG_PROTO		= 0x00000010,
+	WL_PROXD_DEBUG_SCHED		= 0x00000020,
+	WL_PROXD_DEBUG_RANGING		= 0x00000040,
+	WL_PROXD_DEBUG_NAN		= 0x00000080,
+	WL_PROXD_DEBUG_PKT		= 0x00000100,
+	WL_PROXD_DEBUG_SEC		= 0x00000200,
+	WL_PROXD_DEBUG_EVENTLOG		= 0x80000000,	/* map/enable EVNET_LOG_TAG_PROXD_INFO */
+	WL_PROXD_DEBUG_ALL		= 0xffffffff
+};
+typedef uint32 wl_proxd_debug_mask_t;
+
+/** tlv IDs - data length 4 bytes unless overridden by type, alignment 32 bits */
+enum {
+	WL_PROXD_TLV_ID_NONE			= 0,
+	WL_PROXD_TLV_ID_METHOD			= 1,
+	WL_PROXD_TLV_ID_FLAGS			= 2,
+	WL_PROXD_TLV_ID_CHANSPEC		= 3,	/**< note: uint32 */
+	WL_PROXD_TLV_ID_TX_POWER		= 4,
+	WL_PROXD_TLV_ID_RATESPEC		= 5,
+	WL_PROXD_TLV_ID_BURST_DURATION		= 6,	/**< intvl - length of burst */
+	WL_PROXD_TLV_ID_BURST_PERIOD		= 7,	/**< intvl - between bursts */
+	WL_PROXD_TLV_ID_BURST_FTM_SEP		= 8,	/**< intvl - between FTMs */
+	WL_PROXD_TLV_ID_BURST_NUM_FTM		= 9,	/**< uint16 - per burst */
+	WL_PROXD_TLV_ID_NUM_BURST		= 10,	/**< uint16 */
+	WL_PROXD_TLV_ID_FTM_RETRIES		= 11,	/**< uint16 at FTM level */
+	WL_PROXD_TLV_ID_BSS_INDEX		= 12,	/**< uint8 */
+	WL_PROXD_TLV_ID_BSSID			= 13,
+	WL_PROXD_TLV_ID_INIT_DELAY		= 14,	/**< intvl - optional,non-standalone only */
+	WL_PROXD_TLV_ID_BURST_TIMEOUT		= 15,	/**< expect response within - intvl */
+	WL_PROXD_TLV_ID_EVENT_MASK		= 16,	/**< interested events - in/out */
+	WL_PROXD_TLV_ID_FLAGS_MASK		= 17,	/**< interested flags - in only */
+	WL_PROXD_TLV_ID_PEER_MAC		= 18,	/**< mac address of peer */
+	WL_PROXD_TLV_ID_FTM_REQ			= 19,	/**< dot11_ftm_req */
+	WL_PROXD_TLV_ID_LCI_REQ			= 20,
+	WL_PROXD_TLV_ID_LCI			= 21,
+	WL_PROXD_TLV_ID_CIVIC_REQ		= 22,
+	WL_PROXD_TLV_ID_CIVIC			= 23,
+	WL_PROXD_TLV_ID_AVAIL24			= 24,	/**< ROM compatibility */
+	WL_PROXD_TLV_ID_SESSION_FLAGS		= 25,
+	WL_PROXD_TLV_ID_SESSION_FLAGS_MASK	= 26,	/**< in only */
+	WL_PROXD_TLV_ID_RX_MAX_BURST		= 27,	/**< uint16 - limit bursts per session */
+	WL_PROXD_TLV_ID_RANGING_INFO		= 28,	/**< ranging info */
+	WL_PROXD_TLV_ID_RANGING_FLAGS		= 29,	/**< uint16 */
+	WL_PROXD_TLV_ID_RANGING_FLAGS_MASK	= 30,	/**< uint16, in only */
+	WL_PROXD_TLV_ID_NAN_MAP_ID		= 31,
+	WL_PROXD_TLV_ID_DEV_ADDR		= 32,
+	WL_PROXD_TLV_ID_AVAIL			= 33,	/**< wl_proxd_avail_t  */
+	WL_PROXD_TLV_ID_TLV_ID			= 34,	/* uint16 tlv-id */
+	WL_PROXD_TLV_ID_FTM_REQ_RETRIES		= 35,	/* uint16 FTM request retries */
+	WL_PROXD_TLV_ID_TPK			= 36,	/* 32byte TPK  */
+	WL_PROXD_TLV_ID_RI_RR			= 36,	/* RI_RR */
+	WL_PROXD_TLV_ID_TUNE			= 37,	/* wl_proxd_pararms_tof_tune_t */
+
+	/* output - 512 + x */
+	WL_PROXD_TLV_ID_STATUS			= 512,
+	WL_PROXD_TLV_ID_COUNTERS		= 513,
+	WL_PROXD_TLV_ID_INFO			= 514,
+	WL_PROXD_TLV_ID_RTT_RESULT		= 515,
+	WL_PROXD_TLV_ID_AOA_RESULT		= 516,
+	WL_PROXD_TLV_ID_SESSION_INFO		= 517,
+	WL_PROXD_TLV_ID_SESSION_STATUS		= 518,
+	WL_PROXD_TLV_ID_SESSION_ID_LIST		= 519,
+
+	/* debug tlvs can be added starting 1024 */
+	WL_PROXD_TLV_ID_DEBUG_MASK		= 1024,
+	WL_PROXD_TLV_ID_COLLECT			= 1025,	/**< output only */
+	WL_PROXD_TLV_ID_STRBUF			= 1026,
+
+	WL_PROXD_TLV_ID_COLLECT_HEADER		= 1025,	/* wl_proxd_collect_header_t */
+	WL_PROXD_TLV_ID_COLLECT_INFO		= 1028,	/* wl_proxd_collect_info_t */
+	WL_PROXD_TLV_ID_COLLECT_DATA		= 1029,	/* wl_proxd_collect_data_t */
+	WL_PROXD_TLV_ID_COLLECT_CHAN_DATA	= 1030,	/* wl_proxd_collect_data_t */
+
+	WL_PROXD_TLV_ID_MAX
+};
+
+typedef struct wl_proxd_tlv {
+	uint16 id;
+	uint16 len;
+	uint8  data[1];
+} wl_proxd_tlv_t;
+
+/** proxd iovar - applies to proxd, method or session */
+typedef struct wl_proxd_iov {
+	uint16 					version;
+	uint16 					len;
+	wl_proxd_cmd_t 			cmd;
+	wl_proxd_method_t 		method;
+	wl_proxd_session_id_t 	sid;
+	uint8					pad[2];
+	wl_proxd_tlv_t 			tlvs[1];	/**< variable */
+} wl_proxd_iov_t;
+
+#define WL_PROXD_IOV_HDR_SIZE OFFSETOF(wl_proxd_iov_t, tlvs)
+
+/* The following event definitions may move to bcmevent.h, but sharing proxd types
+ * across needs more invasive changes unrelated to proxd
+ */
+enum {
+	WL_PROXD_EVENT_NONE			= 0,	/**< not an event, reserved */
+	WL_PROXD_EVENT_SESSION_CREATE		= 1,
+	WL_PROXD_EVENT_SESSION_START		= 2,
+	WL_PROXD_EVENT_FTM_REQ			= 3,
+	WL_PROXD_EVENT_BURST_START		= 4,
+	WL_PROXD_EVENT_BURST_END		= 5,
+	WL_PROXD_EVENT_SESSION_END		= 6,
+	WL_PROXD_EVENT_SESSION_RESTART		= 7,
+	WL_PROXD_EVENT_BURST_RESCHED		= 8,	/**< burst rescheduled-e.g. partial TSF */
+	WL_PROXD_EVENT_SESSION_DESTROY		= 9,
+	WL_PROXD_EVENT_RANGE_REQ		= 10,
+	WL_PROXD_EVENT_FTM_FRAME		= 11,
+	WL_PROXD_EVENT_DELAY			= 12,
+	WL_PROXD_EVENT_VS_INITIATOR_RPT		= 13,	/**< (target) rx initiator-report */
+	WL_PROXD_EVENT_RANGING			= 14,
+	WL_PROXD_EVENT_LCI_MEAS_REP		= 15,	/* LCI measurement report */
+	WL_PROXD_EVENT_CIVIC_MEAS_REP		= 16,	/* civic measurement report */
+	WL_PROXD_EVENT_COLLECT			= 17,
+	WL_PROXD_EVENT_START_WAIT		= 18,	/* waiting to start */
+
+	WL_PROXD_EVENT_MAX
+};
+typedef int16 wl_proxd_event_type_t;
+
+/** proxd event mask - upto 32 events for now */
+typedef uint32 wl_proxd_event_mask_t;
+
+#define WL_PROXD_EVENT_MASK_ALL 0xfffffffe
+#define WL_PROXD_EVENT_MASK_EVENT(_event_type) (1 << (_event_type))
+#define WL_PROXD_EVENT_ENABLED(_mask, _event_type) (\
+	((_mask) & WL_PROXD_EVENT_MASK_EVENT(_event_type)) != 0)
+
+/** proxd event - applies to proxd, method or session */
+typedef struct wl_proxd_event {
+	uint16					version;
+	uint16					len;
+	wl_proxd_event_type_t 	type;
+	wl_proxd_method_t 		method;
+	wl_proxd_session_id_t 	sid;
+	uint8					pad[2];
+	wl_proxd_tlv_t 			tlvs[1];	/**< variable */
+} wl_proxd_event_t;
+
+enum {
+	WL_PROXD_RANGING_STATE_NONE = 0,
+	WL_PROXD_RANGING_STATE_NOTSTARTED = 1,
+	WL_PROXD_RANGING_STATE_INPROGRESS = 2,
+	WL_PROXD_RANGING_STATE_DONE = 3
+};
+typedef int16 wl_proxd_ranging_state_t;
+
+/** proxd ranging flags */
+enum {
+	WL_PROXD_RANGING_FLAG_NONE = 0x0000,  /**< no flags */
+	WL_PROXD_RANGING_FLAG_DEL_SESSIONS_ON_STOP = 0x0001,
+	WL_PROXD_RANGING_FLAG_ALL = 0xffff
+};
+typedef uint16 wl_proxd_ranging_flags_t;
+
+struct wl_proxd_ranging_info {
+	wl_proxd_status_t   status;
+	wl_proxd_ranging_state_t state;
+	wl_proxd_ranging_flags_t flags;
+	uint16	num_sids;
+	uint16	num_done;
+};
+typedef struct wl_proxd_ranging_info wl_proxd_ranging_info_t;
+
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_event_data {
+	uint32                  H_LB[K_TOF_COLLECT_H_SIZE_20MHZ];
+	uint32                  H_RX[K_TOF_COLLECT_H_SIZE_20MHZ];
+	uint8                   ri_rr[FTM_TPK_LEN];
+	wl_proxd_phy_error_t    phy_err_mask;
+} BWL_POST_PACKED_STRUCT wl_proxd_collect_event_data_t;
+#include <packed_section_end.h>
+
+/** Data returned by the bssload_report iovar. This is also the WLC_E_BSS_LOAD event data */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct wl_bssload {
+	uint16 sta_count;		/**< station count */
+	uint16 aac;			/**< available admission capacity */
+	uint8 chan_util;		/**< channel utilization */
+} BWL_POST_PACKED_STRUCT wl_bssload_t;
+#include <packed_section_end.h>
+
+/**
+ * Maximum number of configurable BSS Load levels.  The number of BSS Load
+ * ranges is always 1 more than the number of configured levels.  eg. if
+ * 3 levels of 10, 20, 30 are configured then this defines 4 load ranges:
+ * 0-10, 11-20, 21-30, 31-255.  A WLC_E_BSS_LOAD event is generated each time
+ * the utilization level crosses into another range, subject to the rate limit.
+ */
+#define MAX_BSSLOAD_LEVELS 8
+#define MAX_BSSLOAD_RANGES (MAX_BSSLOAD_LEVELS + 1)
+
+/** BSS Load event notification configuration. */
+typedef struct wl_bssload_cfg {
+	uint32 rate_limit_msec;	/**< # of events posted to application will be limited to
+				 * one per specified period (0 to disable rate limit).
+				 */
+	uint8 num_util_levels;	/**< Number of entries in util_levels[] below */
+	uint8 util_levels[MAX_BSSLOAD_LEVELS];
+				/**< Variable number of BSS Load utilization levels in
+				 * low to high order.  An event will be posted each time
+				 * a received beacon's BSS Load IE channel utilization
+				 * value crosses a level.
+				 */
+} wl_bssload_cfg_t;
+
+/** Multiple roaming profile suport */
+#define WL_MAX_ROAM_PROF_BRACKETS	4
+
+#define WL_ROAM_PROF_VER_0	0
+#define WL_ROAM_PROF_VER_1	1
+#define WL_MAX_ROAM_PROF_VER	WL_ROAM_PROF_VER_1
+
+#define WL_ROAM_PROF_NONE	(0 << 0)
+#define WL_ROAM_PROF_LAZY	(1 << 0)
+#define WL_ROAM_PROF_NO_CI	(1 << 1)
+#define WL_ROAM_PROF_SUSPEND	(1 << 2)
+#define WL_ROAM_PROF_SYNC_DTIM	(1 << 6)
+#define WL_ROAM_PROF_DEFAULT	(1 << 7)	/**< backward compatible single default profile */
+
+#define WL_FACTOR_TABLE_MAX_LIMIT 5
+
+#define WL_CU_2G_ROAM_TRIGGER (-60)
+#define WL_CU_5G_ROAM_TRIGGER (-70)
+
+#define WL_CU_SCORE_DELTA_DEFAULT 20
+
+#define WL_MAX_CHANNEL_USAGE 0x0FF
+#define WL_CU_PERCENTAGE_DISABLE 0
+#define WL_CU_PERCENTAGE_DEFAULT 70
+#define WL_CU_PERCENTAGE_MAX 100
+#define WL_CU_CALC_DURATION_DEFAULT 10 /* seconds */
+#define WL_CU_CALC_DURATION_MAX 60 /* seconds */
+
+typedef struct wl_roam_prof_v2 {
+	int8	roam_flags;		/**< bit flags */
+	int8	roam_trigger;		/**< RSSI trigger level per profile/RSSI bracket */
+	int8	rssi_lower;
+	int8	roam_delta;
+
+	/* if channel_usage if zero, roam_delta is rssi delta required for new AP */
+	/* if channel_usage if non-zero, roam_delta is score delta(%) required for new AP */
+	int8	rssi_boost_thresh;	/**< Min RSSI to qualify for RSSI boost */
+	int8	rssi_boost_delta;	/**< RSSI boost for AP in the other band */
+	uint16	nfscan;			/**< number of full scan to start with */
+	uint16	fullscan_period;
+	uint16	init_scan_period;
+	uint16	backoff_multiplier;
+	uint16	max_scan_period;
+	uint8	channel_usage;
+	uint8	cu_avg_calc_dur;
+	uint8	pad[2];
+} wl_roam_prof_v2_t;
+
+typedef struct wl_roam_prof_v1 {
+	int8	roam_flags;		/**< bit flags */
+	int8	roam_trigger;		/**< RSSI trigger level per profile/RSSI bracket */
+	int8	rssi_lower;
+	int8	roam_delta;
+
+	/* if channel_usage if zero, roam_delta is rssi delta required for new AP */
+	/* if channel_usage if non-zero, roam_delta is score delta(%) required for new AP */
+	int8	rssi_boost_thresh;	/**< Min RSSI to qualify for RSSI boost */
+	int8	rssi_boost_delta;	/**< RSSI boost for AP in the other band */
+	uint16	nfscan;			/**< number of full scan to start with */
+	uint16	fullscan_period;
+	uint16	init_scan_period;
+	uint16	backoff_multiplier;
+	uint16	max_scan_period;
+} wl_roam_prof_v1_t;
+
+typedef struct wl_roam_prof_band_v2 {
+	uint32	band;			/**< Must be just one band */
+	uint16	ver;			/**< version of this struct */
+	uint16	len;			/**< length in bytes of this structure */
+	wl_roam_prof_v2_t roam_prof[WL_MAX_ROAM_PROF_BRACKETS];
+} wl_roam_prof_band_v2_t;
+
+typedef struct wl_roam_prof_band_v1 {
+	uint32	band;			/**< Must be just one band */
+	uint16	ver;			/**< version of this struct */
+	uint16	len;			/**< length in bytes of this structure */
+	wl_roam_prof_v1_t roam_prof[WL_MAX_ROAM_PROF_BRACKETS];
+} wl_roam_prof_band_v1_t;
+
+#define BSS_MAXTABLE_SIZE 10
+#define WNM_BSS_SELECT_FACTOR_VERSION   1
+typedef struct wnm_bss_select_factor_params {
+	uint8 low;
+	uint8 high;
+	uint8 factor;
+	uint8 pad;
+} wnm_bss_select_factor_params_t;
+
+#define WNM_BSS_SELECT_FIXED_SIZE OFFSETOF(wnm_bss_select_factor_cfg_t, params)
+typedef struct wnm_bss_select_factor_cfg {
+	uint8 version;
+	uint8 band;
+	uint16 type;
+	uint16 pad;
+	uint16 count;
+	wnm_bss_select_factor_params_t params[1];
+} wnm_bss_select_factor_cfg_t;
+
+#define WNM_BSS_SELECT_WEIGHT_VERSION   1
+typedef struct wnm_bss_select_weight_cfg {
+	uint8 version;
+	uint8 band;
+	uint16 type;
+	uint16 weight; /* weightage for each type between 0 to 100 */
+} wnm_bss_select_weight_cfg_t;
+
+#define WNM_BSS_SELECT_TYPE_RSSI   0
+#define WNM_BSS_SELECT_TYPE_CU   1
+
+#define WNM_BSSLOAD_MONITOR_VERSION   1
+typedef struct wnm_bssload_monitor_cfg {
+	uint8 version;
+	uint8 band;
+	uint8 duration; /* duration between 1 to 20sec */
+} wnm_bssload_monitor_cfg_t;
+
+#define WNM_ROAM_TRIGGER_VERSION   1
+typedef struct wnm_roam_trigger_cfg {
+	uint8 version;
+	uint8 band;
+	uint16 type;
+	int16 trigger; /* trigger for each type in new roam algorithm */
+} wnm_roam_trigger_cfg_t;
+
+/* Data structures for Interface Create/Remove  */
+
+#define WL_INTERFACE_CREATE_VER	(2)
+
+/*
+ * The flags filed of the wl_interface_create is designed to be
+ * a Bit Mask. As of now only Bit 0 and Bit 1 are used as mentioned below.
+ * The rest of the bits can be used, incase we have to provide
+ * more information to the dongle
+ */
+
+/*
+ * Bit 0 of flags field is used to inform whether the interface requested to
+ * be created is STA or AP.
+ * 0 - Create a STA interface
+ * 1 - Create an AP interface
+ * NOTE: This Bit 0 is applicable for the WL_INTERFACE_CREATE_VER < 2
+ */
+#define WL_INTERFACE_CREATE_STA	(0 << 0)
+#define WL_INTERFACE_CREATE_AP	(1 << 0)
+
+/*
+ * From revision >= 2 Bit 0 of flags field will not used be for STA or AP interface creation.
+ * "iftype" field shall be used for identifying the interface type.
+ */
+typedef enum wl_interface_type {
+	WL_INTERFACE_TYPE_STA = 0,
+	WL_INTERFACE_TYPE_AP = 1,
+	WL_INTERFACE_TYPE_AWDL = 2,
+	WL_INTERFACE_TYPE_MAX
+} wl_interface_type_t;
+
+/*
+ * Bit 1 of flags field is used to inform whether MAC is present in the
+ * data structure or not.
+ * 0 - Ignore mac_addr field
+ * 1 - Use the mac_addr field
+ */
+#define WL_INTERFACE_MAC_DONT_USE	(0 << 1)
+#define WL_INTERFACE_MAC_USE		(1 << 1)
+
+/*
+ * Bit 2 of flags field is used to inform whether core or wlc index
+ * is present in the data structure or not.
+ * 0 - Ignore wlc_index field
+ * 1 - Use the wlc_index field
+ */
+#define WL_INTERFACE_WLC_INDEX_DONT_USE	(0 << 2)
+#define WL_INTERFACE_WLC_INDEX_USE	(1 << 2)
+
+typedef struct wl_interface_create {
+	uint16	ver;			/**< version of this struct */
+	uint8	pad1[2];		/**< Padding bytes */
+	uint32  flags;			/**< flags that defines the operation */
+	struct	ether_addr   mac_addr;	/**< Optional Mac address */
+	uint8	iftype;			/**< Type of interface created */
+	uint8	pad2;			/**< Padding bytes */
+	uint32  wlc_index;		/**< Optional wlc index */
+} wl_interface_create_t;
+
+typedef struct wl_interface_info {
+	uint16	ver;			/**< version of this struct */
+	struct ether_addr    mac_addr;	/**< MAC address of the interface */
+	char	ifname[BCM_MSG_IFNAME_MAX]; /**< name of interface */
+	uint8	bsscfgidx;		/**< source bsscfg index */
+} wl_interface_info_t;
+
+#define PHY_RXIQEST_AVERAGING_DELAY 10
+
+typedef struct wl_iqest_params {
+	uint32 rxiq;
+	uint8 niter;
+	uint8 delay;
+} wl_iqest_params_t;
+
+typedef struct wl_iqest_sweep_params {
+	wl_iqest_params_t params;
+	uint8 nchannels;
+	uint8 channel[1];
+} wl_iqest_sweep_params_t;
+
+typedef struct wl_iqest_value {
+	uint8 channel;
+	uint32 rxiq;
+} wl_iqest_value_t;
+
+typedef struct wl_iqest_result {
+	uint8 nvalues;
+	wl_iqest_value_t value[1];
+} wl_iqest_result_t;
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/* BTCX AIBSS (Oxygen) Status */
+typedef struct wlc_btc_aibss_info {
+	uint32	prev_tsf_l;		// Lower 32 bits of last read of TSF
+	uint32	prev_tsf_h;		// Higher 32 bits of last read of TSF
+	uint32	last_btinfo;		// Last read of BT info
+	uint32	local_btinfo;		// Local BT INFO BitMap
+	uint8	bt_out_of_sync_cnt;	// BT not in sync with strobe
+	uint8	esco_off_cnt;		// Count incremented when ESCO is off
+	uint8	strobe_enabled;		// Set only in AIBSS mode
+	uint8	strobe_on;		// strobe to BT is on for Oxygen
+	uint8	local_bt_in_sync;	// Sync status of local BT when strobe is on
+	uint8	other_bt_in_sync;	// Sync state of BT in other devices in AIBSS
+	uint8	local_bt_is_master;	// Local BT is master
+	uint8	sco_prot_on;		// eSCO Protection on in local device
+	uint8	other_esco_present;	// eSCO status in other devices in AIBSS
+	uint8	rx_agg_change;		// Indicates Rx Agg size needs to change
+	uint8	rx_agg_modified;	// Rx Agg size modified
+	uint8	acl_grant_set;		// ACL grants on for speeding up sync
+	uint8	write_ie_err_cnt;	// BTCX Ie write error cnt
+	uint8	parse_ie_err_cnt;	// BTCX IE parse error cnt
+	uint8	wci2_fail_cnt;		// WCI2 init failure cnt
+	uint8	strobe_enable_err_cnt;	// Strobe enable err cnt
+	uint8	strobe_init_err_cnt;	// Strobe init err cnt
+	uint8	tsf_jump_cnt;		// TSF jump cnt
+	uint8	acl_grant_cnt;		// ALC grant cnt
+	uint8	pad1;
+	uint16	ibss_tsf_shm;		// SHM address of strobe TSF
+	uint16	pad2;
+} wlc_btc_aibss_info_t;
+
+#define WLC_BTC_AIBSS_STATUS_VER	1
+#define WLC_BTC_AIBSS_STATUS_LEN	(sizeof(wlc_btc_aibss_status_t) - 2 * (sizeof(uint16)))
+
+typedef struct wlc_btc_aibss_status {
+	uint16	version;		// Version #
+	uint16	len;			// Length of the structure(excluding len & version)
+	int32	mode;			// Current value of btc_mode
+	uint16	bth_period;             // bt coex period. read from shm.
+	uint16	agg_off_bm;		// AGG OFF BM read from SHM
+	uint8	bth_active;             // bt active session
+	uint8	pad[3];
+	wlc_btc_aibss_info_t aibss_info;	// Structure definition above
+} wlc_btc_aibss_status_t;
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+typedef enum {
+	STATE_NONE = 0,
+
+	/* WLAN -> BT */
+	W2B_DATA_SET = 21,
+	B2W_ACK_SET = 22,
+	W2B_DATA_CLEAR = 23,
+	B2W_ACK_CLEAR = 24,
+
+	/* BT -> WLAN */
+	B2W_DATA_SET = 31,
+	W2B_ACK_SET = 32,
+	B2W_DATA_CLEAR = 33,
+	W2B_ACK_CLEAR = 34
+} bwte_gci_intstate_t;
+
+#define WL_BWTE_STATS_VERSION 1 /* version of bwte_stats_t */
+typedef struct {
+	uint32 version;
+
+	bwte_gci_intstate_t inttobt;
+	bwte_gci_intstate_t intfrombt;
+
+	uint32 bt2wl_intrcnt; /* bt->wlan interrrupt count */
+	uint32 wl2bt_intrcnt; /* wlan->bt interrupt count  */
+
+	uint32 wl2bt_dset_cnt;
+	uint32 wl2bt_dclear_cnt;
+	uint32 wl2bt_aset_cnt;
+	uint32 wl2bt_aclear_cnt;
+
+	uint32 bt2wl_dset_cnt;
+	uint32 bt2wl_dclear_cnt;
+	uint32 bt2wl_aset_cnt;
+	uint32 bt2wl_aclear_cnt;
+
+	uint32 state_error_1;
+	uint32 state_error_2;
+	uint32 state_error_3;
+	uint32 state_error_4;
+} bwte_stats_t;
+
+#define TBOW_MAX_SSID_LEN        32
+#define TBOW_MAX_PASSPHRASE_LEN  63
+
+#define WL_TBOW_SETUPINFO_T_VERSION 1 /* version of tbow_setup_netinfo_t */
+typedef struct tbow_setup_netinfo {
+	uint32 version;
+	uint8 opmode;
+	uint8 pad;
+	uint8 macaddr[ETHER_ADDR_LEN];
+	uint32 ssid_len;
+	uint8 ssid[TBOW_MAX_SSID_LEN];
+	uint8 passphrase_len;
+	uint8 passphrase[TBOW_MAX_PASSPHRASE_LEN];
+	chanspec_t chanspec;
+	uint32 channel;
+} tbow_setup_netinfo_t;
+
+typedef enum tbow_ho_opmode {
+	TBOW_HO_MODE_START_GO = 0,
+	TBOW_HO_MODE_START_STA,
+	TBOW_HO_MODE_START_GC,
+	TBOW_HO_MODE_TEST_GO,
+	TBOW_HO_MODE_STOP_GO = 0x10,
+	TBOW_HO_MODE_STOP_STA,
+	TBOW_HO_MODE_STOP_GC,
+	TBOW_HO_MODE_TEARDOWN
+} tbow_ho_opmode_t;
+
+/* Beacon trim feature statistics */
+/* configuration */
+#define BCNTRIMST_PER			0	/**< Number of beacons to trim (0: disable) */
+#define BCNTRIMST_TIMEND		1	/**< Number of bytes till TIM IE */
+#define BCNTRIMST_TSFLMT		2	/**< TSF tolerance value (usecs) */
+/* internal use */
+#define BCNTRIMST_CUR			3	/**< PSM's local beacon trim counter */
+#define BCNTRIMST_PREVLEN		4	/**< Beacon length excluding the TIM IE */
+#define BCNTRIMST_TIMLEN		5	/**< TIM IE Length */
+#define BCNTRIMST_RSSI			6	/**< Partial beacon RSSI */
+#define BCNTRIMST_CHAN			7	/**< Partial beacon channel */
+/* debug stat (off by default) */
+#define BCNTRIMST_DUR			8	/**< RX duration until beacon trimmed */
+#define BCNTRIMST_RXMBSS		9	/**< MYBSSID beacon received */
+#define BCNTRIMST_CANTRIM		10	/**< # beacons which were trimmed */
+#define BCNTRIMST_LENCHG		11	/**< # beacons not trimmed due to length change */
+#define BCNTRIMST_TSFDRF		12	/**< # beacons not trimmed due to large TSF delta */
+#define BCNTRIMST_NOTIM			13	/**< # beacons not trimmed due to TIM missing */
+
+#define BCNTRIMST_NUM			14
+
+/* --------------  TX Power Cap --------------- */
+#define TXPWRCAP_MAX_NUM_CORES 8
+#define TXPWRCAP_MAX_NUM_ANTENNAS (TXPWRCAP_MAX_NUM_CORES * 2)
+
+#define TXPWRCAP_NUM_SUBBANDS 5
+
+/* IOVAR txcapconfig enum's */
+#define TXPWRCAPCONFIG_WCI2 0
+#define TXPWRCAPCONFIG_HOST 1
+#define TXPWRCAPCONFIG_WCI2_AND_HOST 2
+
+/* IOVAR txcapstate enum's */
+#define TXPWRCAPSTATE_LOW_CAP  0
+#define TXPWRCAPSTATE_HIGH_CAP 1
+#define TXPWRCAPSTATE_HOST_LOW_WCI2_LOW_CAP	0
+#define TXPWRCAPSTATE_HOST_LOW_WCI2_HIGH_CAP	1
+#define TXPWRCAPSTATE_HOST_HIGH_WCI2_LOW_CAP	2
+#define TXPWRCAPSTATE_HOST_HIGH_WCI2_HIGH_CAP	3
+
+/* IOVAR txcapconfig and txcapstate structure is shared: SET and GET */
+#define TXPWRCAPCTL_VERSION 2
+typedef struct wl_txpwrcap_ctl {
+	uint8   version;
+	uint8   ctl[TXPWRCAP_NUM_SUBBANDS];
+} wl_txpwrcap_ctl_t;
+
+/* IOVAR txcapdump structure: GET only */
+#define TXPWRCAP_DUMP_VERSION 2
+typedef struct wl_txpwrcap_dump {
+	uint8   version;
+	uint8	pad0;
+	uint8   current_country[2];
+	uint32	current_channel;
+	uint8   config[TXPWRCAP_NUM_SUBBANDS];
+	uint8   state[TXPWRCAP_NUM_SUBBANDS];
+	uint8	high_cap_state_enabled;
+	uint8	wci2_cell_status_last;
+	uint8   download_present;
+	uint8	num_subbands;
+	uint8	num_antennas;
+	uint8   num_antennas_per_core[TXPWRCAP_MAX_NUM_CORES];
+	uint8	num_cc_groups;
+	uint8   current_country_cc_group_info_index;
+	int8    low_cap[TXPWRCAP_MAX_NUM_ANTENNAS*TXPWRCAP_NUM_SUBBANDS];
+	int8    high_cap[TXPWRCAP_MAX_NUM_ANTENNAS*TXPWRCAP_NUM_SUBBANDS];
+} wl_txpwrcap_dump_t;
+
+typedef struct wl_txpwrcap_dump_v3 {
+	uint8   version;
+	uint8	pad0;
+	uint8   current_country[2];
+	uint32	current_channel;
+	uint8   config[TXPWRCAP_NUM_SUBBANDS];
+	uint8   state[TXPWRCAP_NUM_SUBBANDS];
+	uint8	high_cap_state_enabled;
+	uint8	wci2_cell_status_last;
+	uint8   download_present;
+	uint8	num_subbands;
+	uint8	num_antennas;
+	uint8   num_antennas_per_core[TXPWRCAP_MAX_NUM_CORES];
+	uint8	num_cc_groups;
+	uint8   current_country_cc_group_info_index;
+	uint8	cap_states_per_cc_group;
+	int8    host_low_wci2_low_cap[TXPWRCAP_MAX_NUM_ANTENNAS*TXPWRCAP_NUM_SUBBANDS];
+	int8    host_low_wci2_high_cap[TXPWRCAP_MAX_NUM_ANTENNAS*TXPWRCAP_NUM_SUBBANDS];
+	int8    host_high_wci2_low_cap[TXPWRCAP_MAX_NUM_ANTENNAS*TXPWRCAP_NUM_SUBBANDS];
+	int8    host_high_wci2_high_cap[TXPWRCAP_MAX_NUM_ANTENNAS*TXPWRCAP_NUM_SUBBANDS];
+} wl_txpwrcap_dump_v3_t;
+
+typedef struct wl_txpwrcap_tbl {
+	uint8 num_antennas_per_core[TXPWRCAP_MAX_NUM_CORES];
+	/* Stores values for valid antennas */
+	int8 pwrcap_cell_on[TXPWRCAP_MAX_NUM_ANTENNAS]; /* qdBm units */
+	int8 pwrcap_cell_off[TXPWRCAP_MAX_NUM_ANTENNAS]; /* qdBm units */
+} wl_txpwrcap_tbl_t;
+
+/* ##### Ecounters section ##### */
+#define ECOUNTERS_VERSION_1	1
+
+/* Input structure for ecounters IOVAR */
+typedef struct ecounters_config_request {
+	uint16 version;		/* config version */
+	uint16 set;		/* Set where data will go. */
+	uint16 size;		/* Size of the set. */
+	uint16 timeout;		/* timeout in seconds. */
+	uint16 num_events;	/* Number of events to report. */
+	uint16 ntypes;		/* Number of entries in type array. */
+	uint16 type[1];		/* Statistics Types (tags) to retrieve. */
+} ecounters_config_request_t;
+
+#define ECOUNTERS_EVENTMSGS_VERSION_1		1
+#define ECOUNTERS_TRIGGER_CONFIG_VERSION_1	1
+
+#define ECOUNTERS_EVENTMSGS_EXT_MASK_OFFSET	\
+		OFFSETOF(ecounters_eventmsgs_ext_t, mask[0])
+
+#define ECOUNTERS_TRIG_CONFIG_TYPE_OFFSET	\
+		OFFSETOF(ecounters_trigger_config_t, type[0])
+
+typedef struct ecounters_eventmsgs_ext {
+	uint8 version;
+	uint8 len;
+	uint8 mask[1];
+} ecounters_eventmsgs_ext_t;
+
+typedef struct ecounters_trigger_config {
+	uint16 version;		/* version */
+	uint16 set;		/* set where data should go */
+	uint16 rsvd;		/* reserved */
+	uint16 pad;		/* pad/reserved */
+	uint16 ntypes;		/* number of types/tags */
+	uint16 type[1];		/* list of types */
+} ecounters_trigger_config_t;
+
+#define ECOUNTERS_TRIGGER_REASON_VERSION_1	1
+/* Triggered due to timer based ecounters */
+#define ECOUNTERS_TRIGGER_REASON_TIMER		0
+/* Triggered due to event based configuration */
+#define ECOUNTERS_TRIGGER_REASON_EVENTS		1
+#define ECOUNTERS_TRIGGER_REASON_MAX		1
+
+typedef struct ecounters_trigger_reason {
+	uint16 version;			/* version */
+	uint16 trigger_reason;		/* trigger reason */
+	uint32 sub_reason_code;		/* sub reason code */
+	uint32 trigger_time_now;	/* time in ms  at trigger */
+	uint32 host_ref_time;		/* host ref time */
+} ecounters_trigger_reason_t;
+
+/* -------------- dynamic BTCOEX --------------- */
+#define DCTL_TROWS	2			/**< currently practical number of rows  */
+#define DCTL_TROWS_MAX	4			/**<  2 extra rows RFU */
+/* DYNCTL profile flags */
+#define DCTL_FLAGS_DISABLED	0		/**< default value: all features disabled */
+#define DCTL_FLAGS_DYNCTL	(1 << 0)	/**<  1 - enabled, 0 - legacy only */
+#define DCTL_FLAGS_DESENSE	(1 << 1)	/**< auto desense is enabled */
+#define DCTL_FLAGS_MSWITCH	(1 << 2)	/**< mode switching is enabled */
+/* for now AGG on/off is handled separately  */
+#define DCTL_FLAGS_TX_AGG_OFF	(1 << 3)	/**< TBD: allow TX agg Off */
+#define DCTL_FLAGS_RX_AGG_OFF	(1 << 4)	/**< TBD: allow RX agg Off */
+/* used for dry run testing only */
+#define DCTL_FLAGS_DRYRUN	(1 << 7)	/**< Enables dynctl dry run mode  */
+#define IS_DYNCTL_ON(prof)	((prof->flags & DCTL_FLAGS_DYNCTL) != 0)
+#define IS_DESENSE_ON(prof)	((prof->flags & DCTL_FLAGS_DESENSE) != 0)
+#define IS_MSWITCH_ON(prof)	((prof->flags & DCTL_FLAGS_MSWITCH) != 0)
+/* desense level currently in use */
+#define DESENSE_OFF	0
+#define DFLT_DESENSE_MID	12
+#define DFLT_DESENSE_HIGH	2
+
+/**
+ * dynctl data points(a set of btpwr & wlrssi thresholds)
+ * for mode & desense switching
+ */
+typedef struct btc_thr_data {
+	int8	mode;	/**< used by desense sw */
+	int8	bt_pwr;	/**< BT tx power threshold */
+	int8	bt_rssi;	/**< BT rssi threshold */
+	/* wl rssi range when mode or desense change may be needed */
+	int8	wl_rssi_high;
+	int8	wl_rssi_low;
+} btc_thr_data_t;
+
+/* dynctl. profile data structure  */
+#define DCTL_PROFILE_VER 0x01
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct  dctl_prof {
+	uint8 version;  /**< dynctl profile version */
+	/* dynctl profile flags bit:0 - dynctl On, bit:1 dsns On, bit:2 mode sw On, */
+	uint8 flags;  /**< bit[6:3] reserved, bit7 - Dryrun (sim) - On */
+	/**  wl desense levels to apply */
+	uint8	dflt_dsns_level;
+	uint8	low_dsns_level;
+	uint8	mid_dsns_level;
+	uint8	high_dsns_level;
+	/** mode switching hysteresis in dBm */
+	int8	msw_btrssi_hyster;
+	/** default btcoex mode */
+	uint8	default_btc_mode;
+	/** num of active rows in mode switching table */
+	uint8	msw_rows;
+	/** num of rows in desense table */
+	uint8	dsns_rows;
+	/** dynctl mode switching data table  */
+	btc_thr_data_t msw_data[DCTL_TROWS_MAX];
+	/** dynctl desense switching data table */
+	btc_thr_data_t dsns_data[DCTL_TROWS_MAX];
+} BWL_POST_PACKED_STRUCT dctl_prof_t;
+#include <packed_section_end.h>
+
+/**  dynctl status info */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct  dynctl_status {
+	uint8 sim_on;	/**< true if simulation is On */
+	uint16	bt_pwr_shm; /**< BT per/task power as read from ucode  */
+	int8	bt_pwr;		/**< BT pwr extracted & converted to dBm */
+	int8	bt_rssi;	/**< BT rssi in dBm */
+	int8	wl_rssi;	/**< last wl rssi reading used by btcoex */
+	uint8	dsns_level; /**< current desense level */
+	uint8	btc_mode;   /**< current btcoex mode */
+	/* add more status items if needed,  pad to 4 BB if needed */
+} BWL_POST_PACKED_STRUCT dynctl_status_t;
+#include <packed_section_end.h>
+
+/**  dynctl simulation (dryrun data) */
+#include <packed_section_start.h>
+typedef BWL_PRE_PACKED_STRUCT struct  dynctl_sim {
+	uint8 sim_on;	/**< simulation mode on/off */
+	int8 btpwr;		/**< simulated BT power in dBm */
+	int8 btrssi;	/**< simulated BT rssi in dBm */
+	int8 wlrssi;	/**< simulated WL rssi in dBm */
+} BWL_POST_PACKED_STRUCT dynctl_sim_t;
+/* no default structure packing */
+#include <packed_section_end.h>
+
+/** PTK key maintained per SCB */
+#define RSN_TEMP_ENCR_KEY_LEN 16
+typedef struct wpa_ptk {
+	uint8 kck[RSN_KCK_LENGTH]; /**< EAPOL-Key Key Confirmation Key (KCK) */
+	uint8 kek[RSN_KEK_LENGTH]; /**< EAPOL-Key Key Encryption Key (KEK) */
+	uint8 tk1[RSN_TEMP_ENCR_KEY_LEN]; /**< Temporal Key 1 (TK1) */
+	uint8 tk2[RSN_TEMP_ENCR_KEY_LEN]; /**< Temporal Key 2 (TK2) */
+} wpa_ptk_t;
+
+/** GTK key maintained per SCB */
+typedef struct wpa_gtk {
+	uint32 idx;
+	uint32 key_len;
+	uint8  key[DOT11_MAX_KEY_SIZE];
+} wpa_gtk_t;
+
+/** FBT Auth Response Data structure */
+typedef struct wlc_fbt_auth_resp {
+	uint8 macaddr[ETHER_ADDR_LEN]; /**< station mac address */
+	uint8 pad[2];
+	uint8 pmk_r1_name[WPA2_PMKID_LEN];
+	wpa_ptk_t ptk; /**< pairwise key */
+	wpa_gtk_t gtk; /**< group key */
+	uint32 ie_len;
+	uint8 status;  /**< Status of parsing FBT authentication
+					Request in application
+					*/
+	uint8 ies[1]; /**< IEs contains MDIE, RSNIE,
+					FBTIE (ANonce, SNonce,R0KH-ID, R1KH-ID)
+					*/
+} wlc_fbt_auth_resp_t;
+
+/** FBT Action Response frame */
+typedef struct wlc_fbt_action_resp {
+	uint16 version; /**< structure version */
+	uint16 length; /**< length of structure */
+	uint8 macaddr[ETHER_ADDR_LEN]; /**< station mac address */
+	uint8 data_len;  /**< len of ie from Category */
+	uint8 data[1]; /**< data contains category, action, sta address, target ap,
+						status code,fbt response frame body
+						*/
+} wlc_fbt_action_resp_t;
+
+#define MACDBG_PMAC_ADDR_INPUT_MAXNUM 16
+#define MACDBG_PMAC_OBJ_TYPE_LEN 8
+
+typedef struct _wl_macdbg_pmac_param_t {
+	char type[MACDBG_PMAC_OBJ_TYPE_LEN];
+	uint8 step;
+	uint8 w_en;
+	uint16 num;
+	uint32 bitmap;
+	uint8 addr_raw;
+	uint8 addr_num;
+	uint16 addr[MACDBG_PMAC_ADDR_INPUT_MAXNUM];
+	uint8 pad0[2];
+	uint32 w_val;
+} wl_macdbg_pmac_param_t;
+
+/** IOVAR 'svmp_sampcol' parameter. Used to set and read SVMP_SAMPLE_COLLECT's setting */
+typedef struct wl_svmp_sampcol_param {
+	uint32 version;           /* version */
+	uint8  enable;
+	uint8  trigger_mode;      /* SVMP_SAMPCOL_TRIGGER */
+	uint8  trigger_mode_s[2]; /* SVMP_SAMPCOL_PKTPROC */
+	uint8  data_samplerate;   /* SVMP_SAMPCOL_SAMPLERATE */
+	uint8  data_sel_phy1;     /* SVMP_SAMPCOL_PHY1MUX */
+	uint8  data_sel_rx1;      /* SVMP_SAMPCOL_RX1MUX without iqCompOut */
+	uint8  data_sel_dualcap;  /* SVMP_SAMPCOL_RX1MUX */
+	uint8  pack_mode;         /* SVMP_SAMPCOL_PACK */
+	uint8  pack_order;
+	uint8  pack_cfix_fmt;
+	uint8  pack_1core_sel;
+	uint16 waitcnt;
+	uint16 caplen;
+	uint32 buff_addr_start;   /* in word-size (2-bytes) */
+	uint32 buff_addr_end;     /* note: Tcl in byte-size, HW in vector-size (8-bytes) */
+	uint8  int2vasip;
+	uint16 status;
+} wl_svmp_sampcol_t;
+
+#define WL_SVMP_SAMPCOL_PARAMS_VERSION	1
+
+enum {
+	SVMP_SAMPCOL_TRIGGER_PKTPROC_TRANSITION = 0,
+	SVMP_SAMPCOL_TRIGGER_FORCE_IMMEDIATE,
+	SVMP_SAMPCOL_TRIGGER_RADAR_DET
+};
+
+enum {
+	SVMP_SAMPCOL_PHY1MUX_GPIOOUT = 0,
+	SVMP_SAMPCOL_PHY1MUX_FFT,
+	SVMP_SAMPCOL_PHY1MUX_DBGHX,
+	SVMP_SAMPCOL_PHY1MUX_RX1MUX
+};
+
+enum {
+	SVMP_SAMPCOL_RX1MUX_FARROWOUT = 4,
+	SVMP_SAMPCOL_RX1MUX_IQCOMPOUT,
+	SVMP_SAMPCOL_RX1MUX_DCFILTEROUT,
+	SVMP_SAMPCOL_RX1MUX_RXFILTEROUT,
+	SVMP_SAMPCOL_RX1MUX_ACIFILTEROUT
+};
+
+enum {
+	SVMP_SAMPCOL_SAMPLERATE_1XBW = 0,
+	SVMP_SAMPCOL_SAMPLERATE_2XBW
+};
+
+enum {
+	SVMP_SAMPCOL_PACK_DUALCAP = 0,
+	SVMP_SAMPCOL_PACK_4CORE,
+	SVMP_SAMPCOL_PACK_2CORE,
+	SVMP_SAMPCOL_PACK_1CORE
+};
+
+enum {
+	SVMP_SAMPCOL_PKTPROC_RESET = 0,
+	SVMP_SAMPCOL_PKTPROC_CARRIER_SEARCH,
+	SVMP_SAMPCOL_PKTPROC_WAIT_FOR_NB_PWR,
+	SVMP_SAMPCOL_PKTPROC_WAIT_FOR_W1_PWR,
+	SVMP_SAMPCOL_PKTPROC_WAIT_FOR_W2_PWR,
+	SVMP_SAMPCOL_PKTPROC_OFDM_PHY,
+	SVMP_SAMPCOL_PKTPROC_TIMING_SEARCH,
+	SVMP_SAMPCOL_PKTPROC_CHAN_EST_1,
+	SVMP_SAMPCOL_PKTPROC_LEG_SIG_DEC,
+	SVMP_SAMPCOL_PKTPROC_SIG_DECODE_1,
+	SVMP_SAMPCOL_PKTPROC_SIG_DECODE_2,
+	SVMP_SAMPCOL_PKTPROC_HT_AGC,
+	SVMP_SAMPCOL_PKTPROC_CHAN_EST_2,
+	SVMP_SAMPCOL_PKTPROC_PAY_DECODE,
+	SVMP_SAMPCOL_PKTPROC_DSSS_CCK_PHY,
+	SVMP_SAMPCOL_PKTPROC_WAIT_ENERGY_DROP,
+	SVMP_SAMPCOL_PKTPROC_WAIT_NCLKS,
+	SVMP_SAMPCOL_PKTPROC_PAY_DEC_EXT,
+	SVMP_SAMPCOL_PKTPROC_SIG_FAIL_DELAY,
+	SVMP_SAMPCOL_PKTPROC_RIFS_SEARCH,
+	SVMP_SAMPCOL_PKTPROC_BOARD_SWITCH_DIV_SEARCH,
+	SVMP_SAMPCOL_PKTPROC_DSSS_CCK_BOARD_SWITCH_DIV_SEARCH,
+	SVMP_SAMPCOL_PKTPROC_CHAN_EST_3,
+	SVMP_SAMPCOL_PKTPROC_CHAN_EST_4,
+	SVMP_SAMPCOL_PKTPROC_FINE_TIMING_SEARCH,
+	SVMP_SAMPCOL_PKTPROC_SET_CLIP_GAIN,
+	SVMP_SAMPCOL_PKTPROC_NAP,
+	SVMP_SAMPCOL_PKTPROC_VHT_SIGA_DEC,
+	SVMP_SAMPCOL_PKTPROC_VHT_SIGB_DEC,
+	SVMP_SAMPCOL_PKTPROC_PKT_ABORT,
+	SVMP_SAMPCOL_PKTPROC_DCCAL
+};
+
+/** IOVAR 'svmp_mem' parameter. Used to read/clear svmp memory */
+typedef struct svmp_mem {
+	uint32 addr;	/**< offset to read svmp memory from vasip base address */
+	uint16 len;	/**< length in count of uint16's */
+	uint16 val;	/**< set the range of addr/len with a value */
+} svmp_mem_t;
+
+/** IOVAR 'mu_rate' parameter. read/set mu rate for upto four users */
+#define MU_RATE_CFG_VERSION	1
+typedef struct mu_rate {
+	uint16	version;	/**< version of the structure as defined by MU_RATE_CFG_VERSION */
+	uint16	length;		/**< length of entire structure */
+	uint8	auto_rate;	/**< enable/disable auto rate */
+	uint16	rate_user[4];	/**< rate per each of four users, set to -1 for no change */
+} mu_rate_t;
+
+/** IOVAR 'mu_group' parameter. Used to set and read MU group recommendation setting */
+#define WL_MU_GROUP_AUTO_COMMAND      -1
+#define WL_MU_GROUP_PARAMS_VERSION     3
+#define WL_MU_GROUP_METHOD_NAMELEN    64
+#define WL_MU_GROUP_NGROUP_MAX        15
+#define WL_MU_GROUP_NUSER_MAX          4
+#define WL_MU_GROUP_METHOD_MIN         0
+#define WL_MU_GROUP_NUMBER_AUTO_MIN    1
+#define WL_MU_GROUP_NUMBER_AUTO_MAX   15
+#define WL_MU_GROUP_NUMBER_FORCED_MAX  8
+#define WL_MU_GROUP_METHOD_OLD         0
+#define WL_MU_GROUP_MODE_AUTO          0
+#define WL_MU_GROUP_MODE_FORCED        1
+#define WL_MU_GROUP_FORCED_1GROUP      1
+#define WL_MU_GROUP_ENTRY_EMPTY       -1
+typedef struct mu_group {
+	uint32 version;          /* version */
+	int16  forced;           /* forced group recommendation */
+	int16  forced_group_mcs; /* forced group with mcs */
+	int16  forced_group_num; /* forced group number */
+	int16  group_option[WL_MU_GROUP_NGROUP_MAX][WL_MU_GROUP_NUSER_MAX];
+	                         /* set mode for forced grouping and read mode for auto grouping */
+	int16  group_GID[WL_MU_GROUP_NGROUP_MAX];
+	int16  group_method;     /* methof for VASIP group recommendation */
+	int16  group_number;     /* requested number for VASIP group recommendation */
+	int16  auto_group_num;   /* exact number from VASIP group recommendation */
+	int8   group_method_name[WL_MU_GROUP_METHOD_NAMELEN];
+} mu_group_t;
+
+typedef struct mupkteng_sta {
+    struct ether_addr ea;
+    int32 nrxchain;
+    int32 idx;
+} mupkteng_sta_t;
+
+typedef struct mupkteng_client {
+    int32 rspec;
+    int32 idx;
+    int32 flen;
+    int32 nframes;
+} mupkteng_client_t;
+
+typedef struct mupkteng_tx {
+    mupkteng_client_t client[8];
+    int32 nclients;
+    int32 ntx;
+} mupkteng_tx_t;
+
+/*
+ * MU Packet engine interface.
+ * The following two definitions will go into
+ * components/shared/devctrl_if/wlioctl_defs.h
+ * when wl utility changes are merged to EAGLE TOB & Trunk
+ */
+
+#define WL_MUPKTENG_PER_TX_START		0x10
+#define WL_MUPKTENG_PER_TX_STOP		        0x20
+
+/** IOVAR 'mu_policy' parameter. Used to configure MU admission control policies */
+#define WL_MU_POLICY_PARAMS_VERSION     1
+#define WL_MU_POLICY_SCHED_DEFAULT	60
+#define WL_MU_POLICY_DISABLED		0
+#define WL_MU_POLICY_ENABLED		1
+#define WL_MU_POLICY_NRX_MIN		1
+#define WL_MU_POLICY_NRX_MAX		2
+typedef struct mu_policy {
+	uint16 version;
+	uint16 length;
+	uint32 sched_timer;
+	uint32 pfmon;
+	uint32 pfmon_gpos;
+	uint32 samebw;
+	uint32 nrx;
+	uint32 max_muclients;
+} mu_policy_t;
+
+#define WL_NAN_BAND_STR_SIZE 5       /* sizeof ("auto") */
+
+/** Definitions of different NAN Bands */
+/* do not change the order */
+enum {
+		NAN_BAND_B = 0,
+		NAN_BAND_A,
+		NAN_BAND_AUTO,
+		NAN_BAND_INVALID = 0xFF
+};
+
+#ifdef WL11ULB
+/* ULB Mode configured via "ulb_mode" IOVAR */
+enum {
+    ULB_MODE_DISABLED = 0,
+    ULB_MODE_STD_ALONE_MODE = 1,    /* Standalone ULB Mode */
+    ULB_MODE_DYN_MODE = 2,      /* Dynamic ULB Mode */
+	/* Add all other enums before this */
+    MAX_SUPP_ULB_MODES
+};
+
+/* ULB BWs configured via "ulb_bw" IOVAR during Standalone Mode Only.
+ * Values of this enumeration are also used to specify 'Current Operational Bandwidth'
+ * and 'Primary Operational Bandwidth' sub-fields in 'ULB Operations' field (used in
+ * 'ULB Operations' Attribute or 'ULB Mode Switch' Attribute)
+ */
+typedef enum {
+    ULB_BW_DISABLED = 0,
+    ULB_BW_10MHZ    = 1,    /* Standalone ULB BW in 10 MHz BW */
+    ULB_BW_5MHZ = 2,    /* Standalone ULB BW in 5 MHz BW */
+    ULB_BW_2P5MHZ   = 3,    /* Standalone ULB BW in 2.5 MHz BW */
+	/* Add all other enums before this */
+    MAX_SUPP_ULB_BW
+} ulb_bw_type_t;
+#endif /* WL11ULB */
+
+#ifdef WLMESH
+
+#define WL_MESH_IOCTL_VERSION     1
+#define MESH_IOC_BUFSZ            512 /* sufficient ioc buff size for mesh */
+
+typedef struct mesh_peer_info_ext {
+	mesh_peer_info_t        peer_info;
+	uint8   pad1;
+	uint16  local_aid;      /* AID generated by *local* to peer */
+	uint32  entry_state;    /* see MESH_PEER_ENTRY_STATE_ACTIVE etc; valid
+				* ONLY for internal peering requests
+				*/
+	int8 rssi;
+	uint8 pad2;
+	struct ether_addr ea; /* peer ea */
+} mesh_peer_info_ext_t;
+
+typedef struct mesh_peer_info_dump {
+	uint32 buflen;
+	uint32 version;
+	uint16 count;   /* number of results */
+	uint16 remaining; /* remaining rsults */
+	mesh_peer_info_ext_t    mpi_ext[1];
+} mesh_peer_info_dump_t;
+
+#define WL_MESH_PEER_RES_FIXED_SIZE (sizeof(mesh_peer_info_dump_t) - sizeof(mesh_peer_info_ext_t))
+
+/* container for mesh iovtls & events */
+typedef struct wl_mesh_ioc {
+	uint16  version;        /* interface command or event version */
+	uint16  id;             /* mesh ioctl cmd  ID  */
+	uint16  len;            /* total length of all tlv records in data[]  */
+	uint16  pad;            /* pad to be 32 bit aligment */
+	uint8   data[1];       /* var len payload of bcm_xtlv_t type */
+} wl_mesh_ioc_t;
+
+enum wl_mesh_cmds {
+	WL_MESH_CMD_ENABLE = 1,
+	WL_MESH_CMD_JOIN = 2,
+	WL_MESH_CMD_PEER_STATUS = 3,
+	WL_MESH_CMD_ADD_ROUTE = 4,
+	WL_MESH_CMD_DEL_ROUTE = 5,
+	WL_MESH_CMD_ADD_FILTER = 6,
+	WL_MESH_CMD_ENAB_AL_METRIC = 7
+};
+
+enum wl_mesh_cmd_xtlv_id {
+	WL_MESH_XTLV_ENABLE = 1,
+	WL_MESH_XTLV_JOIN = 2,
+	WL_MESH_XTLV_STATUS = 3,
+	WL_MESH_XTLV_ADD_ROUTE = 4,
+	WL_MESH_XTLV_DEL_ROUTE = 5,
+	WL_MESH_XTLV_ADD_FILTER = 6,
+	WL_MESH_XTLV_ENAB_AIRLINK = 7
+};
+
+#endif /* WLMESH */
+
+/* Fast BSS Transition parameter configuration */
+#define FBT_PARAM_CURRENT_VERSION 0
+
+typedef struct _wl_fbt_params {
+	uint16	version;		/* version of the structure
+					* as defined by FBT_PARAM_CURRENT_VERSION
+					*/
+	uint16	length;			/* length of the entire structure */
+
+	uint16 param_type;		/* type of parameter defined below */
+	uint16 param_len;		/* length of the param_value */
+	uint8 param_value[1];		/* variable length */
+} wl_fbt_params_t;
+
+#define WL_FBT_PARAM_TYPE_RSNIE			0
+#define WL_FBT_PARAM_TYPE_FTIE			0x1
+#define WL_FBT_PARAM_TYPE_SNONCE		0x2
+#define WL_FBT_PARAM_TYPE_MDE			0x3
+#define WL_FBT_PARAM_TYPE_PMK_R0_NAME		0x4
+#define WL_FBT_PARAM_TYPE_R0_KHID		0x5
+#define WL_FBT_PARAM_TYPE_R1_KHID		0x6
+#define WL_FBT_PARAM_TYPE_FIRST_INVALID		0x7
+
+/* Assoc Mgr commands for fine control of assoc */
+#define WL_ASSOC_MGR_CURRENT_VERSION  0x0
+
+typedef struct {
+	uint16	version;		/* version of the structure as
+					 * defined by WL_ASSOC_MGR_CURRENT_VERSION
+					 */
+	uint16	length;			/* length of the entire structure */
+
+	uint16 cmd;
+	uint16 params;
+} wl_assoc_mgr_cmd_t;
+
+#define WL_ASSOC_MGR_CMD_PAUSE_ON_EVT		0 /* have assoc pause on certain events */
+#define WL_ASSOC_MGR_CMD_ABORT_ASSOC		1
+
+#define WL_ASSOC_MGR_PARAMS_EVENT_NONE			0 /* use this to resume as well as clear */
+#define WL_ASSOC_MGR_PARAMS_PAUSE_EVENT_AUTH_RESP	1
+
+#define WL_WINVER_STRUCT_VER_1 (1)
+
+typedef struct wl_winver {
+
+	/* Version and length of this structure. Length includes all fields in wl_winver_t */
+	uint16 struct_version;
+	uint16 struct_length;
+
+	/* Windows operating system version info (Microsoft provided) */
+	struct {
+		uint32 major_ver;
+		uint32 minor_ver;
+		uint32 build;
+	} os_runtime;
+
+	/* NDIS runtime version (Microsoft provided) */
+	struct {
+		uint16 major_ver;
+		uint16 minor_ver;
+	} ndis_runtime;
+
+	/* NDIS Driver version (Broadcom provided) */
+	struct {
+		uint16 major_ver;
+		uint16 minor_ver;
+	} ndis_driver;
+
+	/* WDI Upper Edge (UE) Driver version (Microsoft provided) */
+	struct {
+	uint8 major_ver;
+		uint8 minor_ver;
+		uint8 suffix;
+	} wdi_ue;
+
+	/* WDI Lower Edge (LE) Driver version (Broadcom provided) */
+	struct {
+		uint8 major_ver;
+		uint8 minor_ver;
+		uint8 suffix;
+	} wdi_le;
+
+} wl_winver_t;
+
+#if defined(WLRCC) || defined(ROAM_CHANNEL_CACHE)
+#define MAX_ROAM_CHANNEL      20
+typedef struct {
+	int32 n;
+	chanspec_t channels[MAX_ROAM_CHANNEL];
+} wl_roam_channel_list_t;
+#endif /* RCC || ROAM_CHANNEL_CACHE */
+
+#ifdef MFP
+/* values for IOV_MFP arg */
+enum {
+    WL_MFP_NONE = 0,
+    WL_MFP_CAPABLE,
+    WL_MFP_REQUIRED
+};
+#endif /* MFP */
+
+typedef enum {
+	CHANSW_UNKNOWN = 0,	/* channel switch due to unknown reason */
+	CHANSW_SCAN = 1,	/* channel switch due to scan */
+	CHANSW_PHYCAL = 2,	/* channel switch due to phy calibration */
+	CHANSW_INIT = 3,	/* channel set at WLC up time */
+	CHANSW_ASSOC = 4,	/* channel switch due to association */
+	CHANSW_ROAM = 5,	/* channel switch due to roam */
+	CHANSW_MCHAN = 6,	/* channel switch triggered by mchan module */
+	CHANSW_IOVAR = 7,	/* channel switch due to IOVAR */
+	CHANSW_CSA_DFS = 8,	/* channel switch due to chan switch  announcement from AP */
+	CHANSW_APCS = 9,	/* Channel switch from AP channel select module */
+	CHANSW_AWDL = 10,	/* channel switch due to AWDL */
+	CHANSW_FBT = 11,	/* Channel switch from FBT module for action frame response */
+	CHANSW_UPDBW = 12,	/* channel switch at update bandwidth */
+	CHANSW_ULB = 13,	/* channel switch at ULB */
+	CHANSW_LAST = 14	/* last channel switch reason */
+} chansw_reason_t;
+
+/*
+ * WOWL unassociated mode power svae pattern.
+ */
+typedef struct wowl_radio_duty_cycle {
+	uint16 wake_interval;
+	uint16  sleep_interval;
+} wowl_radio_duty_cycle_t;
+
+typedef struct nd_ra_ol_limits {
+	uint16 version;         /* version of the iovar buffer */
+	uint16 type;            /* type of data provided */
+	uint16 length;          /* length of the entire structure */
+	uint16 pad1;            /* pad union to 4 byte boundary */
+	union {
+		struct {
+			uint16 min_time;         /* seconds, min time for RA offload hold */
+			uint16 lifetime_percent;
+			/* percent, lifetime percentage for offload hold time */
+		} lifetime_relative;
+		struct {
+			uint16 hold_time;        /* seconds, RA offload hold time */
+			uint16 pad2;             /* unused */
+		} fixed;
+	} limits;
+} nd_ra_ol_limits_t;
+
+#define ND_RA_OL_LIMITS_VER 1
+
+/* nd_ra_ol_limits sub-types */
+#define ND_RA_OL_LIMITS_REL_TYPE   0     /* relative, percent of RA lifetime */
+#define ND_RA_OL_LIMITS_FIXED_TYPE 1     /* fixed time */
+
+/* buffer lengths for the different nd_ra_ol_limits types */
+#define ND_RA_OL_LIMITS_REL_TYPE_LEN   12
+#define ND_RA_OL_LIMITS_FIXED_TYPE_LEN  10
+
+/*
+ * Temperature Throttling control mode
+ */
+typedef struct wl_temp_control {
+	uint8 enable;
+	uint16 control_bit;
+} wl_temp_control_t;
+
+
+/* Data structures for rsdb caps */
+
+#define WL_RSDB_CAPS_VER 2
+
+/*
+ * The flags field of the rsdb_caps_response is designed to be
+ * a Bit Mask. As of now only Bit 0 is used as mentioned below.
+ */
+
+/* Bit-0 in flags is used to indicate if the cores can operate synchronously
+* i.e either as 2x2 MIMO or 2(1x1 SISO). This is true only for 4349 variants
+* 0 - device can operate only in rsdb mode (eg: 4364)
+* 1 - device can operate in both rsdb and mimo (eg : 4359 variants)
+*/
+
+#define SYNCHRONOUS_OPERATION_TRUE	(1 << 0)
+#define WL_RSDB_CAPS_FIXED_LEN  OFFSETOF(rsdb_caps_response_t, num_chains)
+
+typedef struct rsdb_caps_response {
+	uint8 ver;		/* Version */
+	uint8 len;		/* length of this structure excluding ver and len */
+	uint8 rsdb;		/* TRUE for rsdb chip */
+	uint8 num_of_cores;	/* no of d11 cores */
+	uint16 flags;		/* Flags to indicate various capabilities */
+	uint8 num_chains[1];	/* Tx/Rx chains for each core */
+} rsdb_caps_response_t;
+
+/* Data structures for rsdb bands */
+#define WL_RSDB_BANDS_VER       2
+#define WL_RSDB_BANDS_FIXED_LEN  OFFSETOF(rsdb_bands_t, band)
+
+typedef struct rsdb_bands
+{
+	uint8 ver;		/* Version of the iovar */
+	uint8 len;		/* Length of this structure excluding ver and len */
+	uint16 num_cores;	/* num of band-core map information */
+	int16 band[1];		/* The band operating on each of the d11 cores */
+} rsdb_bands_t;
+
+
+typedef struct sim_pm_params {
+	uint32 enabled;
+	uint16 cycle;
+	uint16 up;
+} sim_pm_params_t;
+
+/* Bits for fw_status */
+#define NAP_DISABLED_HOST		0x01   /* Host has disabled through nap_enable */
+#define NAP_DISABLED_RSSI		0x02   /* Disabled because of nap_rssi_threshold */
+
+/* Bits for hw_status */
+#define NAP_HWCFG			0x01   /* State of NAP config bit in phy HW */
+
+#ifdef WL_NATOE
+
+#define WL_NATOE_IOCTL_VERSION		1
+#define WL_NATOE_IOC_BUFSZ		512	/* sufficient ioc buff size for natoe */
+#define WL_NATOE_DBG_STATS_BUFSZ	2048
+
+/* config natoe STA and AP IP's structure */
+typedef struct {
+	uint32 sta_ip;
+	uint32 sta_netmask;
+	uint32 sta_router_ip;
+	uint32 sta_dnsip;
+	uint32 ap_ip;
+	uint32 ap_netmask;
+} wl_natoe_config_ips_t;
+
+/* natoe ports config structure */
+typedef struct {
+	uint16 start_port_num;
+	uint16 no_of_ports;
+} wl_natoe_ports_config_t;
+
+/* natoe ports exception info */
+typedef struct {
+	uint16 sta_port_num;
+	uint16 dst_port_num;    /* for SIP type protocol, dst_port_num info can be ignored by FW */
+	uint32 ip;              /* for SIP ip is APcli_ip and for port clash it is dst_ip */
+	uint8  entry_type;      /* Create/Destroy */
+	uint8  pad;
+} wl_natoe_exception_port_t;
+
+/* container for natoe ioctls & events */
+typedef struct wl_natoe_ioc {
+	uint16  version;        /* interface command or event version */
+	uint16  id;             /* natoe ioctl cmd  ID  */
+	uint16  len;            /* total length of all tlv records in data[]  */
+	uint16  pad;            /* pad to be 32 bit aligment */
+	uint8   data[1];       /* var len payload of bcm_xtlv_t type */
+} wl_natoe_ioc_t;
+
+enum wl_natoe_cmds {
+	WL_NATOE_CMD_ENABLE = 1,
+	WL_NATOE_CMD_CONFIG_IPS = 2,
+	WL_NATOE_CMD_CONFIG_PORTS = 3,
+	WL_NATOE_CMD_DBG_STATS = 4,
+	WL_NATOE_CMD_EXCEPTION_PORT = 5,
+	WL_NATOE_CMD_SKIP_PORT = 6,
+	WL_NATOE_CMD_TBL_CNT = 7
+};
+
+enum wl_natoe_cmd_xtlv_id {
+	WL_NATOE_XTLV_ENABLE = 1,
+	WL_NATOE_XTLV_CONFIG_IPS = 2,
+	WL_NATOE_XTLV_CONFIG_PORTS = 3,
+	WL_NATOE_XTLV_DBG_STATS = 4,
+	WL_NATOE_XTLV_EXCEPTION_PORT = 5,
+	WL_NATOE_XTLV_SKIP_PORT = 6,
+	WL_NATOE_XTLV_TBL_CNT = 7
+};
+
+#endif /* WL_NATOE */
+
+/* rsdb */
+#define ALLOW_SIB_PARALLEL_SCAN	(1 << 0)
+#define WL_RSDB_CONFIG_VER 3
+#define MAX_BANDS 2
+#define WL_RSDB_CONFIG_LEN sizeof(rsdb_config_t)
+
+typedef uint8 rsdb_opmode_t;
+typedef uint32 rsdb_flags_t;
+
+typedef enum rsdb_modes {
+	WLC_SDB_MODE_NOSDB_MAIN = 1, /* 2X2 or MIMO mode (applicable only for 4355) */
+	WLC_SDB_MODE_NOSDB_AUX = 2,
+	WLC_SDB_MODE_SDB_MAIN = 3, /* This is RSDB mode(default) applicable only for 4364 */
+	WLC_SDB_MODE_SDB_AUX = 4,
+	WLC_SDB_MODE_SDB_AUTO = 5, /* Same as WLC_RSDB_MODE_RSDB(1+1) mode above */
+} rsdb_modes_t;
+
+typedef struct {
+	uint8 ver;
+	uint8 len;                      /* length of this structure excluding ver and len */
+	uint16 reserved;
+	rsdb_opmode_t non_infra_mode;
+	rsdb_opmode_t infra_mode[MAX_BANDS];
+	rsdb_flags_t flags[MAX_BANDS];
+	rsdb_opmode_t current_mode;   /* Valid only in GET, returns the current mode */
+	uint8  pad[3];
+} rsdb_config_t;
+
+enum wl_idauth_cmd_ids {
+	WL_IDAUTH_CMD_CONFIG				= 1,
+	WL_IDAUTH_CMD_PEER_INFO				= 2,
+	WL_IDAUTH_CMD_COUNTERS				= 3,
+	WL_IDAUTH_CMD_LAST
+};
+enum wl_idauth_xtlv_id {
+	WL_IDAUTH_XTLV_AUTH_ENAB			= 0x1,
+	WL_IDAUTH_XTLV_GTK_ROTATION			= 0x2,
+	WL_IDAUTH_XTLV_EAPOL_COUNT			= 0x3,
+	WL_IDAUTH_XTLV_EAPOL_INTRVL			= 0x4,
+	WL_IDAUTH_XTLV_BLKLIST_COUNT			= 0x5,
+	WL_IDAUTH_XTLV_BLKLIST_AGE			= 0x6,
+	WL_IDAUTH_XTLV_PEERS_INFO			= 0x7,
+	WL_IDAUTH_XTLV_COUNTERS				= 0x8
+};
+enum wl_idauth_stats {
+	WL_AUTH_PEER_STATE_AUTHORISED			= 0x01,
+	WL_AUTH_PEER_STATE_BLACKLISTED			= 0x02,
+	WL_AUTH_PEER_STATE_4WAY_HS_ONGOING		= 0x03,
+	WL_AUTH_PEER_STATE_LAST
+};
+typedef struct {
+	uint16 state;				/* Peer State: Authorised or Blacklisted */
+	struct ether_addr peer_addr;		/* peer Address */
+	uint32 blklist_end_time;		/* Time of blacklist end */
+} auth_peer_t;
+typedef struct wl_idauth_counters {
+	uint32 auth_reqs;			/* No of auth req recvd */
+	uint32 mic_fail;			/* No of mic fails */
+	uint32 four_way_hs_fail;		/* No of 4-way handshake fails */
+} wl_idauth_counters_t;
+
+#define WLC_UTRACE_LEN  512
+#define WLC_UTRACE_READ_END 0
+#define WLC_UTRACE_MORE_DATA 1
+typedef struct wl_utrace_capture_args_v1 {
+	uint32 length;
+	uint32 flag;
+} wl_utrace_capture_args_v1_t;
+
+#define UTRACE_CAPTURE_VER_2	2
+typedef struct wl_utrace_capture_args_v2 {
+	/* structure control */
+	uint16 version;		/**< structure version */
+	uint16 length;		/**< length of the response */
+	uint32 flag;		/* Indicates if there is more data or not */
+} wl_utrace_capture_args_v2_t;
+
+/* XTLV IDs for the Health Check "hc" iovar top level container */
+enum {
+	WL_HC_XTLV_ID_CAT_HC = 1,
+	WL_HC_XTLV_ID_CAT_DATAPATH_TX = 2,      /* Datapath Tx */
+	WL_HC_XTLV_ID_CAT_DATAPATH_RX = 3,      /* Datapath Rx */
+};
+
+/* Health Check: Common XTLV IDs for sub-elements in the top level container
+ * Number starts at 0x8000 to be out of the way for category specific IDs.
+ */
+enum {
+	WL_HC_XTLV_ID_ERR       = 0x8000,       /* for sub-command  err return */
+	WL_HC_XTLV_ID_IDLIST    = 0x8001,       /* container for uint16 IDs */
+};
+
+/* Health Check: Datapath TX IDs */
+enum {
+	WL_HC_TX_XTLV_ID_VAL_STALL_THRESHOLD   = 1,     /* stall_threshold */
+	WL_HC_TX_XTLV_ID_VAL_STALL_SAMPLE_SIZE = 2,     /* stall_sample_size */
+	WL_HC_TX_XTLV_ID_VAL_STALL_TIMEOUT     = 3,     /* stall_timeout */
+	WL_HC_TX_XTLV_ID_VAL_STALL_FORCE       = 4,     /* stall_force */
+	WL_HC_TX_XTLV_ID_VAL_STALL_EXCLUDE     = 5,     /* stall_exclude */
+	WL_HC_TX_XTLV_ID_VAL_FC_TIMEOUT        = 6,     /* flow ctl timeout */
+	WL_HC_TX_XTLV_ID_VAL_FC_FORCE          = 7,     /* flow ctl force failure */
+};
+
+/* Health Check: Datapath RX IDs */
+enum {
+	WL_HC_RX_XTLV_ID_VAL_DMA_STALL_TIMEOUT = 1,     /* dma_stall_timeout */
+	WL_HC_RX_XTLV_ID_VAL_DMA_STALL_FORCE   = 2,     /* dma_stall test trigger */
+	WL_HC_RX_XTLV_ID_VAL_STALL_THRESHOLD   = 3,     /* stall_threshold */
+	WL_HC_RX_XTLV_ID_VAL_STALL_SAMPLE_SIZE = 4,     /* stall_sample_size */
+	WL_HC_RX_XTLV_ID_VAL_STALL_FORCE       = 5,     /* stall test trigger */
+};
+
+/* IDs of Health Check report structures for sub types of health checks within WL */
+enum {
+	WL_HC_DD_UNDEFINED = 0,		/* Undefined */
+	WL_HC_DD_RX_DMA_STALL = 1,      /* RX DMA stall check */
+	WL_HC_DD_RX_STALL = 2,		/* RX stall check */
+	WL_HC_DD_TX_STALL = 3,		/* TX stall check */
+	WL_HC_DD_MAX
+};
+
+/*
+ * Health Check report structures for sub types of health checks within WL
+ */
+
+/* Health Check report structure for Rx DMA Stall check */
+typedef struct {
+	uint16 type;
+	uint16 length;
+	uint16 timeout;
+	uint16 stalled_dma_bitmap;
+} wl_rx_dma_hc_info_t;
+
+/* Health Check report structure for Tx packet failure check */
+typedef struct {
+	uint16 type;
+	uint16 length;
+	uint32 stall_bitmap;
+	uint32 stall_bitmap1;
+	uint32 failure_ac;
+	uint32 threshold;
+	uint32 tx_all;
+	uint32 tx_failure_all;
+} wl_tx_hc_info_t;
+
+/* Health Check report structure for Rx dropped packet failure check */
+typedef struct {
+	uint16 type;
+	uint16 length;
+	uint32 bsscfg_idx;
+	uint32 rx_hc_pkts;
+	uint32 rx_hc_dropped_all;
+	uint32 rx_hc_alert_th;
+} wl_rx_hc_info_t;
+
+/* HE top level command IDs */
+enum {
+	WL_HE_CMD_ENAB = 0,
+	WL_HE_CMD_FEATURES = 1,
+	WL_HE_CMD_TWT_SETUP = 2,
+	WL_HE_CMD_TWT_TEARDOWN = 3,
+	WL_HE_CMD_TWT_INFO = 4,
+	WL_HE_CMD_BSSCOLOR = 5,
+	WL_HE_CMD_LAST
+};
+
+
+/* TWT Setup descriptor */
+typedef struct {
+	/* Setup Command. */
+	uint8 setup_cmd;	/* See TWT_SETUP_CMD_XXXX in 802.11ah.h,
+				 * valid when bcast_twt is FALSE.
+				 */
+	/* Flow attributes */
+	uint8 flow_flags;	/* See WL_TWT_FLOW_FLAG_XXXX below */
+	uint8 flow_id;		/* must be between 0 and 7 */
+	/* Target Wake Time */
+	uint8 wake_type;	/* See WL_TWT_TIME_TYPE_XXXX below */
+	uint32 wake_time_h;	/* target wake time - BSS TSF (us) */
+	uint32 wake_time_l;
+	uint32 wake_dur;	/* target wake duration in us units */
+	uint32 wake_int;	/* target wake interval */
+} wl_twt_sdesc_t;
+
+/* Flow flags */
+#define WL_TWT_FLOW_FLAG_BROADCAST	(1<<0)
+#define WL_TWT_FLOW_FLAG_IMPLICIT	(1<<1)
+#define WL_TWT_FLOW_FLAG_UNANNOUNCED	(1<<2)
+#define WL_TWT_FLOW_FLAG_TRIGGER	(1<<3)
+
+/* Flow id */
+#define WL_TWT_FLOW_ID_FID	0x07	/* flow id */
+#define WL_TWT_FLOW_ID_GID_MASK	0x70	/* group id - broadcast TWT only */
+#define WL_TWT_FLOW_ID_GID_SHIFT 4
+
+/* Wake type */
+/* TODO: not yet finalized */
+#define WL_TWT_TIME_TYPE_BSS	0	/* The time specified in wake_time_h/l is
+					 * the BSS TSF time.
+					 */
+#define WL_TWT_TIME_TYPE_OFFSET	1	/* The time specified in wake_time_h/l is an offset
+					 * of the TSF time when the iovar is processed.
+					 */
+
+#define WL_TWT_SETUP_VER	0
+
+/* HE TWT Setup command */
+typedef struct {
+	/* structure control */
+	uint16 version;	/* structure version */
+	uint16 length;	/* data length (starting after this field) */
+	/* peer address */
+	struct ether_addr peer;	/* leave it all 0s' for AP */
+	/* session id */
+	uint8 dialog;	/* an arbitrary number to identify the seesion */
+	uint8 pad;
+	/* setup descriptor */
+	wl_twt_sdesc_t desc;
+} wl_twt_setup_t;
+
+#define WL_TWT_TEARDOWN_VER	0
+
+/* HE TWT Teardown command */
+typedef struct {
+	/* structure control */
+	uint16 version;	/* structure version */
+	uint16 length;	/* data length (starting after this field) */
+	/* peer address */
+	struct ether_addr peer;	/* leave it all 0s' for AP */
+	/* flow attributes */
+	uint8 flow_flags;	/* See WL_TWT_FLOW_FLAG_XXXX above.
+				 * (only BORADCAST) is applicable)
+				 */
+	uint8 flow_id;		/* must be between 0 and 7 */
+} wl_twt_teardown_t;
+
+/* twt information descriptor */
+typedef struct {
+	uint8 flow_flags;	/* See WL_TWT_INFO_FLAG_XXX below */
+	uint8 flow_id;
+	uint8 pad[2];
+	uint32 next_twt_h;
+	uint32 next_twt_l;
+} wl_twt_idesc_t;
+
+/* Flow flags */
+#define WL_TWT_INFO_FLAG_RESP_REQ	(1<<0)	/* Request response */
+
+#define WL_TWT_INFO_VER	0
+
+/* HE TWT Information command */
+typedef struct {
+	/* structure control */
+	uint16 version;	/* structure version */
+	uint16 length;	/* data length (starting after this field) */
+	/* peer address */
+	struct ether_addr peer;	/* leave it all 0s' for AP */
+	uint8 pad[2];
+	/* information descriptor */
+	wl_twt_idesc_t desc;
+} wl_twt_info_t;
+
+/* Current version for wlc_clm_power_limits_req_t structure and flags */
+#define WLC_CLM_POWER_LIMITS_REQ_VERSION 1
+/* "clm_power_limits" iovar request structure */
+typedef struct wlc_clm_power_limits_req {
+	/* Input. Structure and flags version */
+	uint32 version;
+	/* Full length of buffer (includes this structure and space for TLV-encoded PPR) */
+	uint32 buflen;
+	/* Input. Flags (see WLC_CLM_POWER_LIMITS_INPUT_FLAG_... below) */
+	uint32 input_flags;
+	/* Input. CC of region whose data is being requested */
+	char cc[WLC_CNTRY_BUF_SZ];
+	/* Input. Channel/subchannel in chanspec_t format */
+	uint32 chanspec;
+	/* Subchannel encoded as clm_limits_type_t */
+	uint32 clm_subchannel;
+	/* Input. 0-based antenna index */
+	uint32 antenna_idx;
+	/* Output. General flags (see WLC_CLM_POWER_LIMITS_OUTPUT_FLAG_... below) */
+	uint32 output_flags;
+	/* Output. 2.4G country flags, encoded as clm_flags_t enum */
+	uint32 clm_country_flags_2g;
+	/* Output. 5G country flags, encoded as clm_flags_t enum */
+	uint32 clm_country_flags_5g;
+	/* Output. Length of TLV-encoded PPR data that follows this structure */
+	uint32 ppr_tlv_size;
+	/* Output. Beginning of buffer for TLV-encoded PPR data */
+	uint8 ppr_tlv[1];
+} wlc_clm_power_limits_req_t;
+
+/* Input. Do not apply SAR limits */
+#define WLC_CLM_POWER_LIMITS_INPUT_FLAG_NO_SAR				0x00000001
+/* Input. Do not apply board limits */
+#define WLC_CLM_POWER_LIMITS_INPUT_FLAG_NO_BOARD			0x00000002
+/* Output. Limits taken from product-specific country data */
+#define WLC_CLM_POWER_LIMITS_OUTPUT_FLAG_PRODUCT_LIMITS			0x00000001
+/* Output. Limits taken from product-specific worldwide data */
+#define WLC_CLM_POWER_LIMITS_OUTPUT_FLAG_WORLDWIDE_LIMITS		0x00000002
+/* Output. Limits taken from country-default (all-product) data */
+#define WLC_CLM_POWER_LIMITS_OUTPUT_FLAG_DEFAULT_COUNTRY_LIMITS		0x00000004
+
+/*
+ * WOG (Wake On Googlecast)
+ */
+
+#define MAX_GCAST_APPID_CNT_LIMIT 50
+#define MAX_DNS_LABEL 63
+
+typedef struct wog_appid {
+	uint8 appID[MAX_DNS_LABEL+1];
+} wog_appid_t;
+
+enum {
+	WOG_APPID_ADD,
+	WOG_APPID_DEL,
+	WOG_APPID_CLEAR,
+	WOG_APPID_LIST,
+	WOG_MAX_APPID_CNT
+};
+
+#define WOG_APPID_IOV_VER 1
+typedef struct wog_appid_iov {
+	/* version for iovar */
+	uint32 ver;
+	/* add/del/clear/list operation */
+	uint32 operation;
+	/* for adding or deleting multiple items */
+	/* for WOG_MAX_APPID_CNT, this value is used for max count for AppID */
+	uint32 cnt;
+	/* Application IDs */
+	/* If FW found an AppID from this list, FW will respond to discovery */
+	/* without wake up the host */
+	wog_appid_t appids[1];
+} wog_appid_iov_t;
+
+/* dns service record */
+/* service name : _googlecast */
+typedef struct wog_srv_record {
+	uint32 ttl;
+	uint16 port; /* tcp 8008 or 8009 */
+	uint8 PAD[2];
+} wog_srv_record_t;
+
+#define GCAST_MAX_MODEL_NAME_LEN 16
+#define GCAST_MAX_FNAME_LEN 64
+#define GCAST_MAX_RS_LEN 60
+
+#define GCAST_UUID_LEN 32
+#define GCAST_PUBLICKEY_ID_LEN 64
+#define GCAST_VER_LEN 2
+typedef struct wog_txt_record {
+	uint32 ttl;
+	/* id : UUID for the receiver */
+	char id[GCAST_UUID_LEN+1];
+
+	/* Cast protocol version supported. Begins at 2 */
+	/* and is incremented by 1 with each version */
+	char ver[GCAST_VER_LEN+1];
+
+	/* 256bit receiver Subject Public Key Identifier from the SSL cert */
+	char public_key[GCAST_PUBLICKEY_ID_LEN+1];
+
+	/* A bitfield of device capabilities. */
+	/* bit 0 : video_out (1:has video out, 0:no video) */
+	/* bit 1 : video_in */
+	/* bit 2 : audio_out */
+	/* bit 3 : audio_in */
+	/* bit 4 : dev_mode */
+	/*	 (1:dev mode enabled, 0: not enabled) */
+	char capability;
+
+	/* Receiver status flag 0:IDLE, 1(BUSY/JOIN) */
+	/* IDLE : The receiver is idle */
+	/*	   and doesn't need to be connected now. */
+	/* BUSY/JOIN : The receiver is hosting an activity */
+	/*	 and invites the sender to join */
+	char receiver_status_flag;
+
+	uint8 PAD0[1];
+
+	char friendly_name[GCAST_MAX_FNAME_LEN+1];
+	uint8 PAD1[3];
+
+	char model_name[GCAST_MAX_MODEL_NAME_LEN+1];
+	uint8 PAD2[3];
+
+	/* Receiver Status text for Cast Protocol v2 */
+	/* Spec says that if the status text exceeds 60 characters in length, */
+	/* it is truncated at 60 caracters and */
+	/* a UTF-8 ellipsis character is appended to indicate trucation. */
+	/* But our dongle won't use UTF-8 ellipsis. It's not a big deal. */
+	char receiver_status[GCAST_MAX_RS_LEN+1];
+	uint8 PAD3[3];
+} wog_txt_record_t;
+
+/* ip will be taken from the ip of wog_info_t */
+typedef struct wog_a_record {
+	uint32 ttl;
+} wog_a_record_t;
+
+/* Google Cast protocl uses mDNS SD for its discovery */
+#define WOG_SD_RESP_VER 1
+typedef struct wog_sd_resp {
+	/* version for iovar */
+	int32 ver;
+	/* device name of Google Cast receiver */
+	char device_name[MAX_DNS_LABEL+1];
+	/* IP address of Google Cast receiver */
+	uint8 ip[4];
+	/* ttl of PTR response */
+	uint32 ptr_ttl;
+	/* DNS TXT record */
+	wog_txt_record_t txt;
+	/* DNS SRV record */
+	wog_srv_record_t srv;
+	/* DNS A record */
+	wog_a_record_t a;
+} wog_sd_resp_t;
+
+enum wl_mbo_cmd_ids {
+	WL_MBO_CMD_ADD_CHAN_PREF = 1,
+	WL_MBO_CMD_DEL_CHAN_PREF = 2,
+	WL_MBO_CMD_LIST_CHAN_PREF = 3,
+	WL_MBO_CMD_CELLULAR_DATA_CAP = 4,
+	WL_MBO_CMD_DUMP_COUNTERS = 5,
+	WL_MBO_CMD_CLEAR_COUNTERS = 6,
+	WL_MBO_CMD_FORCE_ASSOC = 7,
+	WL_MBO_CMD_BSSTRANS_REJECT = 8,
+	/* Add before this !! */
+	WL_MBO_CMD_LAST
+};
+
+enum wl_mbo_xtlv_id {
+	WL_MBO_XTLV_OPCLASS            = 0x1,
+	WL_MBO_XTLV_CHAN               = 0x2,
+	WL_MBO_XTLV_PREFERENCE         = 0x3,
+	WL_MBO_XTLV_REASON_CODE        = 0x4,
+	WL_MBO_XTLV_CELL_DATA_CAP      = 0x5,
+	WL_MBO_XTLV_COUNTERS           = 0x6,
+	WL_MBO_XTLV_ENABLE             = 0x7
+};
+
+typedef struct wl_mbo_counters {
+	/* No of transition req recvd */
+	uint16 trans_req_rcvd;
+	/* No of transition req with disassoc imminent */
+	uint16 trans_req_disassoc;
+	/* No of transition req with BSS Termination */
+	uint16 trans_req_bss_term;
+	/* No of trans req w/ unspecified reason */
+	uint16 trans_resn_unspec;
+	/* No of trans req w/ reason frame loss */
+	uint16 trans_resn_frm_loss;
+	/* No of trans req w/ reason traffic delay */
+	uint16 trans_resn_traffic_delay;
+	/* No of trans req w/ reason insufficient buffer */
+	uint16 trans_resn_insuff_bw;
+	/* No of trans req w/ reason load balance */
+	uint16 trans_resn_load_bal;
+	/* No of trans req w/ reason low rssi */
+	uint16 trans_resn_low_rssi;
+	/* No of trans req w/ reason excessive retransmission */
+	uint16 trans_resn_xcess_retransmn;
+	/* No of trans req w/ reason gray zone */
+	uint16 trans_resn_gray_zone;
+	/* No of trans req w/ reason switch to premium AP */
+	uint16 trans_resn_prem_ap_sw;
+	/* No of transition rejection sent */
+	uint16 trans_rejn_sent;
+	/* No of trans rejn reason excessive frame loss */
+	uint16 trans_rejn_xcess_frm_loss;
+	/* No of trans rejn reason excessive traffic delay */
+	uint16 trans_rejn_xcess_traffic_delay;
+	/* No of trans rejn reason insufficient QoS capability */
+	uint16 trans_rejn_insuffic_qos_cap;
+	/* No of trans rejn reason low RSSI */
+	uint16 trans_rejn_low_rssi;
+	/* No of trans rejn reason high interference */
+	uint16 trans_rejn_high_interference;
+	/* No of trans rejn reason service unavilable */
+	uint16 trans_rejn_service_unavail;
+	/* No of beacon request rcvd */
+	uint16 bcn_req_rcvd;
+	/* No of beacon report sent */
+	uint16 bcn_rep_sent;
+	/* No of null beacon report sent */
+	uint16 null_bcn_rep_sent;
+	/* No of wifi to cell switch */
+	uint16 wifi_to_cell;
+} wl_mbo_counters_t;
+
+/* otpread command */
+#define WL_OTPREAD_VER 1
+
+typedef struct {
+	uint16 version;		/* cmd structure version */
+	uint16 cmd_len;		/* cmd struct len */
+	uint32 rdmode;		/* otp read mode */
+	uint32 rdoffset;	/* byte offset into otp to start read */
+	uint32 rdsize;		/* number of bytes to read */
+} wl_otpread_cmd_t;
+
+#define WL_LEAKY_AP_STATS_GT_TYPE	0
+#define WL_LEAKY_AP_STATS_PKT_TYPE	1
+typedef struct wlc_leaked_infra_guard_marker {
+	/* type field for this TLV: WL_LEAKY_AP_STATS_GT_TYPE */
+	uint16  type;
+	/* length field for this TLV */
+	uint16  len;
+	/* guard sample sequence number; Updated by 1 on every guard sample */
+	uint32  seq_number;
+	/* Guard time start time (tsf; PS indicated and acked) */
+	uint32  start_time;
+	/* tsf timestamp for the GT end event */
+	uint32  gt_tsf_l;
+	/* Guard time period in ms */
+	uint16  guard_duration;
+	/* Number PPDUs in the notification */
+	uint16  num_pkts;
+	/* Flags to indicate some states see below */
+	uint8   flag;
+	/* pad for 32-bit alignment */
+	uint8   reserved[3];
+} wlc_leaked_infra_guard_marker_t;
+
+/* Flag information */
+#define WL_LEAKED_GUARD_TIME_NONE	0               /* Not in any guard time */
+#define WL_LEAKED_GUARD_TIME_FRTS	(0x01 << 0)     /* Normal FRTS power save */
+#define WL_LEAKED_GUARD_TIME_SCAN	(0x01 << 1)     /* Channel switch due to scanning */
+#define WL_LEAKED_GUARD_TIME_AWDL_PSF	(0x01 << 2)     /* Channel switch due to AWDL PSF */
+#define WL_LEAKED_GUARD_TIME_AWDL_AW	(0x01 << 3)     /* Channel switch due to AWDL AW */
+#define WL_LEAKED_GUARD_TIME_TERMINATED (0x01 << 7)     /* indicate a GT is terminated early */
+
+typedef struct wlc_leaked_infra_packet_stat {
+	uint16  type;			/* type field for this TLV: WL_LEAKY_AP_STATS_PKT_TYPE */
+	uint16  len;			/* length field for this TLV */
+	uint16  ppdu_len_bytes;		/* PPDU packet length in bytes */
+	uint16  num_mpdus;		/* number of the MPDUs in the PPDU */
+	uint32  ppdu_time;		/* PPDU arrival time at the begining of the guard time */
+	uint32  rate;			/* PPDU packet rate; Received packet's data rate */
+	uint16  seq_number;		/* sequence number */
+	int8    rssi;			/* RSSI */
+	uint8   tid;			/* tid */
+} wlc_leaked_infra_packet_stat_t;
+
+/* Wake timer structure definition */
+#define WAKE_TIMER_VERSION 1
+#define WAKE_TIMER_NOLIMIT 0xFFFF
+
+typedef struct wake_timer {
+	uint16 ver;
+	uint16 len;
+	uint16 limit;   /* number of events to deliver
+			* 0-disable, 0xffff-indefinite, num_events otherwise
+			*/
+	uint16 count;	/* number of events delivered since enable (get only) */
+	uint16 period;	/* timeout/period in milliseconds */
+} wake_timer_t;
+
+typedef struct wl_desense_restage_gain {
+	uint16 version;
+	uint16 length;
+	uint band;
+	uint8 num_cores;
+	uint8 desense_array[WL_TX_CHAINS_MAX];
+} wl_desense_restage_gain_t;
+
+#define MAX_UCM_CHAINS 5
+#define MAX_UCM_PROFILES 4
+#define UCM_PROFILE_VERSION_1 1
+
+/* UCM per chain attribute struct */
+typedef struct wlc_btcx_chain_attr {
+	uint16 length;			/* chain attr length, version is same as profile version */
+	int8 desense_level;		/* per chain desense level */
+	int8 ack_pwr_strong_rssi;	/* per chain ack power at strong rssi */
+	int8 ack_pwr_weak_rssi;		/* per chain ack power at weak rssi */
+	int8 tx_pwr_strong_rssi;	/* per chain tx power at strong rssi */
+	int8 tx_pwr_weak_rssi;		/* per chain tx power at weak rssi */
+	uint8 PAD[1];			/* additional bytes for alignment */
+} wlc_btcx_chain_attr_t;
+
+typedef struct wlc_btcx_profile_v1 {
+	uint16 version;			/* UCM profile version */
+	uint16 length;			/* profile size */
+	uint16 fixed_length;		/* size of the fixed portion of the profile */
+	uint8 init;			/* profile initialized or not */
+	uint8 chain_attr_count;		/* Number of elements in chain_attr array */
+	uint8 profile_index;		/* profile index */
+	uint8 mode_strong_wl_bt;	/* Mode under strong WLAN and BT RSSI */
+	uint8 mode_weak_wl;		/* Mode under weak WLAN RSSI */
+	uint8 mode_weak_bt;		/* Mode under weak BT RSSI */
+	uint8 mode_weak_wl_bt;		/* Mode under weak BT and WLAN RSSI */
+	int8 mode_wl_hi_lo_rssi_thresh;	/* Strong to weak WLAN RSSI threshold for mode selection */
+	int8 mode_wl_lo_hi_rssi_thresh;	/* Weak to strong WLAN RSSI threshold for mode selection */
+	int8 mode_bt_hi_lo_rssi_thresh;	/* Strong to weak BT RSSI threshold for mode selection */
+	int8 mode_bt_lo_hi_rssi_thresh;	/* Weak to strong BT RSSI threshold for mode selection */
+	int8 desense_wl_hi_lo_rssi_thresh;	/* Strong to weak RSSI threshold for desense */
+	int8 desense_wl_lo_hi_rssi_thresh;	/* Weak to strong RSSI threshold for desense */
+	int8 ack_pwr_wl_hi_lo_rssi_thresh;	/* Strong to weak RSSI threshold for ACK power */
+	int8 ack_pwr_wl_lo_hi_rssi_thresh;	/* Weak to strong RSSI threshold for ACK power */
+	int8 tx_pwr_wl_hi_lo_rssi_thresh;	/* Strong to weak RSSI threshold for Tx power */
+	int8 tx_pwr_wl_lo_hi_rssi_thresh;	/* Weak to strong RSSI threshold for Tx power */
+	uint8 PAD[1];				/* additional bytes for 4 byte alignment */
+	wlc_btcx_chain_attr_t chain_attr[];	/* variable length array with chain attributes */
+} wlc_btcx_profile_v1_t;
+
+typedef struct {
+	uint8   ipaddr[IPV4_ADDR_LEN];
+	uint8   ipaddr_netmask[IPV4_ADDR_LEN];
+	uint8   ipaddr_gateway[IPV4_ADDR_LEN];
+} netx_ifconfig_t;
+
+#ifdef TBTT_OFFSET_STAT
+/* XXX: tbtt offset stat is only for primary STA and non-p2p link */
+typedef struct {
+	uint32 tbtt_offset_avg;
+	uint32 tbtt_offset_min;
+	uint32 tbtt_offset_max;
+} tbtt_offset_stat_t;
+#endif /* TBTT_OFFSET_STAT */
+
+#endif /* _wlioctl_h_ */
diff --git a/wl/components/shared/devctrl_if/wlioctl_defs.h b/wl/components/shared/devctrl_if/wlioctl_defs.h
new file mode 100644
index 0000000..510c3fe
--- /dev/null
+++ b/wl/components/shared/devctrl_if/wlioctl_defs.h
@@ -0,0 +1,2278 @@
+/*
+ * Custom OID/ioctl definitions for
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 2017, Broadcom. 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: wlioctl_defs.h 660256 2016-09-19 22:24:03Z $
+ */
+
+
+#ifndef wlioctl_defs_h
+#define wlioctl_defs_h
+
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+
+
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/* All builds use the new 11ac ratespec/chanspec */
+#undef  D11AC_IOTYPES
+#define D11AC_IOTYPES
+
+/* WL_RSPEC defines for rate information */
+#define WL_RSPEC_RATE_MASK      0x000000FF      /* rate or HT MCS value */
+#define WL_RSPEC_VHT_MCS_MASK   0x0000000F      /* VHT MCS value */
+#define WL_RSPEC_VHT_NSS_MASK   0x000000F0      /* VHT Nss value */
+#define WL_RSPEC_VHT_NSS_SHIFT  4               /* VHT Nss value shift */
+#define WL_RSPEC_TXEXP_MASK     0x00000300
+#define WL_RSPEC_TXEXP_SHIFT    8
+#define WL_RSPEC_BW_MASK        0x00070000      /* bandwidth mask */
+#define WL_RSPEC_BW_SHIFT       16              /* bandwidth shift */
+#define WL_RSPEC_STBC           0x00100000      /* STBC encoding, Nsts = 2 x Nss */
+#define WL_RSPEC_TXBF           0x00200000      /* bit indicates TXBF mode */
+#define WL_RSPEC_LDPC           0x00400000      /* bit indicates adv coding in use */
+#define WL_RSPEC_SGI            0x00800000      /* Short GI mode */
+#define WL_RSPEC_ENCODING_MASK  0x03000000      /* Encoding of Rate/MCS field */
+#define WL_RSPEC_OVERRIDE_RATE  0x40000000      /* bit indicate to override mcs only */
+#define WL_RSPEC_OVERRIDE_MODE  0x80000000      /* bit indicates override both rate & mode */
+
+/* WL_RSPEC_ENCODING field defs */
+#define WL_RSPEC_ENCODE_RATE    0x00000000      /* Legacy rate is stored in RSPEC_RATE_MASK */
+#define WL_RSPEC_ENCODE_HT      0x01000000      /* HT MCS is stored in RSPEC_RATE_MASK */
+#define WL_RSPEC_ENCODE_VHT     0x02000000      /* VHT MCS and Nss is stored in RSPEC_RATE_MASK */
+
+/* WL_RSPEC_BW field defs */
+#define WL_RSPEC_BW_UNSPECIFIED 0
+#define WL_RSPEC_BW_20MHZ       0x00010000
+#define WL_RSPEC_BW_40MHZ       0x00020000
+#define WL_RSPEC_BW_80MHZ       0x00030000
+#define WL_RSPEC_BW_160MHZ      0x00040000
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_RSPEC_BW_10MHZ	0x00050000
+#define WL_RSPEC_BW_5MHZ	0x00060000
+#define WL_RSPEC_BW_2P5MHZ      0x00070000
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* Legacy defines for the nrate iovar */
+#define OLD_NRATE_MCS_INUSE         0x00000080 /* MSC in use,indicates b0-6 holds an mcs */
+#define OLD_NRATE_RATE_MASK         0x0000007f /* rate/mcs value */
+#define OLD_NRATE_STF_MASK          0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */
+#define OLD_NRATE_STF_SHIFT         8          /* stf mode shift */
+#define OLD_NRATE_OVERRIDE          0x80000000 /* bit indicates override both rate & mode */
+#define OLD_NRATE_OVERRIDE_MCS_ONLY 0x40000000 /* bit indicate to override mcs only */
+#define OLD_NRATE_SGI               0x00800000 /* sgi mode */
+#define OLD_NRATE_LDPC_CODING       0x00400000 /* bit indicates adv coding in use */
+
+#define OLD_NRATE_STF_SISO	0		/* stf mode SISO */
+#define OLD_NRATE_STF_CDD	1		/* stf mode CDD */
+#define OLD_NRATE_STF_STBC	2		/* stf mode STBC */
+#define OLD_NRATE_STF_SDM	3		/* stf mode SDM */
+
+#define HIGHEST_SINGLE_STREAM_MCS	7 /* MCS values greater than this enable multiple streams */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WLC_11N_N_PROP_MCS	6
+#define WLC_11N_FIRST_PROP_MCS	87
+#define WLC_11N_LAST_PROP_MCS	102
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#ifndef OEM_ANDROID
+/* given a proprietary MCS, get number of spatial streams */
+#define GET_PROPRIETARY_11N_MCS_NSS(mcs) (1 + ((mcs) - 85) / 8)
+
+#define GET_11N_MCS_NSS(mcs) ((mcs) < 32 ? (1 + ((mcs) / 8)) \
+				: ((mcs) == 32 ? 1 : GET_PROPRIETARY_11N_MCS_NSS(mcs)))
+#endif /* !OEM_ANDROID */
+
+#define MAX_CCA_CHANNELS 38	/* Max number of 20 Mhz wide channels */
+#ifdef DONGLEBUILD
+#define MAX_CCA_SECS	1	/* CCA keeps this many seconds history - trimmed for dongle */
+#else
+#define MAX_CCA_SECS	60	/* CCA keeps this many seconds history */
+#endif
+
+#define IBSS_MED        15	/* Mediom in-bss congestion percentage */
+#define IBSS_HI         25	/* Hi in-bss congestion percentage */
+#define OBSS_MED        12
+#define OBSS_HI         25
+#define INTERFER_MED    5
+#define INTERFER_HI     10
+
+#define  CCA_FLAG_2G_ONLY		0x01	/* Return a channel from 2.4 Ghz band */
+#define  CCA_FLAG_5G_ONLY		0x02	/* Return a channel from 2.4 Ghz band */
+#define  CCA_FLAG_IGNORE_DURATION	0x04	/* Ignore dwell time for each channel */
+#define  CCA_FLAGS_PREFER_1_6_11	0x10
+#define  CCA_FLAG_IGNORE_INTERFER 	0x20 /* do not exlude channel based on interfer level */
+
+#define CCA_ERRNO_BAND 		1	/* After filtering for band pref, no choices left */
+#define CCA_ERRNO_DURATION	2	/* After filtering for duration, no choices left */
+#define CCA_ERRNO_PREF_CHAN	3	/* After filtering for chan pref, no choices left */
+#define CCA_ERRNO_INTERFER	4	/* After filtering for interference, no choices left */
+#define CCA_ERRNO_TOO_FEW	5	/* Only 1 channel was input */
+
+#define WL_STA_AID(a)		((a) &~ 0xc000)
+
+/* Flags for sta_info_t indicating properties of STA */
+#define WL_STA_BRCM		0x00000001	/* Running a Broadcom driver */
+#define WL_STA_WME		0x00000002	/* WMM association */
+#define WL_STA_NONERP		0x00000004	/* No ERP */
+#define WL_STA_AUTHE		0x00000008	/* Authenticated */
+#define WL_STA_ASSOC		0x00000010	/* Associated */
+#define WL_STA_AUTHO		0x00000020	/* Authorized */
+#define WL_STA_WDS		0x00000040	/* Wireless Distribution System */
+#define WL_STA_WDS_LINKUP	0x00000080	/* WDS traffic/probes flowing properly */
+#define WL_STA_PS		0x00000100	/* STA is in power save mode from AP's viewpoint */
+#define WL_STA_APSD_BE		0x00000200	/* APSD delv/trigger for AC_BE is default enabled */
+#define WL_STA_APSD_BK		0x00000400	/* APSD delv/trigger for AC_BK is default enabled */
+#define WL_STA_APSD_VI		0x00000800	/* APSD delv/trigger for AC_VI is default enabled */
+#define WL_STA_APSD_VO		0x00001000	/* APSD delv/trigger for AC_VO is default enabled */
+#define WL_STA_N_CAP		0x00002000	/* STA 802.11n capable */
+#define WL_STA_SCBSTATS		0x00004000	/* Per STA debug stats */
+#define WL_STA_AMPDU_CAP	0x00008000	/* STA AMPDU capable */
+#define WL_STA_AMSDU_CAP	0x00010000	/* STA AMSDU capable */
+#define WL_STA_MIMO_PS		0x00020000	/* mimo ps mode is enabled */
+#define WL_STA_MIMO_RTS		0x00040000	/* send rts in mimo ps mode */
+#define WL_STA_RIFS_CAP		0x00080000	/* rifs enabled */
+#define WL_STA_VHT_CAP		0x00100000	/* STA VHT(11ac) capable */
+#define WL_STA_WPS		0x00200000	/* WPS state */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_STA_DWDS_CAP		0x01000000	/* DWDS CAP */
+#define WL_STA_DWDS		0x02000000	/* DWDS active */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WL_WDS_LINKUP		WL_STA_WDS_LINKUP	/* deprecated */
+
+/* STA HT cap fields */
+#define WL_STA_CAP_LDPC_CODING		0x0001	/* Support for rx of LDPC coded pkts */
+#define WL_STA_CAP_40MHZ		0x0002  /* FALSE:20Mhz, TRUE:20/40MHZ supported */
+#define WL_STA_CAP_MIMO_PS_MASK		0x000C  /* Mimo PS mask */
+#define WL_STA_CAP_MIMO_PS_SHIFT	0x0002	/* Mimo PS shift */
+#define WL_STA_CAP_MIMO_PS_OFF		0x0003	/* Mimo PS, no restriction */
+#define WL_STA_CAP_MIMO_PS_RTS		0x0001	/* Mimo PS, send RTS/CTS around MIMO frames */
+#define WL_STA_CAP_MIMO_PS_ON		0x0000	/* Mimo PS, MIMO disallowed */
+#define WL_STA_CAP_GF			0x0010	/* Greenfield preamble support */
+#define WL_STA_CAP_SHORT_GI_20		0x0020	/* 20MHZ short guard interval support */
+#define WL_STA_CAP_SHORT_GI_40		0x0040	/* 40Mhz short guard interval support */
+#define WL_STA_CAP_TX_STBC		0x0080	/* Tx STBC support */
+#define WL_STA_CAP_RX_STBC_MASK		0x0300	/* Rx STBC mask */
+#define WL_STA_CAP_RX_STBC_SHIFT	8	/* Rx STBC shift */
+#define WL_STA_CAP_DELAYED_BA		0x0400	/* delayed BA support */
+#define WL_STA_CAP_MAX_AMSDU		0x0800	/* Max AMSDU size in bytes , 0=3839, 1=7935 */
+#define WL_STA_CAP_DSSS_CCK		0x1000	/* DSSS/CCK supported by the BSS */
+#define WL_STA_CAP_PSMP			0x2000	/* Power Save Multi Poll support */
+#define WL_STA_CAP_40MHZ_INTOLERANT	0x4000	/* 40MHz Intolerant */
+#define WL_STA_CAP_LSIG_TXOP		0x8000	/* L-SIG TXOP protection support */
+
+#define WL_STA_CAP_RX_STBC_NO		0x0	/* no rx STBC support */
+#define WL_STA_CAP_RX_STBC_ONE_STREAM	0x1	/* rx STBC support of 1 spatial stream */
+#define WL_STA_CAP_RX_STBC_TWO_STREAM	0x2	/* rx STBC support of 1-2 spatial streams */
+#define WL_STA_CAP_RX_STBC_THREE_STREAM	0x3	/* rx STBC support of 1-3 spatial streams */
+
+/* scb vht flags */
+#define WL_STA_VHT_LDPCCAP	0x0001
+#define WL_STA_SGI80		0x0002
+#define WL_STA_SGI160		0x0004
+#define WL_STA_VHT_TX_STBCCAP	0x0008
+#define WL_STA_VHT_RX_STBCCAP	0x0010
+#define WL_STA_SU_BEAMFORMER	0x0020
+#define WL_STA_SU_BEAMFORMEE	0x0040
+#define WL_STA_MU_BEAMFORMER	0x0080
+#define WL_STA_MU_BEAMFORMEE	0x0100
+#define WL_STA_VHT_TXOP_PS	0x0200
+#define WL_STA_HTC_VHT_CAP	0x0400
+
+/* Values for TX Filter override mode */
+#define WLC_TXFILTER_OVERRIDE_DISABLED  0
+#define WLC_TXFILTER_OVERRIDE_ENABLED   1
+
+#define WL_IOCTL_ACTION_GET		0x0
+#define WL_IOCTL_ACTION_SET		0x1
+#define WL_IOCTL_ACTION_OVL_IDX_MASK	0x1e
+#define WL_IOCTL_ACTION_OVL_RSV		0x20
+#define WL_IOCTL_ACTION_OVL		0x40
+#define WL_IOCTL_ACTION_MASK		0x7e
+#define WL_IOCTL_ACTION_OVL_SHIFT	1
+
+/* For WLC_SET_INFRA ioctl & infra_configuration iovar SET/GET operations */
+#define WL_BSSTYPE_INDEP 0
+#define WL_BSSTYPE_INFRA 1
+#define WL_BSSTYPE_ANY   2	/* deprecated */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_BSSTYPE_MESH  3
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/* Bitmask for scan_type */
+#define WL_SCANFLAGS_PASSIVE	0x01	/* force passive scan */
+#define WL_SCANFLAGS_RESERVED	0x02	/* Reserved */
+#define WL_SCANFLAGS_PROHIBITED	0x04	/* allow scanning prohibited channels */
+#define WL_SCANFLAGS_OFFCHAN	0x08	/* allow scanning/reporting off-channel APs */
+#define WL_SCANFLAGS_HOTSPOT	0x10	/* automatic ANQP to hotspot APs */
+#define WL_SCANFLAGS_SWTCHAN	0x20	/* Force channel switch for differerent bandwidth */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_SCANFLAGS_FORCE_PARALLEL 0x40 /* Force parallel scan even when actcb_fn_t is on.
+					  * by default parallel scan will be disabled if actcb_fn_t
+					  * is provided.
+					  */
+#define WL_SCANFLAGS_SISO	0x40	/* Use 1 RX chain for scanning */
+#define WL_SCANFLAGS_MIMO	0x80	/* Force MIMO scanning */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* wl_iscan_results status values */
+#define WL_SCAN_RESULTS_SUCCESS	0
+#define WL_SCAN_RESULTS_PARTIAL	1
+#define WL_SCAN_RESULTS_PENDING	2
+#define WL_SCAN_RESULTS_ABORTED	3
+#define WL_SCAN_RESULTS_NO_MEM  4
+
+#define SCANOL_ENABLED			(1 << 0)
+#define SCANOL_BCAST_SSID		(1 << 1)
+#define SCANOL_NOTIFY_BCAST_SSID	(1 << 2)
+#define SCANOL_RESULTS_PER_CYCLE	(1 << 3)
+
+/* scan times in milliseconds */
+#define SCANOL_HOME_TIME		45	/* for home channel processing */
+#define SCANOL_ASSOC_TIME		20	/* dwell on a channel while associated */
+#define SCANOL_UNASSOC_TIME		40	/* dwell on a channel while unassociated */
+#define SCANOL_PASSIVE_TIME		110	/* listen on a channelfor passive scan */
+#define SCANOL_AWAY_LIMIT		100	/* max time to be away from home channel */
+#define SCANOL_IDLE_REST_TIME		40
+#define SCANOL_IDLE_REST_MULTIPLIER	0
+#define SCANOL_ACTIVE_REST_TIME		20
+#define SCANOL_ACTIVE_REST_MULTIPLIER	0
+#define SCANOL_CYCLE_IDLE_REST_TIME	300000	/* Idle Rest Time between Scan Cycle (msec) */
+#define SCANOL_CYCLE_IDLE_REST_MULTIPLIER	0	/* Idle Rest Time Multiplier */
+#define SCANOL_CYCLE_ACTIVE_REST_TIME	200
+#define SCANOL_CYCLE_ACTIVE_REST_MULTIPLIER	0
+#define SCANOL_MAX_REST_TIME		3600000	/* max rest time between scan cycle (msec) */
+#define SCANOL_CYCLE_DEFAULT		0	/* default for Max Scan Cycle, 0 = forever */
+#define SCANOL_CYCLE_MAX		864000	/* Max Scan Cycle */
+						/* 10 sec/scan cycle => 100 days */
+#define SCANOL_NPROBES			2	/* for Active scan; send n probes on each channel */
+#define SCANOL_NPROBES_MAX		5	/* for Active scan; send n probes on each channel */
+#define SCANOL_SCAN_START_DLY		10	/* delay start of offload scan (sec) */
+#define SCANOL_SCAN_START_DLY_MAX	240	/* delay start of offload scan (sec) */
+#define SCANOL_MULTIPLIER_MAX		10	/* Max Multiplier */
+#define SCANOL_UNASSOC_TIME_MAX		100	/* max dwell on a channel while unassociated */
+#define SCANOL_PASSIVE_TIME_MAX		500	/* max listen on a channel for passive scan */
+#define SCANOL_SSID_MAX			16	/* max supported preferred SSID */
+
+/* masks for channel and ssid count */
+#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff
+#define WL_SCAN_PARAMS_NSSID_SHIFT 16
+
+#define WL_SCAN_ACTION_START      1
+#define WL_SCAN_ACTION_CONTINUE   2
+#define WL_SCAN_ACTION_ABORT      3
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#if defined(SIMPLE_ISCAN)
+#define ISCAN_RETRY_CNT   5
+#define ISCAN_STATE_IDLE   0
+#define ISCAN_STATE_SCANING 1
+#define ISCAN_STATE_PENDING 2
+#endif /* SIMPLE_ISCAN */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#define ANTENNA_NUM_1	1		/* total number of antennas to be used */
+#define ANTENNA_NUM_2	2
+#define ANTENNA_NUM_3	3
+#define ANTENNA_NUM_4	4
+
+#define ANT_SELCFG_AUTO		0x80	/* bit indicates antenna sel AUTO */
+#define ANT_SELCFG_MASK		0x33	/* antenna configuration mask */
+#define ANT_SELCFG_TX_UNICAST	0	/* unicast tx antenna configuration */
+#define ANT_SELCFG_RX_UNICAST	1	/* unicast rx antenna configuration */
+#define ANT_SELCFG_TX_DEF	2	/* default tx antenna configuration */
+#define ANT_SELCFG_RX_DEF	3	/* default rx antenna configuration */
+
+/* interference source detection and identification mode */
+#define ITFR_MODE_DISABLE	0	/* disable feature */
+#define ITFR_MODE_MANUAL_ENABLE	1	/* enable manual detection */
+#define ITFR_MODE_AUTO_ENABLE	2	/* enable auto detection */
+
+/* bit definitions for flags in interference source report */
+#define ITFR_INTERFERENCED	1	/* interference detected */
+#define ITFR_HOME_CHANNEL	2	/* home channel has interference */
+#define ITFR_NOISY_ENVIRONMENT	4	/* noisy environemnt so feature stopped */
+
+#define WL_NUM_RPI_BINS		8
+#define WL_RM_TYPE_BASIC	1
+#define WL_RM_TYPE_CCA		2
+#define WL_RM_TYPE_RPI		3
+#define WL_RM_TYPE_ABORT	-1	/* ABORT any in-progress RM request */
+
+#define WL_RM_FLAG_PARALLEL	(1<<0)
+
+#define WL_RM_FLAG_LATE		(1<<1)
+#define WL_RM_FLAG_INCAPABLE	(1<<2)
+#define WL_RM_FLAG_REFUSED	(1<<3)
+
+/* flags */
+#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */
+
+#define WLC_CIS_DEFAULT	0	/* built-in default */
+#define WLC_CIS_SROM	1	/* source is sprom */
+#define WLC_CIS_OTP	2	/* source is otp */
+
+/* PCL - Power Control Loop */
+/* current gain setting is replaced by user input */
+#define WL_ATTEN_APP_INPUT_PCL_OFF	0	/* turn off PCL, apply supplied input */
+#define WL_ATTEN_PCL_ON			1	/* turn on PCL */
+/* current gain setting is maintained */
+#define WL_ATTEN_PCL_OFF		2	/* turn off PCL. */
+
+/* defines used by poweridx iovar - it controls power in a-band */
+/* current gain setting is maintained */
+#define WL_PWRIDX_PCL_OFF	-2	/* turn off PCL.  */
+#define WL_PWRIDX_PCL_ON	-1	/* turn on PCL */
+#define WL_PWRIDX_LOWER_LIMIT	-2	/* lower limit */
+#define WL_PWRIDX_UPPER_LIMIT	63	/* upper limit */
+/* value >= 0 causes
+ *	- input to be set to that value
+ *	- PCL to be off
+ */
+
+#define BCM_MAC_STATUS_INDICATION	(0x40010200L)
+
+/* Values for TX Filter override mode */
+#define WLC_TXFILTER_OVERRIDE_DISABLED  0
+#define WLC_TXFILTER_OVERRIDE_ENABLED   1
+
+/* magic pattern used for mismatch driver and wl */
+#define WL_TXFIFO_SZ_MAGIC	0xa5a5
+
+/* check this magic number */
+#define WLC_IOCTL_MAGIC		0x14e46c77
+
+
+/* bss_info_cap_t flags */
+#define WL_BSS_FLAGS_FROM_BEACON	0x01	/* bss_info derived from beacon */
+#define WL_BSS_FLAGS_FROM_CACHE		0x02	/* bss_info collected from cache */
+#define WL_BSS_FLAGS_RSSI_ONCHANNEL	0x04	/* rssi info received on channel (vs offchannel) */
+#define WL_BSS_FLAGS_HS20		0x08	/* hotspot 2.0 capable */
+#define WL_BSS_FLAGS_RSSI_INVALID	0x10	/* BSS contains invalid RSSI */
+#define WL_BSS_FLAGS_RSSI_INACCURATE	0x20	/* BSS contains inaccurate RSSI */
+#define WL_BSS_FLAGS_SNR_INVALID	0x40	/* BSS contains invalid SNR */
+#define WL_BSS_FLAGS_NF_INVALID		0x80	/* BSS contains invalid noise floor */
+
+/* bit definitions for bcnflags in wl_bss_info */
+#define WL_BSS_BCNFLAGS_INTERWORK_PRESENT	0x01 /* beacon had IE, accessnet valid */
+#define WL_BSS_BCNFLAGS_INTERWORK_PRESENT_VALID 0x02 /* on indicates support for this API */
+
+/* bssinfo flag for nbss_cap */
+#define VHT_BI_SGI_80MHZ			0x00000100
+#define VHT_BI_80MHZ			    0x00000200
+#define VHT_BI_160MHZ			    0x00000400
+#define VHT_BI_8080MHZ			    0x00000800
+
+/* reference to wl_ioctl_t struct used by usermode driver */
+#define ioctl_subtype	set		/* subtype param */
+#define ioctl_pid	used		/* pid param */
+#define ioctl_status	needed		/* status param */
+
+
+/* Enumerate crypto algorithms */
+#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_SMS4		11
+#define CRYPTO_ALGO_PMK			12	/* for 802.1x supp to set PMK before 4-way */
+#define CRYPTO_ALGO_BIP			13  /* 802.11w BIP (aes cmac) */
+
+#define CRYPTO_ALGO_AES_GCM     14  /* 128 bit GCM */
+#define CRYPTO_ALGO_AES_CCM256  15  /* 256 bit CCM */
+#define CRYPTO_ALGO_AES_GCM256  16  /* 256 bit GCM */
+#define CRYPTO_ALGO_BIP_CMAC256 17  /* 256 bit BIP CMAC */
+#define CRYPTO_ALGO_BIP_GMAC    18  /* 128 bit BIP GMAC */
+#define CRYPTO_ALGO_BIP_GMAC256 19  /* 256 bit BIP GMAC */
+
+#define CRYPTO_ALGO_NONE        CRYPTO_ALGO_OFF
+
+/* algo bit vector */
+#define KEY_ALGO_MASK(_algo)	(1 << _algo)
+
+
+#define KEY_ALGO_MASK_WEP		(KEY_ALGO_MASK(CRYPTO_ALGO_WEP1) | \
+					KEY_ALGO_MASK(CRYPTO_ALGO_WEP128) | \
+					KEY_ALGO_MASK(CRYPTO_ALGO_NALG))
+
+#define KEY_ALGO_MASK_AES		(KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM) | \
+					KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM256) | \
+					KEY_ALGO_MASK(CRYPTO_ALGO_AES_GCM) | \
+					KEY_ALGO_MASK(CRYPTO_ALGO_AES_GCM256))
+#define KEY_ALGO_MASK_TKIP		(KEY_ALGO_MASK(CRYPTO_ALGO_TKIP))
+#define KEY_ALGO_MASK_WAPI		(KEY_ALGO_MASK(CRYPTO_ALGO_SMS4))
+
+#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)	/* Indicates this key is using soft encrypt */
+#define WL_PRIMARY_KEY	(1 << 1)	/* Indicates this key is the primary (ie tx) key */
+#define WL_KF_RES_4	(1 << 4)	/* Reserved for backward compat */
+#define WL_KF_RES_5	(1 << 5)	/* Reserved for backward compat */
+#define WL_IBSS_PEER_GROUP_KEY	(1 << 6)	/* Indicates a group key for a IBSS PEER */
+
+/* wireless security bitvec */
+#define WEP_ENABLED		0x0001
+#define TKIP_ENABLED		0x0002
+#define AES_ENABLED		0x0004
+#define WSEC_SWFLAG		0x0008
+#define SES_OW_ENABLED		0x0040	/* to go into transition mode without setting wep */
+#ifdef WLFIPS
+#define FIPS_ENABLED	0x0080
+#endif /* WLFIPS */
+
+#ifdef DONGLEBUILD
+/* wsec macros for operating on the above definitions */
+#ifdef WLWSEC
+#define WSEC_WEP_ENABLED(wsec)	((wsec) & WEP_ENABLED)
+#define WSEC_TKIP_ENABLED(wsec)	((wsec) & TKIP_ENABLED)
+#define WSEC_AES_ENABLED(wsec)	((wsec) & AES_ENABLED)
+#else
+#define WSEC_WEP_ENABLED(wsec) NULL
+#define WSEC_TKIP_ENABLED(wsec) NULL
+#define WSEC_AES_ENABLED(wsec) NULL
+#endif /* WLWSEC */
+#else
+#define WSEC_WEP_ENABLED(wsec)	((wsec) & WEP_ENABLED)
+#define WSEC_TKIP_ENABLED(wsec)	((wsec) & TKIP_ENABLED)
+#define WSEC_AES_ENABLED(wsec)	((wsec) & AES_ENABLED)
+#endif /* DONGLEBUILD */
+
+#ifdef DONGLEBUILD
+#ifdef WLWSEC
+#define WSEC_ENABLED(wsec)	((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+#else
+#define WSEC_ENABLED(wsec) 0
+#endif /* WLWSEC */
+#else
+#define WSEC_ENABLED(wsec)	((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+#endif /* DONGLEBUILD */
+
+#define WSEC_SES_OW_ENABLED(wsec)	((wsec) & SES_OW_ENABLED)
+#ifdef BCMWAPI_WAI
+#define WSEC_SMS4_ENABLED(wsec)	((wsec) & SMS4_ENABLED)
+#endif /* BCMWAPI_WAI */
+
+
+/* Following macros are not used any more. Just kept here to
+ * avoid build issue in BISON/CARIBOU branch
+ */
+#define MFP_CAPABLE		0x0200
+#define MFP_REQUIRED	0x0400
+#define MFP_SHA256		0x0800 /* a special configuration for STA for WIFI test tool */
+
+/* WPA authentication mode bitvec */
+#define WPA_AUTH_DISABLED	0x0000	/* Legacy (i.e., non-WPA) */
+#define WPA_AUTH_NONE		0x0001	/* none (IBSS) */
+#define WPA_AUTH_UNSPECIFIED	0x0002	/* over 802.1x */
+#define WPA_AUTH_PSK		0x0004	/* Pre-shared key */
+/* #define WPA_AUTH_8021X 0x0020 */	/* 802.1x, reserved */
+#define WPA2_AUTH_UNSPECIFIED	0x0040	/* over 802.1x */
+#define WPA2_AUTH_PSK		0x0080	/* Pre-shared key */
+#define BRCM_AUTH_PSK           0x0100  /* BRCM specific PSK */
+#define BRCM_AUTH_DPT		0x0200	/* DPT PSK without group keys */
+#if defined(BCMWAPI_WAI)
+#define WPA_AUTH_WAPI           0x0400
+#define WAPI_AUTH_NONE		WPA_AUTH_NONE	/* none (IBSS) */
+#define WAPI_AUTH_UNSPECIFIED	0x0400	/* over AS */
+#define WAPI_AUTH_PSK		0x0800	/* Pre-shared key */
+#endif 
+#define WPA2_AUTH_1X_SHA256	0x1000  /* 1X with SHA256 key derivation */
+#define WPA2_AUTH_TPK		0x2000	/* TDLS Peer Key */
+#define WPA2_AUTH_FT		0x4000	/* Fast Transition. */
+#define WPA2_AUTH_PSK_SHA256	0x8000	/* PSK with SHA256 key derivation */
+/* WPA2_AUTH_SHA256 not used anymore. Just kept here to avoid build issue in DINGO */
+#define WPA2_AUTH_SHA256	0x8000
+#define WPA_AUTH_PFN_ANY	0xffffffff	/* for PFN, match only ssid */
+
+/* pmkid */
+#define	MAXPMKID		16
+
+/* SROM12 changes */
+#define	WLC_IOCTL_MAXLEN		8192	/* max length ioctl buffer required */
+
+
+#define	WLC_IOCTL_SMLEN			256	/* "small" length ioctl buffer required */
+#define WLC_IOCTL_MEDLEN		1536    /* "med" length ioctl buffer required */
+#if defined(LCNCONF) || defined(LCN40CONF) || defined(LCN20CONF)
+#define WLC_SAMPLECOLLECT_MAXLEN	8192	/* Max Sample Collect buffer */
+#else
+#define WLC_SAMPLECOLLECT_MAXLEN	10240	/* Max Sample Collect buffer for two cores */
+#endif
+#define WLC_SAMPLECOLLECT_MAXLEN_LCN40  8192
+
+/* common ioctl definitions */
+#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_OVERLAY_IOCTL			11 */ /* not supported */
+#define WLC_GET_RATE				12
+#define WLC_GET_MAX_RATE			13
+#define WLC_GET_INSTANCE			14
+/* #define WLC_GET_FRAG				15 */ /* no longer supported */
+/* #define WLC_SET_FRAG				16 */ /* no longer supported */
+/* #define WLC_GET_RTS				17 */ /* no longer supported */
+/* #define WLC_SET_RTS				18 */ /* no longer supported */
+#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_DUMP_SCB				28 */ /* no longer supported */
+#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_WEP				42 */ /* no longer supported */
+/* #define WLC_SET_WEP				43 */ /* no longer supported */
+#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	/* diag */
+#define WLC_GET_TXANT				61
+#define WLC_SET_TXANT				62
+#define WLC_GET_ANTDIV				63
+#define WLC_SET_ANTDIV				64
+/* #define WLC_GET_TXPWR			65 */ /* no longer supported */
+/* #define WLC_SET_TXPWR			66 */ /* no longer supported */
+#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_GET_LOCALE			73 */ /* no longer supported */
+#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_D11CNTS			89 */ /* -> "counters" iovar */
+#define WLC_GET_FORCELINK			90	/* ndis only */
+#define WLC_SET_FORCELINK			91	/* ndis only */
+#define WLC_FREQ_ACCURACY			92	/* diag */
+#define WLC_CARRIER_SUPPRESS			93	/* diag */
+#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_DIAG_LOOPBACK			103	old tray diag */
+/* #define WLC_RESET_D11CNTS			104 */ /* -> "reset_d11cnts" iovar */
+#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	/* current rateset */
+#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_BAND				141
+#define WLC_SET_BAND				142
+#define WLC_SCB_DEAUTHENTICATE			143
+#define WLC_GET_SHORTSLOT			144
+#define WLC_GET_SHORTSLOT_OVERRIDE		145
+#define WLC_SET_SHORTSLOT_OVERRIDE		146
+#define WLC_GET_SHORTSLOT_RESTRICT		147
+#define WLC_SET_SHORTSLOT_RESTRICT		148
+#define WLC_GET_GMODE_PROTECTION		149
+#define WLC_GET_GMODE_PROTECTION_OVERRIDE	150
+#define WLC_SET_GMODE_PROTECTION_OVERRIDE	151
+#define WLC_UPGRADE				152
+/* #define WLC_GET_MRATE			153 */ /* no longer supported */
+/* #define WLC_SET_MRATE			154 */ /* no longer supported */
+#define WLC_GET_IGNORE_BCNS			155
+#define WLC_SET_IGNORE_BCNS			156
+#define WLC_GET_SCB_TIMEOUT			157
+#define WLC_SET_SCB_TIMEOUT			158
+#define WLC_GET_ASSOCLIST			159
+#define WLC_GET_CLK				160
+#define WLC_SET_CLK				161
+#define WLC_GET_UP				162
+#define WLC_OUT					163
+#define WLC_GET_WPA_AUTH			164
+#define WLC_SET_WPA_AUTH			165
+#define WLC_GET_UCFLAGS				166
+#define WLC_SET_UCFLAGS				167
+#define WLC_GET_PWRIDX				168
+#define WLC_SET_PWRIDX				169
+#define WLC_GET_TSSI				170
+#define WLC_GET_SUP_RATESET_OVERRIDE		171
+#define WLC_SET_SUP_RATESET_OVERRIDE		172
+/* #define WLC_SET_FAST_TIMER			173 */ /* no longer supported */
+/* #define WLC_GET_FAST_TIMER			174 */ /* no longer supported */
+/* #define WLC_SET_SLOW_TIMER			175 */ /* no longer supported */
+/* #define WLC_GET_SLOW_TIMER			176 */ /* no longer supported */
+/* #define WLC_DUMP_PHYREGS			177 */ /* no longer supported */
+#define WLC_GET_PROTECTION_CONTROL		178
+#define WLC_SET_PROTECTION_CONTROL		179
+#define WLC_GET_PHYLIST				180
+#define WLC_ENCRYPT_STRENGTH			181	/* ndis only */
+#define WLC_DECRYPT_STATUS			182	/* ndis only */
+#define WLC_GET_KEY_SEQ				183
+#define WLC_GET_SCAN_CHANNEL_TIME		184
+#define WLC_SET_SCAN_CHANNEL_TIME		185
+#define WLC_GET_SCAN_UNASSOC_TIME		186
+#define WLC_SET_SCAN_UNASSOC_TIME		187
+#define WLC_GET_SCAN_HOME_TIME			188
+#define WLC_SET_SCAN_HOME_TIME			189
+#define WLC_GET_SCAN_NPROBES			190
+#define WLC_SET_SCAN_NPROBES			191
+#define WLC_GET_PRB_RESP_TIMEOUT		192
+#define WLC_SET_PRB_RESP_TIMEOUT		193
+#define WLC_GET_ATTEN				194
+#define WLC_SET_ATTEN				195
+#define WLC_GET_SHMEM				196	/* diag */
+#define WLC_SET_SHMEM				197	/* diag */
+/* #define WLC_GET_GMODE_PROTECTION_CTS		198 */ /* no longer supported */
+/* #define WLC_SET_GMODE_PROTECTION_CTS		199 */ /* no longer supported */
+#define WLC_SET_WSEC_TEST			200
+#define WLC_SCB_DEAUTHENTICATE_FOR_REASON	201
+#define WLC_TKIP_COUNTERMEASURES		202
+#define WLC_GET_PIOMODE				203
+#define WLC_SET_PIOMODE				204
+#define WLC_SET_ASSOC_PREFER			205
+#define WLC_GET_ASSOC_PREFER			206
+#define WLC_SET_ROAM_PREFER			207
+#define WLC_GET_ROAM_PREFER			208
+#define WLC_SET_LED				209
+#define WLC_GET_LED				210
+#define WLC_GET_INTERFERENCE_MODE		211
+#define WLC_SET_INTERFERENCE_MODE		212
+#define WLC_GET_CHANNEL_QA			213
+#define WLC_START_CHANNEL_QA			214
+#define WLC_GET_CHANNEL_SEL			215
+#define WLC_START_CHANNEL_SEL			216
+#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_SET_GLACIAL_TIMER		233 */ /* no longer supported */
+/* #define WLC_GET_GLACIAL_TIMER		234 */ /* no longer supported */
+#define WLC_GET_KEY_PRIMARY			235
+#define WLC_SET_KEY_PRIMARY			236
+
+
+/* #define WLC_DUMP_RADIOREGS			237 */ /* no longer supported */
+#define WLC_GET_ACI_ARGS			238
+#define WLC_SET_ACI_ARGS			239
+#define WLC_UNSET_CALLBACK			240
+#define WLC_SET_CALLBACK			241
+#define WLC_GET_RADAR				242
+#define WLC_SET_RADAR				243
+#define WLC_SET_SPECT_MANAGMENT			244
+#define WLC_GET_SPECT_MANAGMENT			245
+#define WLC_WDS_GET_REMOTE_HWADDR		246	/* handled in wl_linux.c/wl_vx.c */
+#define WLC_WDS_GET_WPA_SUP			247
+#define WLC_SET_CS_SCAN_TIMER			248
+#define WLC_GET_CS_SCAN_TIMER			249
+#define WLC_MEASURE_REQUEST			250
+#define WLC_INIT				251
+#define WLC_SEND_QUIET				252
+#define WLC_KEEPALIVE			253
+#define WLC_SEND_PWR_CONSTRAINT			254
+#define WLC_UPGRADE_STATUS			255
+#define WLC_CURRENT_PWR				256
+#define WLC_GET_SCAN_PASSIVE_TIME		257
+#define WLC_SET_SCAN_PASSIVE_TIME		258
+#define WLC_LEGACY_LINK_BEHAVIOR		259
+#define WLC_GET_CHANNELS_IN_COUNTRY		260
+#define WLC_GET_COUNTRY_LIST			261
+#define WLC_GET_VAR				262	/* get value of named variable */
+#define WLC_SET_VAR				263	/* set named variable to value */
+#define WLC_NVRAM_GET				264	/* deprecated */
+#define WLC_NVRAM_SET				265
+#define WLC_NVRAM_DUMP				266
+#define WLC_REBOOT				267
+#define WLC_SET_WSEC_PMK			268
+#define WLC_GET_AUTH_MODE			269
+#define WLC_SET_AUTH_MODE			270
+#define WLC_GET_WAKEENTRY			271
+#define WLC_SET_WAKEENTRY			272
+#define WLC_NDCONFIG_ITEM			273	/* currently handled in wl_oid.c */
+#define WLC_NVOTPW				274
+#define WLC_OTPW				275
+#define WLC_IOV_BLOCK_GET			276
+#define WLC_IOV_MODULES_GET			277
+#define WLC_SOFT_RESET				278
+#define WLC_GET_ALLOW_MODE			279
+#define WLC_SET_ALLOW_MODE			280
+#define WLC_GET_DESIRED_BSSID			281
+#define WLC_SET_DESIRED_BSSID			282
+#define	WLC_DISASSOC_MYAP			283
+#define WLC_GET_NBANDS				284	/* for Dongle EXT_STA support */
+#define WLC_GET_BANDSTATES			285	/* for Dongle EXT_STA support */
+#define WLC_GET_WLC_BSS_INFO			286	/* for Dongle EXT_STA support */
+#define WLC_GET_ASSOC_INFO			287	/* for Dongle EXT_STA support */
+#define WLC_GET_OID_PHY				288	/* for Dongle EXT_STA support */
+#define WLC_SET_OID_PHY				289	/* for Dongle EXT_STA support */
+#define WLC_SET_ASSOC_TIME			290	/* for Dongle EXT_STA support */
+#define WLC_GET_DESIRED_SSID			291	/* for Dongle EXT_STA support */
+#define WLC_GET_CHANSPEC			292	/* for Dongle EXT_STA support */
+#define WLC_GET_ASSOC_STATE			293	/* for Dongle EXT_STA support */
+#define WLC_SET_PHY_STATE			294	/* for Dongle EXT_STA support */
+#define WLC_GET_SCAN_PENDING			295	/* for Dongle EXT_STA support */
+#define WLC_GET_SCANREQ_PENDING			296	/* for Dongle EXT_STA support */
+#define WLC_GET_PREV_ROAM_REASON		297	/* for Dongle EXT_STA support */
+#define WLC_SET_PREV_ROAM_REASON		298	/* for Dongle EXT_STA support */
+#define WLC_GET_BANDSTATES_PI			299	/* for Dongle EXT_STA support */
+#define WLC_GET_PHY_STATE			300	/* for Dongle EXT_STA support */
+#define WLC_GET_BSS_WPA_RSN			301	/* for Dongle EXT_STA support */
+#define WLC_GET_BSS_WPA2_RSN			302	/* for Dongle EXT_STA support */
+#define WLC_GET_BSS_BCN_TS			303	/* for Dongle EXT_STA support */
+#define WLC_GET_INT_DISASSOC			304	/* for Dongle EXT_STA support */
+#define WLC_SET_NUM_PEERS			305     /* for Dongle EXT_STA support */
+#define WLC_GET_NUM_BSS				306	/* for Dongle EXT_STA support */
+#define WLC_PHY_SAMPLE_COLLECT			307	/* phy sample collect mode */
+/* #define WLC_UM_PRIV				308 */	/* Deprecated: usermode driver */
+#define WLC_GET_CMD				309
+/* #define WLC_LAST				310 */	/* Never used - can be reused */
+#define WLC_SET_INTERFERENCE_OVERRIDE_MODE	311	/* set inter mode override */
+#define WLC_GET_INTERFERENCE_OVERRIDE_MODE	312	/* get inter mode override */
+/* #define WLC_GET_WAI_RESTRICT	313 */
+/* #define WLC_SET_WAI_RESTRICT	314 */
+/* #define WLC_SET_WAI_REKEY	315 */
+#define WLC_SET_NAT_CONFIG			316	/* for configuring NAT filter driver */
+#define WLC_GET_NAT_STATE			317
+#define WLC_GET_TXBF_RATESET			318
+#define WLC_SET_TXBF_RATESET			319
+#define WLC_SCAN_CQ				320
+#define WLC_GET_RSSI_QDB			321 /* qdB portion of the RSSI */
+#define WLC_DUMP_RATESET			322
+#define WLC_ECHO				323
+#define WLC_LAST				324
+#ifndef EPICTRL_COOKIE
+#define EPICTRL_COOKIE		0xABADCEDE
+#endif
+
+/* vx wlc ioctl's offset */
+#define CMN_IOCTL_OFF 0x180
+
+/*
+ * custom OID support
+ *
+ * 0xFF - implementation specific OID
+ * 0xE4 - first byte of Broadcom PCI vendor ID
+ * 0x14 - second byte of Broadcom PCI vendor ID
+ * 0xXX - the custom OID number
+ */
+
+/* begin 0x1f values beyond the start of the ET driver range. */
+#define WL_OID_BASE		0xFFE41420
+
+/* NDIS overrides */
+#define OID_WL_GETINSTANCE	(WL_OID_BASE + WLC_GET_INSTANCE)
+#define OID_WL_GET_FORCELINK	(WL_OID_BASE + WLC_GET_FORCELINK)
+#define OID_WL_SET_FORCELINK	(WL_OID_BASE + WLC_SET_FORCELINK)
+#define	OID_WL_ENCRYPT_STRENGTH	(WL_OID_BASE + WLC_ENCRYPT_STRENGTH)
+#define OID_WL_DECRYPT_STATUS	(WL_OID_BASE + WLC_DECRYPT_STATUS)
+#define OID_LEGACY_LINK_BEHAVIOR (WL_OID_BASE + WLC_LEGACY_LINK_BEHAVIOR)
+#define OID_WL_NDCONFIG_ITEM	(WL_OID_BASE + WLC_NDCONFIG_ITEM)
+
+/* EXT_STA Dongle suuport */
+#define OID_STA_CHANSPEC	(WL_OID_BASE + WLC_GET_CHANSPEC)
+#define OID_STA_NBANDS		(WL_OID_BASE + WLC_GET_NBANDS)
+#define OID_STA_GET_PHY		(WL_OID_BASE + WLC_GET_OID_PHY)
+#define OID_STA_SET_PHY		(WL_OID_BASE + WLC_SET_OID_PHY)
+#define OID_STA_ASSOC_TIME	(WL_OID_BASE + WLC_SET_ASSOC_TIME)
+#define OID_STA_DESIRED_SSID	(WL_OID_BASE + WLC_GET_DESIRED_SSID)
+#define OID_STA_SET_PHY_STATE	(WL_OID_BASE + WLC_SET_PHY_STATE)
+#define OID_STA_SCAN_PENDING	(WL_OID_BASE + WLC_GET_SCAN_PENDING)
+#define OID_STA_SCANREQ_PENDING (WL_OID_BASE + WLC_GET_SCANREQ_PENDING)
+#define OID_STA_GET_ROAM_REASON (WL_OID_BASE + WLC_GET_PREV_ROAM_REASON)
+#define OID_STA_SET_ROAM_REASON (WL_OID_BASE + WLC_SET_PREV_ROAM_REASON)
+#define OID_STA_GET_PHY_STATE	(WL_OID_BASE + WLC_GET_PHY_STATE)
+#define OID_STA_INT_DISASSOC	(WL_OID_BASE + WLC_GET_INT_DISASSOC)
+#define OID_STA_SET_NUM_PEERS	(WL_OID_BASE + WLC_SET_NUM_PEERS)
+#define OID_STA_GET_NUM_BSS	(WL_OID_BASE + WLC_GET_NUM_BSS)
+
+/* NAT filter driver support */
+#define OID_NAT_SET_CONFIG	(WL_OID_BASE + WLC_SET_NAT_CONFIG)
+#define OID_NAT_GET_STATE	(WL_OID_BASE + WLC_GET_NAT_STATE)
+
+#define WL_DECRYPT_STATUS_SUCCESS	1
+#define WL_DECRYPT_STATUS_FAILURE	2
+#define WL_DECRYPT_STATUS_UNKNOWN	3
+
+/* allows user-mode app to poll the status of USB image upgrade */
+#define WLC_UPGRADE_SUCCESS			0
+#define WLC_UPGRADE_PENDING			1
+
+/* WLC_GET_AUTH, WLC_SET_AUTH values */
+#define WL_AUTH_OPEN_SYSTEM		0	/* d11 open authentication */
+#define WL_AUTH_SHARED_KEY		1	/* d11 shared authentication */
+#define WL_AUTH_OPEN_SHARED		2	/* try open, then shared if open failed w/rc 13 */
+
+/* a large TX Power as an init value to factor out of MIN() calculations,
+ * keep low enough to fit in an int8, units are .25 dBm
+ */
+#define WLC_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
+
+/* "diag" iovar argument and error code */
+#define WL_DIAG_INTERRUPT			1	/* d11 loopback interrupt test */
+#define WL_DIAG_LOOPBACK			2	/* d11 loopback data test */
+#define WL_DIAG_MEMORY				3	/* d11 memory test */
+#define WL_DIAG_LED				4	/* LED test */
+#define WL_DIAG_REG				5	/* d11/phy register test */
+#define WL_DIAG_SROM				6	/* srom read/crc test */
+#define WL_DIAG_DMA				7	/* DMA test */
+#define WL_DIAG_LOOPBACK_EXT			8	/* enhenced d11 loopback data test */
+
+#define WL_DIAGERR_SUCCESS			0
+#define WL_DIAGERR_FAIL_TO_RUN			1	/* unable to run requested diag */
+#define WL_DIAGERR_NOT_SUPPORTED		2	/* diag requested is not supported */
+#define WL_DIAGERR_INTERRUPT_FAIL		3	/* loopback interrupt test failed */
+#define WL_DIAGERR_LOOPBACK_FAIL		4	/* loopback data test failed */
+#define WL_DIAGERR_SROM_FAIL			5	/* srom read failed */
+#define WL_DIAGERR_SROM_BADCRC			6	/* srom crc failed */
+#define WL_DIAGERR_REG_FAIL			7	/* d11/phy register test failed */
+#define WL_DIAGERR_MEMORY_FAIL			8	/* d11 memory test failed */
+#define WL_DIAGERR_NOMEM			9	/* diag test failed due to no memory */
+#define WL_DIAGERR_DMA_FAIL			10	/* DMA test failed */
+
+#define WL_DIAGERR_MEMORY_TIMEOUT		11	/* d11 memory test didn't finish in time */
+#define WL_DIAGERR_MEMORY_BADPATTERN		12	/* d11 memory test result in bad pattern */
+
+/* band types */
+#define	WLC_BAND_AUTO		0	/* auto-select */
+#define	WLC_BAND_5G		1	/* 5 Ghz */
+#define	WLC_BAND_2G		2	/* 2.4 Ghz */
+#define	WLC_BAND_ALL		3	/* all bands */
+#define WLC_BAND_INVALID	-1	/* Invalid band */
+
+/* band range returned by band_range iovar */
+#define WL_CHAN_FREQ_RANGE_2G      0
+#define WL_CHAN_FREQ_RANGE_5GL     1
+#define WL_CHAN_FREQ_RANGE_5GM     2
+#define WL_CHAN_FREQ_RANGE_5GH     3
+
+#define WL_CHAN_FREQ_RANGE_5GLL_5BAND    4
+#define WL_CHAN_FREQ_RANGE_5GLH_5BAND    5
+#define WL_CHAN_FREQ_RANGE_5GML_5BAND    6
+#define WL_CHAN_FREQ_RANGE_5GMH_5BAND    7
+#define WL_CHAN_FREQ_RANGE_5GH_5BAND     8
+
+#define WL_CHAN_FREQ_RANGE_5G_BAND0     1
+#define WL_CHAN_FREQ_RANGE_5G_BAND1     2
+#define WL_CHAN_FREQ_RANGE_5G_BAND2     3
+#define WL_CHAN_FREQ_RANGE_5G_BAND3     4
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_CHAN_FREQ_RANGE_5G_4BAND     5
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* SROM12 */
+#define WL_CHAN_FREQ_RANGE_5G_BAND4 5
+#define WL_CHAN_FREQ_RANGE_2G_40 6
+#define WL_CHAN_FREQ_RANGE_5G_BAND0_40 7
+#define WL_CHAN_FREQ_RANGE_5G_BAND1_40 8
+#define WL_CHAN_FREQ_RANGE_5G_BAND2_40 9
+#define WL_CHAN_FREQ_RANGE_5G_BAND3_40 10
+#define WL_CHAN_FREQ_RANGE_5G_BAND4_40 11
+#define WL_CHAN_FREQ_RANGE_5G_BAND0_80 12
+#define WL_CHAN_FREQ_RANGE_5G_BAND1_80 13
+#define WL_CHAN_FREQ_RANGE_5G_BAND2_80 14
+#define WL_CHAN_FREQ_RANGE_5G_BAND3_80 15
+#define WL_CHAN_FREQ_RANGE_5G_BAND4_80 16
+
+#define WL_CHAN_FREQ_RANGE_5G_5BAND	18
+#define WL_CHAN_FREQ_RANGE_5G_5BAND_40	19
+#define WL_CHAN_FREQ_RANGE_5G_5BAND_80	20
+
+#define WLC_MACMODE_DISABLED	0	/* MAC list disabled */
+#define WLC_MACMODE_DENY	1	/* Deny specified (i.e. allow unspecified) */
+#define WLC_MACMODE_ALLOW	2	/* Allow specified (i.e. deny unspecified) */
+
+/*
+ * 54g modes (basic bits may still be overridden)
+ *
+ * GMODE_LEGACY_B			Rateset: 1b, 2b, 5.5, 11
+ *					Preamble: Long
+ *					Shortslot: Off
+ * GMODE_AUTO				Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ *					Extended Rateset: 6, 9, 12, 48
+ *					Preamble: Long
+ *					Shortslot: Auto
+ * GMODE_ONLY				Rateset: 1b, 2b, 5.5b, 11b, 18, 24b, 36, 54
+ *					Extended Rateset: 6b, 9, 12b, 48
+ *					Preamble: Short required
+ *					Shortslot: Auto
+ * GMODE_B_DEFERRED			Rateset: 1b, 2b, 5.5b, 11b, 18, 24, 36, 54
+ *					Extended Rateset: 6, 9, 12, 48
+ *					Preamble: Long
+ *					Shortslot: On
+ * GMODE_PERFORMANCE			Rateset: 1b, 2b, 5.5b, 6b, 9, 11b, 12b, 18, 24b, 36, 48, 54
+ *					Preamble: Short required
+ *					Shortslot: On and required
+ * GMODE_LRS				Rateset: 1b, 2b, 5.5b, 11b
+ *					Extended Rateset: 6, 9, 12, 18, 24, 36, 48, 54
+ *					Preamble: Long
+ *					Shortslot: Auto
+ */
+#define GMODE_LEGACY_B		0
+#define GMODE_AUTO		1
+#define GMODE_ONLY		2
+#define GMODE_B_DEFERRED	3
+#define GMODE_PERFORMANCE	4
+#define GMODE_LRS		5
+#define GMODE_MAX		6
+
+/* values for PLCPHdr_override */
+#define WLC_PLCP_AUTO	-1
+#define WLC_PLCP_SHORT	0
+#define WLC_PLCP_LONG	1
+
+/* values for g_protection_override and n_protection_override */
+#define WLC_PROTECTION_AUTO		-1
+#define WLC_PROTECTION_OFF		0
+#define WLC_PROTECTION_ON		1
+#define WLC_PROTECTION_MMHDR_ONLY	2
+#define WLC_PROTECTION_CTS_ONLY		3
+
+/* values for g_protection_control and n_protection_control */
+#define WLC_PROTECTION_CTL_OFF		0
+#define WLC_PROTECTION_CTL_LOCAL	1
+#define WLC_PROTECTION_CTL_OVERLAP	2
+
+/* values for n_protection */
+#define WLC_N_PROTECTION_OFF		0
+#define WLC_N_PROTECTION_OPTIONAL	1
+#define WLC_N_PROTECTION_20IN40		2
+#define WLC_N_PROTECTION_MIXEDMODE	3
+
+/* values for n_preamble_type */
+#define WLC_N_PREAMBLE_MIXEDMODE	0
+#define WLC_N_PREAMBLE_GF		1
+#define WLC_N_PREAMBLE_GF_BRCM          2
+
+/* values for band specific 40MHz capabilities (deprecated) */
+#define WLC_N_BW_20ALL			0
+#define WLC_N_BW_40ALL			1
+#define WLC_N_BW_20IN2G_40IN5G		2
+
+#define WLC_BW_20MHZ_BIT		(1<<0)
+#define WLC_BW_40MHZ_BIT		(1<<1)
+#define WLC_BW_80MHZ_BIT		(1<<2)
+#define WLC_BW_160MHZ_BIT		(1<<3)
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WLC_BW_10MHZ_BIT		(1<<4)
+#define WLC_BW_5MHZ_BIT			(1<<5)
+#define WLC_BW_2P5MHZ_BIT		(1<<6)
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/* Bandwidth capabilities */
+#define WLC_BW_CAP_20MHZ		(WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_40MHZ		(WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_80MHZ		(WLC_BW_80MHZ_BIT|WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#define WLC_BW_CAP_160MHZ		(WLC_BW_160MHZ_BIT|WLC_BW_80MHZ_BIT| \
+	WLC_BW_40MHZ_BIT|WLC_BW_20MHZ_BIT)
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WLC_BW_CAP_2P5MHZ		(WLC_BW_2P5MHZ_BIT)
+#define WLC_BW_CAP_5MHZ			(WLC_BW_5MHZ_BIT)
+#define WLC_BW_CAP_10MHZ		(WLC_BW_10MHZ_BIT)
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WLC_BW_CAP_UNRESTRICTED		0xFF
+
+#define WL_BW_CAP_20MHZ(bw_cap)	(((bw_cap) & WLC_BW_20MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_40MHZ(bw_cap)	(((bw_cap) & WLC_BW_40MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_80MHZ(bw_cap)	(((bw_cap) & WLC_BW_80MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_160MHZ(bw_cap)(((bw_cap) & WLC_BW_160MHZ_BIT) ? TRUE : FALSE)
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_BW_CAP_2P5MHZ(bw_cap)(((bw_cap) & WLC_BW_2P5MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_5MHZ(bw_cap)	(((bw_cap) & WLC_BW_5MHZ_BIT) ? TRUE : FALSE)
+#define WL_BW_CAP_10MHZ(bw_cap)	(((bw_cap) & WLC_BW_10MHZ_BIT) ? TRUE : FALSE)
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/* values to force tx/rx chain */
+#define WLC_N_TXRX_CHAIN0		0
+#define WLC_N_TXRX_CHAIN1		1
+
+/* bitflags for SGI support (sgi_rx iovar) */
+#define WLC_N_SGI_20			0x01
+#define WLC_N_SGI_40			0x02
+#define WLC_VHT_SGI_80			0x04
+#define WLC_VHT_SGI_160			0x08
+
+/* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */
+#define WLC_SGI_ALL				0x02
+
+#define LISTEN_INTERVAL			10
+/* interference mitigation options */
+#define	INTERFERE_OVRRIDE_OFF	-1	/* interference override off */
+#define	INTERFERE_NONE	0	/* off */
+#define	NON_WLAN	1	/* foreign/non 802.11 interference, no auto detect */
+#define	WLAN_MANUAL	2	/* ACI: no auto detection */
+#define	WLAN_AUTO	3	/* ACI: auto detect */
+#define	WLAN_AUTO_W_NOISE	4	/* ACI: auto - detect and non 802.11 interference */
+#define AUTO_ACTIVE	(1 << 7) /* Auto is currently active */
+
+/* interfernece mode bit-masks (ACPHY) */
+#define ACPHY_ACI_GLITCHBASED_DESENSE 1   /* bit 0 */
+#define ACPHY_ACI_HWACI_PKTGAINLMT 2      /* bit 1 */
+#define ACPHY_ACI_W2NB_PKTGAINLMT 4       /* bit 2 */
+#define ACPHY_ACI_PREEMPTION 8            /* bit 3 */
+#define ACPHY_HWACI_MITIGATION 16         /* bit 4 */
+#define ACPHY_LPD_PREEMPTION 32           /* bit 5 */
+#define ACPHY_HWOBSS_MITIGATION 64        /* bit 6 */
+#define ACPHY_ACI_MAX_MODE 127
+
+/* AP environment */
+#define AP_ENV_DETECT_NOT_USED		0 /* We aren't using AP environment detection */
+#define AP_ENV_DENSE			1 /* "Corporate" or other AP dense environment */
+#define AP_ENV_SPARSE			2 /* "Home" or other sparse environment */
+#define AP_ENV_INDETERMINATE		3 /* AP environment hasn't been identified */
+
+#define TRIGGER_NOW				0
+#define TRIGGER_CRS				0x01
+#define TRIGGER_CRSDEASSERT			0x02
+#define TRIGGER_GOODFCS				0x04
+#define TRIGGER_BADFCS				0x08
+#define TRIGGER_BADPLCP				0x10
+#define TRIGGER_CRSGLITCH			0x20
+
+#define	WL_SAMPLEDATA_HEADER_TYPE	1
+#define WL_SAMPLEDATA_HEADER_SIZE	80	/* sample collect header size (bytes) */
+#define	WL_SAMPLEDATA_TYPE		2
+#define	WL_SAMPLEDATA_SEQ		0xff	/* sequence # */
+#define	WL_SAMPLEDATA_MORE_DATA		0x100	/* more data mask */
+
+/* WL_OTA START */
+#define WL_OTA_ARG_PARSE_BLK_SIZE	1200
+#define WL_OTA_TEST_MAX_NUM_RATE	30
+#define WL_OTA_TEST_MAX_NUM_SEQ		100
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_OTA_TEST_MAX_NUM_RSSI	85
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WL_THRESHOLD_LO_BAND	70	/* range from 5250MHz - 5350MHz */
+
+/* radar iovar SET defines */
+#define WL_RADAR_DETECTOR_OFF		0	/* radar detector off */
+#define WL_RADAR_DETECTOR_ON		1	/* radar detector on */
+#define WL_RADAR_SIMULATED		2	/* force radar detector to declare
+						 * detection once
+						 */
+#define WL_RADAR_SIMULATED_SC		3	/* force radar detector to declare
+						 * detection once on scan core
+						 * if available and active
+						 */
+#define WL_RSSI_ANT_VERSION	1	/* current version of wl_rssi_ant_t */
+#define WL_ANT_RX_MAX		2	/* max 2 receive antennas */
+#define WL_ANT_HT_RX_MAX	4	/* max 4 receive antennas/cores */
+#define WL_ANT_IDX_1		0	/* antenna index 1 */
+#define WL_ANT_IDX_2		1	/* antenna index 2 */
+
+#ifndef WL_RSSI_ANT_MAX
+#define WL_RSSI_ANT_MAX		4	/* max possible rx antennas */
+#elif WL_RSSI_ANT_MAX != 4
+#error "WL_RSSI_ANT_MAX does not match"
+#endif
+
+/* dfs_status iovar-related defines */
+
+/* cac - channel availability check,
+ * ism - in-service monitoring
+ * csa - channel switching announcement
+ */
+
+/* cac state values */
+#define WL_DFS_CACSTATE_IDLE		0	/* state for operating in non-radar channel */
+#define	WL_DFS_CACSTATE_PREISM_CAC	1	/* CAC in progress */
+#define WL_DFS_CACSTATE_ISM		2	/* ISM in progress */
+#define WL_DFS_CACSTATE_CSA		3	/* csa */
+#define WL_DFS_CACSTATE_POSTISM_CAC	4	/* ISM CAC */
+#define WL_DFS_CACSTATE_PREISM_OOC	5	/* PREISM OOC */
+#define WL_DFS_CACSTATE_POSTISM_OOC	6	/* POSTISM OOC */
+#define WL_DFS_CACSTATES		7	/* this many states exist */
+
+/* Defines used with channel_bandwidth for curpower */
+#define WL_BW_20MHZ		0
+#define WL_BW_40MHZ		1
+#define WL_BW_80MHZ		2
+#define WL_BW_160MHZ		3
+#define WL_BW_8080MHZ		4
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_BW_2P5MHZ		5
+#define WL_BW_5MHZ		6
+#define WL_BW_10MHZ		7
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* tx_power_t.flags bits */
+#define WL_TX_POWER_F_ENABLED	1
+#define WL_TX_POWER_F_HW		2
+#define WL_TX_POWER_F_MIMO		4
+#define WL_TX_POWER_F_SISO		8
+#define WL_TX_POWER_F_HT		0x10
+#define WL_TX_POWER_F_VHT		0x20
+#define WL_TX_POWER_F_OPENLOOP		0x40
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_TX_POWER_F_PROP11NRATES	0x80
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WL_TX_POWER_F_UNIT_QDBM		0x100
+/* Message levels */
+#define WL_ERROR_VAL		0x00000001
+#define WL_TRACE_VAL		0x00000002
+#define WL_PRHDRS_VAL		0x00000004
+#define WL_PRPKT_VAL		0x00000008
+#define WL_INFORM_VAL		0x00000010
+#define WL_TMP_VAL		0x00000020
+#define WL_OID_VAL		0x00000040
+#define WL_RATE_VAL		0x00000080
+#define WL_ASSOC_VAL		0x00000100
+#define WL_PRUSR_VAL		0x00000200
+#define WL_PS_VAL		0x00000400
+#define WL_TXPWR_VAL		0x00000000	/* retired in TOT on 6/10/2009 */
+#define WL_MODE_SWITCH_VAL	0x00000800 /* Using retired TXPWR val */
+#define WL_PORT_VAL		0x00001000
+#define WL_DUAL_VAL		0x00002000
+#define WL_WSEC_VAL		0x00004000
+#define WL_WSEC_DUMP_VAL	0x00008000
+#define WL_LOG_VAL		0x00010000
+#define WL_NRSSI_VAL		0x00000000	/* retired in TOT on 6/10/2009 */
+#define WL_BCNTRIM_VAL		0x00020000	/* Using retired NRSSI VAL */
+#define WL_LOFT_VAL		0x00000000	/* retired in TOT on 6/10/2009 */
+#define WL_PFN_VAL		0x00040000 /* Using retired LOFT_VAL */
+#define WL_REGULATORY_VAL	0x00080000
+#define WL_CSA_VAL		0x00080000  /* Reusing REGULATORY_VAL due to lackof bits */
+#define WL_TAF_VAL		0x00100000
+#define WL_RADAR_VAL		0x00000000	/* retired in TOT on 6/10/2009 */
+#define WL_WDI_VAL		0x00200000	/* Using retired WL_RADAR_VAL VAL */
+#define WL_MPC_VAL		0x00400000
+#define WL_APSTA_VAL		0x00800000
+#define WL_DFS_VAL		0x01000000
+#define WL_BA_VAL		0x00000000	/* retired in TOT on 6/14/2010 */
+#define WL_MUMIMO_VAL		0x02000000      /* Using retired WL_BA_VAL */
+#define WL_ACI_VAL		0x04000000
+#define WL_PRMAC_VAL		0x04000000
+#define WL_MBSS_VAL		0x04000000
+#define WL_CAC_VAL		0x08000000
+#define WL_AMSDU_VAL		0x10000000
+#define WL_AMPDU_VAL		0x20000000
+#define WL_FFPLD_VAL		0x40000000
+#define WL_ROAM_EXP_VAL		0x80000000
+
+/* wl_msg_level is full. For new bits take the next one and AND with
+ * wl_msg_level2 in wl_dbg.h
+ */
+#define WL_DPT_VAL		0x00000001
+/* re-using WL_DPT_VAL */
+/* re-using WL_MESH_VAL */
+#define WL_NATOE_VAL		0x00000001
+#define WL_MESH_VAL		0x00000001
+#define WL_SCAN_VAL		0x00000002
+#define WL_WOWL_VAL		0x00000004
+#define WL_COEX_VAL		0x00000008
+#define WL_RTDC_VAL		0x00000010
+#define WL_PROTO_VAL		0x00000020
+#define WL_CHANINT_VAL		0x00000080
+#define WL_WMF_VAL		0x00000100
+#define WL_P2P_VAL		0x00000200
+#define WL_ITFR_VAL		0x00000400
+#define WL_MCHAN_VAL		0x00000800
+#define WL_TDLS_VAL		0x00001000
+#define WL_MCNX_VAL		0x00002000
+#define WL_PROT_VAL		0x00004000
+#define WL_PSTA_VAL		0x00008000
+#define WL_TSO_VAL		0x00010000
+#define WL_TRF_MGMT_VAL		0x00020000
+#define WL_LPC_VAL	        0x00040000
+#define WL_L2FILTER_VAL		0x00080000
+#define WL_TXBF_VAL		0x00100000
+#define WL_P2PO_VAL		0x00200000
+#define WL_TBTT_VAL		0x00400000
+#define WL_FBT_VAL		0x00800000
+#define WL_RRM_VAL		0x00800000 /* reuse */
+#define WL_MQ_VAL		0x01000000
+
+/* This level is currently used in Phoenix2 only */
+#define WL_SRSCAN_VAL		0x02000000
+
+#define WL_WNM_VAL		0x04000000
+/* re-using WL_WNM_VAL for MBO */
+#define WL_MBO_VAL		0x04000000
+#define WL_PWRSEL_VAL		0x10000000
+#define WL_NET_DETECT_VAL	0x20000000
+#define WL_PCIE_VAL		0x40000000
+#define WL_PMDUR_VAL	0x80000000
+
+
+/* use top-bit for WL_TIME_STAMP_VAL because this is a modifier
+ * rather than a message-type of its own
+ */
+#define WL_TIMESTAMP_VAL        0x80000000
+
+/* max # of leds supported by GPIO (gpio pin# == led index#) */
+#define	WL_LED_NUMGPIO		32	/* gpio 0-31 */
+
+/* led per-pin behaviors */
+#define	WL_LED_OFF		0		/* always off */
+#define	WL_LED_ON		1		/* always on */
+#define	WL_LED_ACTIVITY		2		/* activity */
+#define	WL_LED_RADIO		3		/* radio enabled */
+#define	WL_LED_ARADIO		4		/* 5  Ghz radio enabled */
+#define	WL_LED_BRADIO		5		/* 2.4Ghz radio enabled */
+#define	WL_LED_BGMODE		6		/* on if gmode, off if bmode */
+#define	WL_LED_WI1		7
+#define	WL_LED_WI2		8
+#define	WL_LED_WI3		9
+#define	WL_LED_ASSOC		10		/* associated state indicator */
+#define	WL_LED_INACTIVE		11		/* null behavior (clears default behavior) */
+#define	WL_LED_ASSOCACT		12		/* on when associated; blink fast for activity */
+#define WL_LED_WI4		13
+#define WL_LED_WI5		14
+#define	WL_LED_BLINKSLOW	15		/* blink slow */
+#define	WL_LED_BLINKMED		16		/* blink med */
+#define	WL_LED_BLINKFAST	17		/* blink fast */
+#define	WL_LED_BLINKCUSTOM	18		/* blink custom */
+#define	WL_LED_BLINKPERIODIC	19		/* blink periodic (custom 1000ms / off 400ms) */
+#define WL_LED_ASSOC_WITH_SEC	20		/* when connected with security */
+						/* keep on for 300 sec */
+#define WL_LED_START_OFF	21		/* off upon boot, could be turned on later */
+#define WL_LED_WI6		22
+#define WL_LED_WI7		23
+#define WL_LED_WI8		24
+#define	WL_LED_NUMBEHAVIOR	25
+
+/* led behavior numeric value format */
+#define	WL_LED_BEH_MASK		0x3f		/* behavior mask */
+#define	WL_LED_PMU_OVERRIDE	0x40		/* need to set PMU Override bit for the GPIO */
+#define	WL_LED_AL_MASK		0x80		/* activelow (polarity) bit */
+
+/* number of bytes needed to define a proper bit mask for MAC event reporting */
+#define BCMIO_ROUNDUP(x, y)	((((x) + ((y) - 1)) / (y)) * (y))
+#define BCMIO_NBBY		8
+#define WL_EVENTING_MASK_LEN	16
+
+#define WL_EVENTING_MASK_EXT_LEN \
+    MAX(WL_EVENTING_MASK_LEN, (ROUNDUP(WLC_E_LAST, NBBY)/NBBY))
+
+/* join preference types */
+#define WL_JOIN_PREF_RSSI	1	/* by RSSI */
+#define WL_JOIN_PREF_WPA	2	/* by akm and ciphers */
+#define WL_JOIN_PREF_BAND	3	/* by 802.11 band */
+#define WL_JOIN_PREF_RSSI_DELTA	4	/* by 802.11 band only if RSSI delta condition matches */
+#define WL_JOIN_PREF_TRANS_PREF	5	/* defined by requesting AP */
+
+/* band preference */
+#define WLJP_BAND_ASSOC_PREF	255	/* use what WLC_SET_ASSOC_PREFER ioctl specifies */
+
+/* any multicast cipher suite */
+#define WL_WPA_ACP_MCS_ANY	"\x00\x00\x00\x00"
+
+/* 802.11h measurement types */
+#define WLC_MEASURE_TPC			1
+#define WLC_MEASURE_CHANNEL_BASIC	2
+#define WLC_MEASURE_CHANNEL_CCA		3
+#define WLC_MEASURE_CHANNEL_RPI		4
+
+/* regulatory enforcement levels */
+#define SPECT_MNGMT_OFF			0		/* both 11h and 11d disabled */
+#define SPECT_MNGMT_LOOSE_11H		1		/* allow non-11h APs in scan lists */
+#define SPECT_MNGMT_STRICT_11H		2		/* prune out non-11h APs from scan list */
+#define SPECT_MNGMT_STRICT_11D		3		/* switch to 802.11D mode */
+/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE
+ * adoption is done regardless of capability spectrum_management
+ */
+#define SPECT_MNGMT_LOOSE_11H_D		4		/* operation defined above */
+
+/* bit position in per_chan_info; these depend on current country/regulatory domain */
+#define WL_CHAN_VALID_HW		(1 << 0)	/* valid with current HW */
+#define WL_CHAN_VALID_SW		(1 << 1)	/* valid with current country setting */
+#define WL_CHAN_BAND_5G			(1 << 2)	/* 5GHz-band channel */
+#define WL_CHAN_RADAR			(1 << 3)	/* radar sensitive channel */
+#define WL_CHAN_INACTIVE		(1 << 4)	/* temporarily inactive due to radar */
+#define WL_CHAN_PASSIVE			(1 << 5)	/* channel is in passive mode */
+#define WL_CHAN_RESTRICTED		(1 << 6)	/* restricted use channel */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_CHAN_RADAR_EU_WEATHER	(1 << 7)	/* EU Radar weather channel. Implies an
+							 * EU Radar channel.
+							 */
+/* following definition is for precommit; will be removed once wl, acsd switch to the new def */
+#define WL_CHAN_WEATHER_RADAR		WL_CHAN_RADAR_EU_WEATHER
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* BTC mode used by "btc_mode" iovar */
+#define	WL_BTC_DISABLE		0	/* disable BT coexistence */
+#define WL_BTC_FULLTDM      1	/* full TDM COEX */
+#define WL_BTC_ENABLE       1	/* full TDM COEX to maintain backward compatiblity */
+#define WL_BTC_PREMPT      2    /* full TDM COEX with preemption */
+#define WL_BTC_LITE        3	/* light weight coex for large isolation platform */
+#define WL_BTC_PARALLEL		4   /* BT and WLAN run in parallel with separate antenna  */
+#define WL_BTC_HYBRID		5   /* hybrid coex, only ack is allowed to transmit in BT slot */
+#define WL_BTC_DEFAULT		8	/* set the default mode for the device */
+#define WL_INF_BTC_DISABLE      0
+#define WL_INF_BTC_ENABLE       1
+#define WL_INF_BTC_AUTO         3
+
+/* BTC wire used by "btc_wire" iovar */
+#define	WL_BTC_DEFWIRE		0	/* use default wire setting */
+#define WL_BTC_2WIRE		2	/* use 2-wire BTC */
+#define WL_BTC_3WIRE		3	/* use 3-wire BTC */
+#define WL_BTC_4WIRE		4	/* use 4-wire BTC */
+
+/* BTC flags: BTC configuration that can be set by host */
+#define WL_BTC_FLAG_PREMPT               (1 << 0)
+#define WL_BTC_FLAG_BT_DEF               (1 << 1)
+#define WL_BTC_FLAG_ACTIVE_PROT          (1 << 2)
+#define WL_BTC_FLAG_SIM_RSP              (1 << 3)
+#define WL_BTC_FLAG_PS_PROTECT           (1 << 4)
+#define WL_BTC_FLAG_SIM_TX_LP	         (1 << 5)
+#define WL_BTC_FLAG_ECI                  (1 << 6)
+#define WL_BTC_FLAG_LIGHT                (1 << 7)
+#define WL_BTC_FLAG_PARALLEL             (1 << 8)
+
+/* maximum channels returned by the get valid channels iovar */
+#define WL_NUMCHANNELS		64
+
+/* max number of chanspecs (used by the iovar to calc. buf space) */
+#ifdef WL11AC_80P80
+#define WL_NUMCHANSPECS 206
+#else
+#define WL_NUMCHANSPECS 110
+#endif
+
+/* WDS link local endpoint WPA role */
+#define WL_WDS_WPA_ROLE_AUTH	0	/* authenticator */
+#define WL_WDS_WPA_ROLE_SUP	1	/* supplicant */
+#define WL_WDS_WPA_ROLE_AUTO	255	/* auto, based on mac addr value */
+
+/* Base offset values */
+#define WL_PKT_FILTER_BASE_PKT   0
+#define WL_PKT_FILTER_BASE_END   1
+#define WL_PKT_FILTER_BASE_D11_H 2 /* May be removed */
+#define WL_PKT_FILTER_BASE_D11_D 3 /* May be removed */
+#define WL_PKT_FILTER_BASE_ETH_H 4
+#define WL_PKT_FILTER_BASE_ETH_D 5
+#define WL_PKT_FILTER_BASE_ARP_H 6
+#define WL_PKT_FILTER_BASE_ARP_D 7 /* May be removed */
+#define WL_PKT_FILTER_BASE_IP4_H 8
+#define WL_PKT_FILTER_BASE_IP4_D 9
+#define WL_PKT_FILTER_BASE_IP6_H 10
+#define WL_PKT_FILTER_BASE_IP6_D 11
+#define WL_PKT_FILTER_BASE_TCP_H 12
+#define WL_PKT_FILTER_BASE_TCP_D 13 /* May be removed */
+#define WL_PKT_FILTER_BASE_UDP_H 14
+#define WL_PKT_FILTER_BASE_UDP_D 15
+#define WL_PKT_FILTER_BASE_IP6_P 16
+#define WL_PKT_FILTER_BASE_COUNT 17 /* May be removed */
+
+/* String mapping for bases that may be used by applications or debug */
+#define WL_PKT_FILTER_BASE_NAMES \
+	{ "START", WL_PKT_FILTER_BASE_PKT },   \
+	{ "END",   WL_PKT_FILTER_BASE_END },   \
+	{ "ETH_H", WL_PKT_FILTER_BASE_ETH_H }, \
+	{ "ETH_D", WL_PKT_FILTER_BASE_ETH_D }, \
+	{ "D11_H", WL_PKT_FILTER_BASE_D11_H }, \
+	{ "D11_D", WL_PKT_FILTER_BASE_D11_D }, \
+	{ "ARP_H", WL_PKT_FILTER_BASE_ARP_H }, \
+	{ "IP4_H", WL_PKT_FILTER_BASE_IP4_H }, \
+	{ "IP4_D", WL_PKT_FILTER_BASE_IP4_D }, \
+	{ "IP6_H", WL_PKT_FILTER_BASE_IP6_H }, \
+	{ "IP6_D", WL_PKT_FILTER_BASE_IP6_D }, \
+	{ "IP6_P", WL_PKT_FILTER_BASE_IP6_P }, \
+	{ "TCP_H", WL_PKT_FILTER_BASE_TCP_H }, \
+	{ "TCP_D", WL_PKT_FILTER_BASE_TCP_D }, \
+	{ "UDP_H", WL_PKT_FILTER_BASE_UDP_H }, \
+	{ "UDP_D", WL_PKT_FILTER_BASE_UDP_D }
+
+/* Flags for a pattern list element */
+#define WL_PKT_FILTER_MFLAG_NEG 0x0001
+
+/*
+ * Packet engine interface
+ */
+
+#define WL_PKTENG_PER_TX_START			0x01
+#define WL_PKTENG_PER_TX_STOP			0x02
+#define WL_PKTENG_PER_RX_START			0x04
+#define WL_PKTENG_PER_RX_WITH_ACK_START		0x05
+#define WL_PKTENG_PER_TX_WITH_ACK_START		0x06
+#define WL_PKTENG_PER_RX_STOP			0x08
+#define WL_PKTENG_PER_MASK			0xff
+
+#define WL_PKTENG_SYNCHRONOUS			0x100	/* synchronous flag */
+#define WL_PKTENG_SYNCHRONOUS_UNBLK		0x200	/* synchronous unblock flag */
+#ifdef PKTENG_LONGPKTSZ
+/* max pktsz limit for pkteng */
+#define WL_PKTENG_MAXPKTSZ				PKTENG_LONGPKTSZ
+#else
+#define WL_PKTENG_MAXPKTSZ				16384
+#endif
+
+#define NUM_80211b_RATES	4
+#define NUM_80211ag_RATES	8
+#define NUM_80211n_RATES	32
+#define NUM_80211_RATES		(NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES)
+
+/*
+ * WOWL capability/override settings
+ */
+#define WL_WOWL_MAGIC           (1 << 0)    /* Wakeup on Magic packet */
+#define WL_WOWL_NET             (1 << 1)    /* Wakeup on Netpattern */
+#define WL_WOWL_DIS             (1 << 2)    /* Wakeup on loss-of-link due to Disassoc/Deauth */
+#define WL_WOWL_RETR            (1 << 3)    /* Wakeup on retrograde TSF */
+#define WL_WOWL_BCN             (1 << 4)    /* Wakeup on loss of beacon */
+#define WL_WOWL_TST             (1 << 5)    /* Wakeup after test */
+#define WL_WOWL_M1              (1 << 6)    /* Wakeup after PTK refresh */
+#define WL_WOWL_EAPID           (1 << 7)    /* Wakeup after receipt of EAP-Identity Req */
+#define WL_WOWL_PME_GPIO        (1 << 8)    /* Wakeind via PME(0) or GPIO(1) */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_WOWL_ULP_BAILOUT     (1 << 8)    /* wakeind via unknown pkt by basic ULP-offloads -
+ * WL_WOWL_ULP_BAILOUT - same as WL_WOWL_PME_GPIO used only for DONGLE BUILDS
+ */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WL_WOWL_NEEDTKIP1       (1 << 9)    /* need tkip phase 1 key to be updated by the driver */
+#define WL_WOWL_GTK_FAILURE     (1 << 10)   /* enable wakeup if GTK fails */
+#define WL_WOWL_EXTMAGPAT       (1 << 11)   /* support extended magic packets */
+#define WL_WOWL_ARPOFFLOAD      (1 << 12)   /* support ARP/NS/keepalive offloading */
+#define WL_WOWL_WPA2            (1 << 13)   /* read protocol version for EAPOL frames */
+#define WL_WOWL_KEYROT          (1 << 14)   /* If the bit is set, use key rotaton */
+#define WL_WOWL_BCAST           (1 << 15)   /* If the bit is set, frm received was bcast frame */
+#define WL_WOWL_SCANOL          (1 << 16)   /* If the bit is set, scan offload is enabled */
+#define WL_WOWL_TCPKEEP_TIME    (1 << 17)   /* Wakeup on tcpkeep alive timeout */
+#define WL_WOWL_MDNS_CONFLICT   (1 << 18)   /* Wakeup on mDNS Conflict Resolution */
+#define WL_WOWL_MDNS_SERVICE    (1 << 19)   /* Wakeup on mDNS Service Connect */
+#define WL_WOWL_TCPKEEP_DATA    (1 << 20)   /* tcp keepalive got data */
+#define WL_WOWL_FW_HALT         (1 << 21)   /* Firmware died in wowl mode */
+#define WL_WOWL_ENAB_HWRADIO    (1 << 22)   /* Enable detection of radio button changes */
+#define WL_WOWL_MIC_FAIL        (1 << 23)   /* Offloads detected MIC failure(s) */
+#define WL_WOWL_UNASSOC         (1 << 24)   /* Wakeup in Unassociated state (Net/Magic Pattern) */
+#define WL_WOWL_SECURE          (1 << 25)   /* Wakeup if received matched secured pattern */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_WOWL_EXCESS_WAKE     (1 << 26)   /* Excess wake */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WL_WOWL_LINKDOWN        (1 << 31)   /* Link Down indication in WoWL mode */
+
+#define WL_WOWL_TCPKEEP         (1 << 20)   /* temp copy to satisfy automerger */
+#define MAGIC_PKT_MINLEN 102    /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */
+
+#define WOWL_PATTEN_TYPE_ARP	(1 << 0)	/* ARP offload Pattern */
+#define WOWL_PATTEN_TYPE_NA	(1 << 1)	/* NA offload Pattern */
+
+#define MAGIC_PKT_MINLEN	102    /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */
+#define MAGIC_PKT_NUM_MAC_ADDRS	16
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#if defined(DSLCPE_DELAY)
+#define WL_DELAYMODE_DEFER  0   /* defer by scheduler's choice, make this driver default */
+#define WL_DELAYMODE_FORCE  1   /* force, this is driver default */
+#define WL_DELAYMODE_AUTO   2   /* defer if no sta associated, force if sta associated */
+#endif
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* Overlap BSS Scan parameters default, minimum, maximum */
+#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT		20	/* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN			5	/* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX			1000	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT		10	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN			10	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX			1000	/* unit TU */
+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT	300	/* unit Sec */
+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN		10	/* unit Sec */
+#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX		900	/* unit Sec */
+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT	5
+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN	5
+#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX	100
+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT	200	/* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN	200	/* unit TU */
+#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX	10000	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT	20	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN	20	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX	10000	/* unit TU */
+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT	25	/* unit percent */
+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN		0	/* unit percent */
+#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX		100	/* unit percent */
+
+#define WL_MIN_NUM_OBSS_SCAN_ARG 7	/* minimum number of arguments required for OBSS Scan */
+
+#define WL_COEX_INFO_MASK		0x07
+#define WL_COEX_INFO_REQ		0x01
+#define	WL_COEX_40MHZ_INTOLERANT	0x02
+#define	WL_COEX_WIDTH20			0x04
+
+#define	WLC_RSSI_INVALID	 0	/* invalid RSSI value */
+
+#define MAX_RSSI_LEVELS 8
+
+/* **** EXTLOG **** */
+#define EXTLOG_CUR_VER		0x0100
+
+#define MAX_ARGSTR_LEN		18 /* At least big enough for storing ETHER_ADDR_STR_LEN */
+
+/* log modules (bitmap) */
+#define LOG_MODULE_COMMON	0x0001
+#define LOG_MODULE_ASSOC	0x0002
+#define LOG_MODULE_EVENT	0x0004
+#define LOG_MODULE_MAX		3			/* Update when adding module */
+
+/* log levels */
+#define WL_LOG_LEVEL_DISABLE	0
+#define WL_LOG_LEVEL_ERR	1
+#define WL_LOG_LEVEL_WARN	2
+#define WL_LOG_LEVEL_INFO	3
+#define WL_LOG_LEVEL_MAX	WL_LOG_LEVEL_INFO	/* Update when adding level */
+
+/* flag */
+#define LOG_FLAG_EVENT		1
+
+/* log arg_type */
+#define LOG_ARGTYPE_NULL	0
+#define LOG_ARGTYPE_STR		1	/* %s */
+#define LOG_ARGTYPE_INT		2	/* %d */
+#define LOG_ARGTYPE_INT_STR	3	/* %d...%s */
+#define LOG_ARGTYPE_STR_INT	4	/* %s...%d */
+
+/* 802.11 Mgmt Packet flags */
+#define VNDR_IE_BEACON_FLAG	0x1
+#define VNDR_IE_PRBRSP_FLAG	0x2
+#define VNDR_IE_ASSOCRSP_FLAG	0x4
+#define VNDR_IE_AUTHRSP_FLAG	0x8
+#define VNDR_IE_PRBREQ_FLAG	0x10
+#define VNDR_IE_ASSOCREQ_FLAG	0x20
+#define VNDR_IE_IWAPID_FLAG	0x40 /* vendor IE in IW advertisement protocol ID field */
+#define VNDR_IE_AUTHREQ_FLAG	0x80
+#define VNDR_IE_CUSTOM_FLAG	0x100 /* allow custom IE id */
+
+#if defined(WLP2P)
+/* P2P Action Frames flags (spec ordered) */
+#define VNDR_IE_GONREQ_FLAG     0x001000
+#define VNDR_IE_GONRSP_FLAG     0x002000
+#define VNDR_IE_GONCFM_FLAG     0x004000
+#define VNDR_IE_INVREQ_FLAG     0x008000
+#define VNDR_IE_INVRSP_FLAG     0x010000
+#define VNDR_IE_DISREQ_FLAG     0x020000
+#define VNDR_IE_DISRSP_FLAG     0x040000
+#define VNDR_IE_PRDREQ_FLAG     0x080000
+#define VNDR_IE_PRDRSP_FLAG     0x100000
+
+#define VNDR_IE_P2PAF_SHIFT	12
+#endif /* WLP2P */
+
+/* channel interference measurement (chanim) related defines */
+
+/* chanim mode */
+#define CHANIM_DISABLE	0	/* disabled */
+#define CHANIM_DETECT	1	/* detection only */
+#define CHANIM_EXT		2	/* external state machine */
+#define CHANIM_ACT		3	/* full internal state machine, detect + act */
+#define CHANIM_MODE_MAX 4
+
+/* define for apcs reason code */
+#define APCS_INIT		0
+#define APCS_IOCTL		1
+#define APCS_CHANIM		2
+#define APCS_CSTIMER		3
+#define APCS_TXDLY		5
+#define APCS_NONACSD		6
+#define APCS_DFS_REENTRY	7
+#define APCS_TXFAIL		8
+#define APCS_MAX		9
+
+/* number of ACS record entries */
+#define CHANIM_ACS_RECORD			10
+
+/* CHANIM */
+#define CCASTATS_TXDUR  0
+#define CCASTATS_INBSS  1
+#define CCASTATS_OBSS   2
+#define CCASTATS_NOCTG  3
+#define CCASTATS_NOPKT  4
+#define CCASTATS_DOZE   5
+#define CCASTATS_TXOP	6
+#define CCASTATS_GDTXDUR        7
+#define CCASTATS_BDTXDUR        8
+
+#ifndef WLCHANIM_V2
+#define CCASTATS_MAX    9
+#else /* WLCHANIM_V2 */
+#define CCASTATS_MYRX      9
+#define CCASTATS_MAX    10
+#endif /* WLCHANIM_V2 */
+
+#define WL_CHANIM_COUNT_ALL	0xff
+#define WL_CHANIM_COUNT_ONE	0x1
+
+/* ap tpc modes */
+#define	AP_TPC_OFF		0
+#define	AP_TPC_BSS_PWR		1	/* BSS power control */
+#define AP_TPC_AP_PWR		2	/* AP power control */
+#define	AP_TPC_AP_BSS_PWR	3	/* Both AP and BSS power control */
+#define AP_TPC_MAX_LINK_MARGIN	127
+
+/* ap tpc modes */
+#define	AP_TPC_OFF		0
+#define	AP_TPC_BSS_PWR		1	/* BSS power control */
+#define AP_TPC_AP_PWR		2	/* AP power control */
+#define	AP_TPC_AP_BSS_PWR	3	/* Both AP and BSS power control */
+#define AP_TPC_MAX_LINK_MARGIN	127
+
+/* state */
+#define WL_P2P_DISC_ST_SCAN	0
+#define WL_P2P_DISC_ST_LISTEN	1
+#define WL_P2P_DISC_ST_SEARCH	2
+
+/* i/f type */
+#define WL_P2P_IF_CLIENT	0
+#define WL_P2P_IF_GO		1
+#define WL_P2P_IF_DYNBCN_GO	2
+#define WL_P2P_IF_DEV		3
+
+/* count */
+#define WL_P2P_SCHED_RSVD	0
+#define WL_P2P_SCHED_REPEAT	255	/* anything > 255 will be treated as 255 */
+
+#define WL_P2P_SCHED_FIXED_LEN		3
+
+/* schedule type */
+#define WL_P2P_SCHED_TYPE_ABS		0	/* Scheduled Absence */
+#define WL_P2P_SCHED_TYPE_REQ_ABS	1	/* Requested Absence */
+
+/* schedule action during absence periods (for WL_P2P_SCHED_ABS type) */
+#define WL_P2P_SCHED_ACTION_NONE	0	/* no action */
+#define WL_P2P_SCHED_ACTION_DOZE	1	/* doze */
+/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */
+#define WL_P2P_SCHED_ACTION_GOOFF	2	/* turn off GO beacon/prbrsp functions */
+/* schedule option - WL_P2P_SCHED_TYPE_XXX */
+#define WL_P2P_SCHED_ACTION_RESET	255	/* reset */
+
+/* schedule option - WL_P2P_SCHED_TYPE_ABS */
+#define WL_P2P_SCHED_OPTION_NORMAL	0	/* normal start/interval/duration/count */
+#define WL_P2P_SCHED_OPTION_BCNPCT	1	/* percentage of beacon interval */
+/* schedule option - WL_P2P_SCHED_TYPE_REQ_ABS */
+#define WL_P2P_SCHED_OPTION_TSFOFS	2	/* normal start/internal/duration/count with
+						 * start being an offset of the 'current' TSF
+						 */
+
+/* feature flags */
+#define WL_P2P_FEAT_GO_CSA	(1 << 0)	/* GO moves with the STA using CSA method */
+#define WL_P2P_FEAT_GO_NOLEGACY	(1 << 1)	/* GO does not probe respond to non-p2p probe
+						 * requests
+						 */
+#define WL_P2P_FEAT_RESTRICT_DEV_RESP (1 << 2)	/* Restrict p2p dev interface from responding */
+
+/* n-mode support capability */
+/* 2x2 includes both 1x1 & 2x2 devices
+ * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
+ * control it independently
+ */
+#define WL_11N_2x2			1
+#define WL_11N_3x3			3
+#define WL_11N_4x4			4
+
+/* define 11n feature disable flags */
+#define WLFEATURE_DISABLE_11N		0x00000001
+#define WLFEATURE_DISABLE_11N_STBC_TX	0x00000002
+#define WLFEATURE_DISABLE_11N_STBC_RX	0x00000004
+#define WLFEATURE_DISABLE_11N_SGI_TX	0x00000008
+#define WLFEATURE_DISABLE_11N_SGI_RX	0x00000010
+#define WLFEATURE_DISABLE_11N_AMPDU_TX	0x00000020
+#define WLFEATURE_DISABLE_11N_AMPDU_RX	0x00000040
+#define WLFEATURE_DISABLE_11N_GF	0x00000080
+
+/* Proxy STA modes */
+#define PSTA_MODE_DISABLED		0
+#define PSTA_MODE_PROXY			1
+#define PSTA_MODE_REPEATER		2
+
+/* op code in nat_cfg */
+#define NAT_OP_ENABLE		1	/* enable NAT on given interface */
+#define NAT_OP_DISABLE		2	/* disable NAT on given interface */
+#define NAT_OP_DISABLE_ALL	3	/* disable NAT on all interfaces */
+
+/* NAT state */
+#define NAT_STATE_ENABLED	1	/* NAT is enabled */
+#define NAT_STATE_DISABLED	2	/* NAT is disabled */
+
+#define CHANNEL_5G_LOW_START	36	/* 5G low (36..48) CDD enable/disable bit mask */
+#define CHANNEL_5G_MID_START	52	/* 5G mid (52..64) CDD enable/disable bit mask */
+#define CHANNEL_5G_HIGH_START	100	/* 5G high (100..140) CDD enable/disable bit mask */
+#define CHANNEL_5G_UPPER_START	149	/* 5G upper (149..161) CDD enable/disable bit mask */
+
+/* D0 Coalescing */
+#define IPV4_ARP_FILTER		0x0001
+#define IPV4_NETBT_FILTER	0x0002
+#define IPV4_LLMNR_FILTER	0x0004
+#define IPV4_SSDP_FILTER	0x0008
+#define IPV4_WSD_FILTER		0x0010
+#define IPV6_NETBT_FILTER	0x0200
+#define IPV6_LLMNR_FILTER	0x0400
+#define IPV6_SSDP_FILTER	0x0800
+#define IPV6_WSD_FILTER		0x1000
+
+/* Network Offload Engine */
+#define NWOE_OL_ENABLE		0x00000001
+
+/*
+ * Traffic management structures/defines.
+ */
+
+/* Traffic management bandwidth parameters */
+#define TRF_MGMT_MAX_PRIORITIES                 3
+
+#define TRF_MGMT_FLAG_ADD_DSCP                  0x0001  /* Add DSCP to IP TOS field */
+#define TRF_MGMT_FLAG_DISABLE_SHAPING           0x0002  /* Don't shape traffic */
+#define TRF_MGMT_FLAG_MANAGE_LOCAL_TRAFFIC      0x0008  /* Manage traffic over our local subnet */
+#define TRF_MGMT_FLAG_FILTER_ON_MACADDR         0x0010  /* filter on MAC address */
+#define TRF_MGMT_FLAG_NO_RX                     0x0020  /* do not apply fiters to rx packets */
+
+#define TRF_FILTER_MAC_ADDR              0x0001 /* L2 filter use dst mac address for filtering */
+#define TRF_FILTER_IP_ADDR               0x0002 /* L3 filter use ip ddress for filtering */
+#define TRF_FILTER_L4                    0x0004 /* L4 filter use tcp/udp for filtering */
+#define TRF_FILTER_DWM                   0x0008 /* L3 filter use DSCP for filtering */
+#define TRF_FILTER_FAVORED               0x0010 /* Tag the packet FAVORED */
+
+/* WNM/NPS subfeatures mask */
+#define WL_WNM_BSSTRANS		0x00000001
+#define WL_WNM_PROXYARP		0x00000002
+#define WL_WNM_MAXIDLE		0x00000004
+#define WL_WNM_TIMBC		0x00000008
+#define WL_WNM_TFS		0x00000010
+#define WL_WNM_SLEEP		0x00000020
+#define WL_WNM_DMS		0x00000040
+#define WL_WNM_FMS		0x00000080
+#define WL_WNM_NOTIF		0x00000100
+#define WL_WNM_WBTEXT	0x00000200
+#define WL_WNM_MAX		0x00000400
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#ifdef WLWNM_BRCM
+#define BRCM_WNM_FEATURE_SET\
+					(WL_WNM_PROXYARP | \
+					WL_WNM_SLEEP | \
+					WL_WNM_FMS | \
+					WL_WNM_TFS | \
+					WL_WNM_TIMBC | \
+					WL_WNM_BSSTRANS | \
+					WL_WNM_DMS | \
+					WL_WNM_NOTIF | \
+					0)
+#endif /* WLWNM_BRCM */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#ifndef ETHER_MAX_DATA
+#define ETHER_MAX_DATA	1500
+#endif /* ETHER_MAX_DATA */
+
+/* Different discovery modes for dpt */
+#define	DPT_DISCOVERY_MANUAL	0x01	/* manual discovery mode */
+#define	DPT_DISCOVERY_AUTO	0x02	/* auto discovery mode */
+#define	DPT_DISCOVERY_SCAN	0x04	/* scan-based discovery mode */
+
+/* different path selection values */
+#define DPT_PATHSEL_AUTO	0	/* auto mode for path selection */
+#define DPT_PATHSEL_DIRECT	1	/* always use direct DPT path */
+#define DPT_PATHSEL_APPATH	2	/* always use AP path */
+
+/* different ops for deny list */
+#define DPT_DENY_LIST_ADD	1	/* add to dpt deny list */
+#define DPT_DENY_LIST_REMOVE	2	/* remove from dpt deny list */
+
+/* different ops for manual end point */
+#define DPT_MANUAL_EP_CREATE	1	/* create manual dpt endpoint */
+#define DPT_MANUAL_EP_MODIFY	2	/* modify manual dpt endpoint */
+#define DPT_MANUAL_EP_DELETE	3	/* delete manual dpt endpoint */
+
+/* flags to indicate DPT status */
+#define	DPT_STATUS_ACTIVE	0x01	/* link active (though may be suspended) */
+#define	DPT_STATUS_AES		0x02	/* link secured through AES encryption */
+#define	DPT_STATUS_FAILED	0x04	/* DPT link failed */
+
+#ifdef WLTDLS
+/* different ops for manual end point */
+#define TDLS_MANUAL_EP_CREATE	1	/* create manual dpt endpoint */
+#define TDLS_MANUAL_EP_MODIFY	2	/* modify manual dpt endpoint */
+#define TDLS_MANUAL_EP_DELETE	3	/* delete manual dpt endpoint */
+#define TDLS_MANUAL_EP_PM		4	/*  put dpt endpoint in PM mode */
+#define TDLS_MANUAL_EP_WAKE		5	/* wake up dpt endpoint from PM */
+#define TDLS_MANUAL_EP_DISCOVERY	6	/* discover if endpoint is TDLS capable */
+#define TDLS_MANUAL_EP_CHSW		7	/* channel switch */
+#define TDLS_MANUAL_EP_WFD_TPQ	8	/* WiFi-Display Tunneled Probe reQuest */
+
+/* modes */
+#define TDLS_WFD_IE_TX			0
+#define TDLS_WFD_IE_RX			1
+#define TDLS_WFD_PROBE_IE_TX	2
+#define TDLS_WFD_PROBE_IE_RX	3
+#endif /* WLTDLS */
+
+/* define for flag */
+#define TSPEC_PENDING		0	/* TSPEC pending */
+#define TSPEC_ACCEPTED		1	/* TSPEC accepted */
+#define TSPEC_REJECTED		2	/* TSPEC rejected */
+#define TSPEC_UNKNOWN		3	/* TSPEC unknown */
+#define TSPEC_STATUS_MASK	7	/* TSPEC status mask */
+
+
+/* Software feature flag defines used by wlfeatureflag */
+#ifdef WLAFTERBURNER
+#define WL_SWFL_ABBFL       0x0001 /* Allow Afterburner on systems w/o hardware BFL */
+#define WL_SWFL_ABENCORE    0x0002 /* Allow AB on non-4318E chips */
+#endif /* WLAFTERBURNER */
+#define WL_SWFL_NOHWRADIO	0x0004
+#define WL_SWFL_FLOWCONTROL     0x0008 /* Enable backpressure to OS stack */
+#define WL_SWFL_WLBSSSORT	0x0010 /* Per-port supports sorting of BSS */
+
+#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */
+
+#define CSA_BROADCAST_ACTION_FRAME	0	/* csa broadcast action frame */
+#define CSA_UNICAST_ACTION_FRAME	  1 /* csa unicast action frame */
+
+/* Roaming trigger definitions for WLC_SET_ROAM_TRIGGER.
+ *
+ * (-100 < value < 0)   value is used directly as a roaming trigger in dBm
+ * (0 <= value) value specifies a logical roaming trigger level from
+ *                      the list below
+ *
+ * WLC_GET_ROAM_TRIGGER always returns roaming trigger value in dBm, never
+ * the logical roam trigger value.
+ */
+#define WLC_ROAM_TRIGGER_DEFAULT	0 /* default roaming trigger */
+#define WLC_ROAM_TRIGGER_BANDWIDTH	1 /* optimize for bandwidth roaming trigger */
+#define WLC_ROAM_TRIGGER_DISTANCE	2 /* optimize for distance roaming trigger */
+#define WLC_ROAM_TRIGGER_AUTO		3 /* auto-detect environment */
+#define WLC_ROAM_TRIGGER_MAX_VALUE	3 /* max. valid value */
+
+#define WLC_ROAM_NEVER_ROAM_TRIGGER	(-100) /* Avoid Roaming by setting a large value */
+
+/* Preferred Network Offload (PNO, formerly PFN) defines */
+#define WPA_AUTH_PFN_ANY	0xffffffff	/* for PFN, match only ssid */
+
+#define SORT_CRITERIA_BIT		0
+#define AUTO_NET_SWITCH_BIT		1
+#define ENABLE_BKGRD_SCAN_BIT		2
+#define IMMEDIATE_SCAN_BIT		3
+#define	AUTO_CONNECT_BIT		4
+#define	ENABLE_BD_SCAN_BIT		5
+#define ENABLE_ADAPTSCAN_BIT		6
+#define IMMEDIATE_EVENT_BIT		8
+#define SUPPRESS_SSID_BIT		9
+#define ENABLE_NET_OFFLOAD_BIT		10
+/* report found/lost events for SSID and BSSID networks seperately */
+#define REPORT_SEPERATELY_BIT		11
+#define BESTN_BSSID_ONLY_BIT		12
+
+#define SORT_CRITERIA_MASK		0x0001
+#define AUTO_NET_SWITCH_MASK		0x0002
+#define ENABLE_BKGRD_SCAN_MASK		0x0004
+#define IMMEDIATE_SCAN_MASK		0x0008
+#define	AUTO_CONNECT_MASK		0x0010
+
+#define ENABLE_BD_SCAN_MASK		0x0020
+#define ENABLE_ADAPTSCAN_MASK		0x00c0
+#define IMMEDIATE_EVENT_MASK		0x0100
+#define SUPPRESS_SSID_MASK		0x0200
+#define ENABLE_NET_OFFLOAD_MASK		0x0400
+/* report found/lost events for SSID and BSSID networks seperately */
+#define REPORT_SEPERATELY_MASK		0x0800
+#define BESTN_BSSID_ONLY_MASK		0x1000
+
+#define PFN_VERSION			2
+#ifdef PFN_SCANRESULT_2
+#define PFN_SCANRESULT_VERSION		2
+#else
+#define PFN_SCANRESULT_VERSION		1
+#endif /* PFN_SCANRESULT_2 */
+#ifndef MAX_PFN_LIST_COUNT
+#define MAX_PFN_LIST_COUNT		16
+#endif /* MAX_PFN_LIST_COUNT */
+
+#define PFN_COMPLETE			1
+#define PFN_INCOMPLETE			0
+
+#define DEFAULT_BESTN			2
+#define DEFAULT_MSCAN			0
+#define DEFAULT_REPEAT			10
+#define DEFAULT_EXP				2
+
+#define PFN_PARTIAL_SCAN_BIT		0
+#define PFN_PARTIAL_SCAN_MASK		1
+
+#define WL_PFN_SUPPRESSFOUND_MASK	0x08
+#define WL_PFN_SUPPRESSLOST_MASK	0x10
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WL_PFN_SSID_A_BAND_TRIG		0x20
+#define WL_PFN_SSID_BG_BAND_TRIG	0x40
+#define WL_PFN_SSID_IMPRECISE_MATCH	0x80
+#define WL_PFN_SSID_SAME_NETWORK	0x10000
+#define WL_PFN_SUPPRESS_AGING_MASK	0x20000
+#define WL_PFN_FLUSH_ALL_SSIDS		0x40000
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#define WL_PFN_RSSI_MASK		0xff00
+#define WL_PFN_RSSI_SHIFT		8
+
+#define WL_PFN_REPORT_ALLNET    0
+#define WL_PFN_REPORT_SSIDNET   1
+#define WL_PFN_REPORT_BSSIDNET  2
+
+#define WL_PFN_CFG_FLAGS_PROHIBITED	0x00000001	/* Accept and use prohibited channels */
+#define WL_PFN_CFG_FLAGS_HISTORY_OFF	0x00000002	/* Scan history suppressed */
+
+#define WL_PFN_HIDDEN_BIT		2
+#define PNO_SCAN_MAX_FW			508*1000	/* max time scan time in msec */
+#define PNO_SCAN_MAX_FW_SEC		PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */
+#define PNO_SCAN_MIN_FW_SEC		10			/* min time scan time in SEC */
+#define WL_PFN_HIDDEN_MASK		0x4
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define MAX_SSID_WHITELIST_NUM         4
+#define MAX_BSSID_PREF_LIST_NUM        32
+#define MAX_BSSID_BLACKLIST_NUM        32
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#ifndef BESTN_MAX
+#define BESTN_MAX			10
+#endif
+
+#ifndef MSCAN_MAX
+#define MSCAN_MAX			32
+#endif
+
+/* TCP Checksum Offload error injection for testing */
+#define TOE_ERRTEST_TX_CSUM	0x00000001
+#define TOE_ERRTEST_RX_CSUM	0x00000002
+#define TOE_ERRTEST_RX_CSUM2	0x00000004
+
+/* ARP Offload feature flags for arp_ol iovar */
+#define ARP_OL_AGENT		0x00000001
+#define ARP_OL_SNOOP		0x00000002
+#define ARP_OL_HOST_AUTO_REPLY	0x00000004
+#define ARP_OL_PEER_AUTO_REPLY	0x00000008
+
+/* ARP Offload error injection */
+#define ARP_ERRTEST_REPLY_PEER	0x1
+#define ARP_ERRTEST_REPLY_HOST	0x2
+
+#define ARP_MULTIHOMING_MAX	8	/* Maximum local host IP addresses */
+#define ND_MULTIHOMING_MAX 10	/* Maximum local host IP addresses */
+#define ND_REQUEST_MAX		5	/* Max set of offload params */
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+/* AOAC wake event flag */
+#define WAKE_EVENT_NLO_DISCOVERY_BIT		1
+#define WAKE_EVENT_AP_ASSOCIATION_LOST_BIT	2
+#define WAKE_EVENT_GTK_HANDSHAKE_ERROR_BIT 4
+#define WAKE_EVENT_4WAY_HANDSHAKE_REQUEST_BIT 8
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define WAKE_EVENT_NET_PACKET_BIT 0x10
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+#define MAX_NUM_WOL_PATTERN	22 /* LOGO requirements min 22 */
+
+
+/* Packet filter operation mode */
+/* True: 1; False: 0 */
+#define PKT_FILTER_MODE_FORWARD_ON_MATCH		1
+/* Enable and disable pkt_filter as a whole */
+#define PKT_FILTER_MODE_DISABLE					2
+/* Cache first matched rx pkt(be queried by host later) */
+#define PKT_FILTER_MODE_PKT_CACHE_ON_MATCH		4
+/* If pkt_filter is enabled and no filter is set, don't forward anything */
+#define PKT_FILTER_MODE_PKT_FORWARD_OFF_DEFAULT 8
+
+#ifdef DONGLEOVERLAYS
+#define OVERLAY_IDX_MASK		0x000000ff
+#define OVERLAY_IDX_SHIFT		0
+#define OVERLAY_FLAGS_MASK		0xffffff00
+#define OVERLAY_FLAGS_SHIFT		8
+/* overlay written to device memory immediately after loading the base image */
+#define OVERLAY_FLAG_POSTLOAD	0x100
+/* defer overlay download until the device responds w/WLC_E_OVL_DOWNLOAD event */
+#define OVERLAY_FLAG_DEFER_DL	0x200
+/* overlay downloaded prior to the host going to sleep */
+#define OVERLAY_FLAG_PRESLEEP	0x400
+#define OVERLAY_DOWNLOAD_CHUNKSIZE	1024
+#endif /* DONGLEOVERLAYS */
+
+/* reuse two number in the sc/rc space */
+#define	SMFS_CODE_MALFORMED 0xFFFE
+#define SMFS_CODE_IGNORED	0xFFFD
+
+/* RFAWARE def */
+#define BCM_ACTION_RFAWARE		0x77
+#define BCM_ACTION_RFAWARE_DCS  0x01
+
+/* DCS reason code define */
+#define BCM_DCS_IOVAR		0x1
+#define BCM_DCS_UNKNOWN		0xFF
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#ifdef EXT_STA
+#define IHV_OID_BCM 0x00181000	/* based on BRCM_OUI value */
+/* ---------------------------------------------------------------------------
+*  Event codes
+* ---------------------------------------------------------------------------
+*/
+
+#define IHV_DRIVER_EVENT_GEN_INDICATION                 0x00000011L     /* from driver */
+#endif /* EXT_STA */
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+#ifdef PROP_TXSTATUS
+/* Bit definitions for tlv iovar */
+/*
+ * enable RSSI signals:
+ * WLFC_CTL_TYPE_RSSI
+ */
+#define WLFC_FLAGS_RSSI_SIGNALS			0x0001
+
+/* enable (if/mac_open, if/mac_close,, mac_add, mac_del) signals:
+ *
+ * WLFC_CTL_TYPE_MAC_OPEN
+ * WLFC_CTL_TYPE_MAC_CLOSE
+ *
+ * WLFC_CTL_TYPE_INTERFACE_OPEN
+ * WLFC_CTL_TYPE_INTERFACE_CLOSE
+ *
+ * WLFC_CTL_TYPE_MACDESC_ADD
+ * WLFC_CTL_TYPE_MACDESC_DEL
+ *
+ */
+#define WLFC_FLAGS_XONXOFF_SIGNALS		0x0002
+
+/* enable (status, fifo_credit, mac_credit) signals
+ * WLFC_CTL_TYPE_MAC_REQUEST_CREDIT
+ * WLFC_CTL_TYPE_TXSTATUS
+ * WLFC_CTL_TYPE_FIFO_CREDITBACK
+ */
+#define WLFC_FLAGS_CREDIT_STATUS_SIGNALS	0x0004
+
+#define WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE	0x0008
+#define WLFC_FLAGS_PSQ_GENERATIONFSM_ENABLE	0x0010
+#define WLFC_FLAGS_PSQ_ZERO_BUFFER_ENABLE	0x0020
+#define WLFC_FLAGS_HOST_RXRERODER_ACTIVE	0x0040
+#define WLFC_FLAGS_PKT_STAMP_SIGNALS		0x0080
+
+#endif /* PROP_TXSTATUS */
+
+#define WL_TIMBC_STATUS_AP_UNKNOWN	255	/* AP status for internal use only */
+
+#define WL_DFRTS_LOGIC_OFF	0	/* Feature is disabled */
+#define WL_DFRTS_LOGIC_OR	1	/* OR all non-zero threshold conditions */
+#define WL_DFRTS_LOGIC_AND	2	/* AND all non-zero threshold conditions */
+
+/* Definitions for Reliable Multicast */
+#define WL_RELMCAST_MAX_CLIENT		32
+#define WL_RELMCAST_FLAG_INBLACKLIST	1
+#define WL_RELMCAST_FLAG_ACTIVEACKER	2
+#define WL_RELMCAST_FLAG_RELMCAST	4
+
+/* structures for proximity detection device role */
+#define WL_PROXD_MODE_DISABLE	0
+#define WL_PROXD_MODE_NEUTRAL	1
+#define WL_PROXD_MODE_INITIATOR	2
+#define WL_PROXD_MODE_TARGET	3
+#define WL_PROXD_RANDOM_WAKEUP	0x8000
+
+
+#ifdef NET_DETECT
+#define NET_DETECT_MAX_WAKE_DATA_SIZE	2048
+#define NET_DETECT_MAX_PROFILES		16
+#define NET_DETECT_MAX_CHANNELS		50
+#endif /* NET_DETECT */
+
+
+/* Bit masks for radio disabled status - returned by WL_GET_RADIO */
+#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)	/* some countries don't support any channel */
+#define WL_RADIO_PERCORE_DISABLE	(1<<4)	/* Radio diable per core for DVT */
+
+#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
+
+/* Override bit for WLC_SET_TXPWR.  if set, ignore other level limits */
+#define WL_TXPWR_OVERRIDE	(1U<<31)
+#define WL_TXPWR_2G		(1U<<30)
+#define WL_TXPWR_5G		(1U<<29)
+#define WL_TXPWR_NEG   (1U<<28)
+
+#define WL_TXPWR_MASK		(~(0x7<<29))
+#define WL_TXPWR_CORE_MAX	(3)
+#define WL_TXPWR_CORE0_MASK	(0x000000FF)
+#define WL_TXPWR_CORE0_SHIFT	(0)
+#define WL_TXPWR_CORE1_MASK	(0x0000FF00)
+#define WL_TXPWR_CORE1_SHIFT	(8)
+#define WL_TXPWR_CORE2_MASK	(0x00FF0000)
+#define WL_TXPWR_CORE2_SHIFT	(16)
+
+/* phy types (returned by WLC_GET_PHYTPE) */
+#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_LCN20	12
+#define	WLC_PHY_TYPE_NULL	0xf
+
+/* Values for PM */
+#define PM_OFF	0
+#define PM_MAX	1
+#define PM_FAST 2
+#define PM_FORCE_OFF 3		/* use this bit to force PM off even bt is active */
+
+#define WL_WME_CNT_VERSION	1	/* current version of wl_wme_cnt_t */
+
+/* fbt_cap: FBT assoc / reassoc modes. */
+#define WLC_FBT_CAP_DRV_4WAY_AND_REASSOC  1 /* Driver 4-way handshake & reassoc (WLFBT). */
+
+/* monitor_promisc_level bits */
+#define WL_MONPROMISC_PROMISC 0x0001
+#define WL_MONPROMISC_CTRL 0x0002
+#define WL_MONPROMISC_FCS 0x0004
+
+/* TCP Checksum Offload defines */
+#define TOE_TX_CSUM_OL		0x00000001
+#define TOE_RX_CSUM_OL		0x00000002
+
+/* Wi-Fi Display Services (WFDS) */
+#define WL_P2P_SOCIAL_CHANNELS_MAX  WL_NUMCHANNELS
+#define MAX_WFDS_SEEK_SVC 4	/* Max # of wfds services to seek */
+#define MAX_WFDS_ADVERT_SVC 4	/* Max # of wfds services to advertise */
+#define MAX_WFDS_SVC_NAME_LEN 200	/* maximum service_name length */
+#define MAX_WFDS_ADV_SVC_INFO_LEN 65000	/* maximum adv service_info length */
+#define P2P_WFDS_HASH_LEN 6		/* Length of a WFDS service hash */
+#define MAX_WFDS_SEEK_SVC_INFO_LEN 255	/* maximum seek service_info req length */
+#define MAX_WFDS_SEEK_SVC_NAME_LEN 200	/* maximum service_name length */
+
+/* ap_isolate bitmaps */
+#define AP_ISOLATE_DISABLED		0x0
+#define AP_ISOLATE_SENDUP_ALL		0x01
+#define AP_ISOLATE_SENDUP_MCAST		0x02
+
+/* Type values for the wl_pwrstats_t data field */
+#define WL_PWRSTATS_TYPE_PHY		0 /**< struct wl_pwr_phy_stats */
+#define WL_PWRSTATS_TYPE_SCAN		1 /**< struct wl_pwr_scan_stats */
+#define WL_PWRSTATS_TYPE_USB_HSIC	2 /**< struct wl_pwr_usb_hsic_stats */
+#define WL_PWRSTATS_TYPE_PM_AWAKE1	3 /**< struct wl_pwr_pm_awake_stats_v1 */
+#define WL_PWRSTATS_TYPE_CONNECTION	4 /* struct wl_pwr_connect_stats; assoc and key-exch time */
+#define WL_PWRSTATS_TYPE_PCIE		6 /**< struct wl_pwr_pcie_stats */
+#define WL_PWRSTATS_TYPE_PM_AWAKE2	7 /**< struct wl_pwr_pm_awake_stats_v2 */
+#define WL_PWRSTATS_TYPE_SDIO		8 /* struct wl_pwr_sdio_stats */
+#define WL_PWRSTATS_TYPE_MIMO_PS_METRICS 9 /* struct wl_mimo_meas_metrics_t */
+
+#endif /* wlioctl_defs_h */
diff --git a/wl/components/shared/proto/802.11.h b/wl/components/shared/proto/802.11.h
new file mode 100644
index 0000000..a5ec095
--- /dev/null
+++ b/wl/components/shared/proto/802.11.h
@@ -0,0 +1,4961 @@
+/*
+ * Fundamental types and constants relating to 802.11
+ *
+ * Copyright (C) 2017, Broadcom. 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: 802.11.h 663798 2017-02-09 06:38:25Z $
+ */
+
+#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>
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+#define DOT11_TU_TO_US			1024	/* 802.11 Time Unit is 1024 microseconds */
+
+/* Generic 802.11 frame constants */
+#define DOT11_A3_HDR_LEN		24	/* d11 header length with A3 */
+#define DOT11_A4_HDR_LEN		30	/* d11 header length with A4 */
+#define DOT11_MAC_HDR_LEN		DOT11_A3_HDR_LEN	/* MAC header length */
+#define DOT11_FCS_LEN			4	/* d11 FCS length */
+#define DOT11_ICV_LEN			4	/* d11 ICV length */
+#define DOT11_ICV_AES_LEN		8	/* d11 ICV/AES length */
+#define DOT11_QOS_LEN			2	/* d11 QoS length */
+#define DOT11_HTC_LEN			4	/* d11 HT Control field length */
+
+#define DOT11_KEY_INDEX_SHIFT		6	/* d11 key index shift */
+#define DOT11_IV_LEN			4	/* d11 IV length */
+#define DOT11_IV_TKIP_LEN		8	/* d11 IV TKIP length */
+#define DOT11_IV_AES_OCB_LEN		4	/* d11 IV/AES/OCB length */
+#define DOT11_IV_AES_CCM_LEN		8	/* d11 IV/AES/CCM length */
+#define DOT11_IV_MAX_LEN		8	/* maximum iv len for any encryption */
+
+/* Includes MIC */
+#define DOT11_MAX_MPDU_BODY_LEN		2304	/* max MPDU body length */
+/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */
+#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)	/* d11 max MPDU length */
+
+#define DOT11_MAX_SSID_LEN		32	/* d11 max ssid length */
+
+/* dot11RTSThreshold */
+#define DOT11_DEFAULT_RTS_LEN		2347	/* d11 default RTS length */
+#define DOT11_MAX_RTS_LEN		2347	/* d11 max RTS length */
+
+/* dot11FragmentationThreshold */
+#define DOT11_MIN_FRAG_LEN		256	/* d11 min fragmentation length */
+#define DOT11_MAX_FRAG_LEN		2346	/* Max frag is also limited by aMPDUMaxLength
+						* of the attached PHY
+						*/
+#define DOT11_DEFAULT_FRAG_LEN		2346	/* d11 default fragmentation length */
+
+/* dot11BeaconPeriod */
+#define DOT11_MIN_BEACON_PERIOD		1	/* d11 min beacon period */
+#define DOT11_MAX_BEACON_PERIOD		0xFFFF	/* d11 max beacon period */
+
+/* dot11DTIMPeriod */
+#define DOT11_MIN_DTIM_PERIOD		1	/* d11 min DTIM period */
+#define DOT11_MAX_DTIM_PERIOD		0xFF	/* d11 max DTIM period */
+
+/** 802.2 LLC/SNAP header used by 802.11 per 802.1H */
+#define DOT11_LLC_SNAP_HDR_LEN		8	/* d11 LLC/SNAP header length */
+/* minimum LLC header length; DSAP, SSAP, 8 bit Control (unnumbered) */
+#define DOT11_LLC_HDR_LEN_MIN		3
+#define DOT11_OUI_LEN			3	/* d11 OUI length */
+BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header {
+	uint8	dsap;				/* always 0xAA */
+	uint8	ssap;				/* always 0xAA */
+	uint8	ctl;				/* always 0x03 */
+	uint8	oui[DOT11_OUI_LEN];		/* RFC1042: 0x00 0x00 0x00
+						 * Bridge-Tunnel: 0x00 0x00 0xF8
+						 */
+	uint16	type;				/* ethertype */
+} BWL_POST_PACKED_STRUCT;
+
+/* RFC1042 header used by 802.11 per 802.1H */
+#define RFC1042_HDR_LEN	(ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN)	/* RCF1042 header length */
+
+/* Generic 802.11 MAC header */
+/**
+ * N.B.: This struct reflects the full 4 address 802.11 MAC header.
+ *		 The fields are defined such that the shorter 1, 2, and 3
+ *		 address headers just use the first k fields.
+ */
+BWL_PRE_PACKED_STRUCT struct dot11_header {
+	uint16			fc;		/* frame control */
+	uint16			durid;		/* duration/ID */
+	struct ether_addr	a1;		/* address 1 */
+	struct ether_addr	a2;		/* address 2 */
+	struct ether_addr	a3;		/* address 3 */
+	uint16			seq;		/* sequence control */
+	struct ether_addr	a4;		/* address 4 */
+} BWL_POST_PACKED_STRUCT;
+
+/* Control frames */
+
+BWL_PRE_PACKED_STRUCT struct dot11_rts_frame {
+	uint16			fc;		/* frame control */
+	uint16			durid;		/* duration/ID */
+	struct ether_addr	ra;		/* receiver address */
+	struct ether_addr	ta;		/* transmitter address */
+} BWL_POST_PACKED_STRUCT;
+#define	DOT11_RTS_LEN		16		/* d11 RTS frame length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_cts_frame {
+	uint16			fc;		/* frame control */
+	uint16			durid;		/* duration/ID */
+	struct ether_addr	ra;		/* receiver address */
+} BWL_POST_PACKED_STRUCT;
+#define	DOT11_CTS_LEN		10		/* d11 CTS frame length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_ack_frame {
+	uint16			fc;		/* frame control */
+	uint16			durid;		/* duration/ID */
+	struct ether_addr	ra;		/* receiver address */
+} BWL_POST_PACKED_STRUCT;
+#define	DOT11_ACK_LEN		10		/* d11 ACK frame length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame {
+	uint16			fc;		/* frame control */
+	uint16			durid;		/* AID */
+	struct ether_addr	bssid;		/* receiver address, STA in AP */
+	struct ether_addr	ta;		/* transmitter address */
+} BWL_POST_PACKED_STRUCT;
+#define	DOT11_PS_POLL_LEN	16		/* d11 PS poll frame length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame {
+	uint16			fc;		/* frame control */
+	uint16			durid;		/* duration/ID */
+	struct ether_addr	ra;		/* receiver address */
+	struct ether_addr	bssid;		/* transmitter address, STA in AP */
+} BWL_POST_PACKED_STRUCT;
+#define	DOT11_CS_END_LEN	16		/* d11 CF-END frame length */
+
+/**
+ * RWL wifi protocol: The Vendor Specific Action frame is defined for vendor-specific signaling
+ *  category+OUI+vendor specific content ( this can be variable)
+ */
+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;
+
+/** generic vendor specific action frame with variable length */
+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
+
+/* BA/BAR Control parameters */
+#define DOT11_BA_CTL_POLICY_NORMAL	0x0000	/* normal ack */
+#define DOT11_BA_CTL_POLICY_NOACK	0x0001	/* no ack */
+#define DOT11_BA_CTL_POLICY_MASK	0x0001	/* ack policy mask */
+
+#define DOT11_BA_CTL_MTID		0x0002	/* multi tid BA */
+#define DOT11_BA_CTL_COMPRESSED		0x0004	/* compressed bitmap */
+
+#define DOT11_BA_CTL_NUMMSDU_MASK	0x0FC0	/* num msdu in bitmap mask */
+#define DOT11_BA_CTL_NUMMSDU_SHIFT	6	/* num msdu in bitmap shift */
+
+#define DOT11_BA_CTL_TID_MASK		0xF000	/* tid mask */
+#define DOT11_BA_CTL_TID_SHIFT		12	/* tid shift */
+
+/** control frame header (BA/BAR) */
+BWL_PRE_PACKED_STRUCT struct dot11_ctl_header {
+	uint16			fc;		/* frame control */
+	uint16			durid;		/* duration/ID */
+	struct ether_addr	ra;		/* receiver address */
+	struct ether_addr	ta;		/* transmitter address */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_CTL_HDR_LEN	16		/* control frame hdr len */
+
+/** BAR frame payload */
+BWL_PRE_PACKED_STRUCT struct dot11_bar {
+	uint16			bar_control;	/* BAR Control */
+	uint16			seqnum;		/* Starting Sequence control */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BAR_LEN		4		/* BAR frame payload length */
+
+#define DOT11_BA_BITMAP_LEN	128		/* bitmap length */
+#define DOT11_BA_CMP_BITMAP_LEN	8		/* compressed bitmap length */
+/** BA frame payload */
+BWL_PRE_PACKED_STRUCT struct dot11_ba {
+	uint16			ba_control;	/* BA Control */
+	uint16			seqnum;		/* Starting Sequence control */
+	uint8			bitmap[DOT11_BA_BITMAP_LEN];	/* Block Ack Bitmap */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_BA_LEN		4		/* BA frame payload len (wo bitmap) */
+
+/** Management frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_management_header {
+	uint16			fc;		/* frame control */
+	uint16			durid;		/* duration/ID */
+	struct ether_addr	da;		/* receiver address */
+	struct ether_addr	sa;		/* transmitter address */
+	struct ether_addr	bssid;		/* BSS ID */
+	uint16			seq;		/* sequence control */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_management_header dot11_management_header_t;
+#define	DOT11_MGMT_HDR_LEN	24		/* d11 management header length */
+
+/* Management frame payloads */
+
+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		/* 802.11 beacon/probe frame fixed length */
+#define	DOT11_BCN_PRB_FIXED_LEN	12		/* 802.11 beacon/probe frame fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_auth {
+	uint16			alg;		/* algorithm */
+	uint16			seq;		/* sequence control */
+	uint16			status;		/* status code */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_AUTH_FIXED_LEN	6		/* length of auth frame without challenge IE */
+
+BWL_PRE_PACKED_STRUCT struct dot11_assoc_req {
+	uint16			capability;	/* capability information */
+	uint16			listen;		/* listen interval */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ASSOC_REQ_FIXED_LEN	4	/* length of assoc frame without info elts */
+
+BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req {
+	uint16			capability;	/* capability information */
+	uint16			listen;		/* listen interval */
+	struct ether_addr	ap;		/* Current AP address */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_REASSOC_REQ_FIXED_LEN	10	/* length of assoc frame without info elts */
+
+BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp {
+	uint16			capability;	/* capability information */
+	uint16			status;		/* status code */
+	uint16			aid;		/* association ID */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_ASSOC_RESP_FIXED_LEN	6	/* length of assoc resp frame without info elts */
+
+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	/* d11 action measurement header length */
+
+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;
+
+/* These lengths assume 64 MU groups, as specified in 802.11ac-2013 */
+#define DOT11_ACTION_GID_MEMBERSHIP_LEN  8    /* bytes */
+#define DOT11_ACTION_GID_USER_POS_LEN   16    /* bytes */
+BWL_PRE_PACKED_STRUCT struct dot11_action_group_id {
+	uint8   category;
+	uint8   action;
+	uint8   membership_status[DOT11_ACTION_GID_MEMBERSHIP_LEN];
+	uint8   user_position[DOT11_ACTION_GID_USER_POS_LEN];
+} BWL_POST_PACKED_STRUCT;
+
+#define SM_PWRSAVE_ENABLE	1
+#define SM_PWRSAVE_MODE		2
+
+/* ************* 802.11h related definitions. ************* */
+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 {
+	int8 min;
+	int8 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 	/* length of IE data, not including 2 byte header */
+
+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;
+
+/**
+ * Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband
+ * offset for 40MHz operation.  The possible 3 values are:
+ * 1 = above control channel
+ * 3 = below control channel
+ * 0 = no extension channel
+ */
+BWL_PRE_PACKED_STRUCT struct dot11_extch {
+	uint8	id;		/* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */
+	uint8	len;		/* IE length */
+	uint8	extch;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extch dot11_extch_ie_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch {
+	uint8	id;		/* IE ID, 221, DOT11_MNG_PROPR_ID */
+	uint8	len;		/* IE length */
+	uint8	oui[3];
+	uint8	type;           /* type indicates what follows */
+	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	/* 802.11n ID not yet assigned */
+#define DOT11_EXTCH_IE_LEN	1
+#define DOT11_EXT_CH_MASK	0x03	/* extension channel mask */
+#define DOT11_EXT_CH_UPPER	0x01	/* ext. ch. on upper sb */
+#define DOT11_EXT_CH_LOWER	0x03	/* ext. ch. on lower sb */
+#define DOT11_EXT_CH_NONE	0x00	/* no extension ch.  */
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr {
+	uint8	category;
+	uint8	action;
+	uint8	data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_action_frmhdr dot11_action_frmhdr_t;
+#define DOT11_ACTION_FRMHDR_LEN	2
+
+/** CSA IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_channel_switch {
+	uint8 id;	/* id DOT11_MNG_CHANNEL_SWITCH_ID */
+	uint8 len;	/* length of IE */
+	uint8 mode;	/* mode 0 or 1 */
+	uint8 channel;	/* channel switch to */
+	uint8 count;	/* number of beacons before switching */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_channel_switch dot11_chan_switch_ie_t;
+
+#define DOT11_SWITCH_IE_LEN	3	/* length of IE data, not including 2 byte header */
+/* CSA mode - 802.11h-2003 $7.3.2.20 */
+#define DOT11_CSA_MODE_ADVISORY		0	/* no DOT11_CSA_MODE_NO_TX restriction imposed */
+#define DOT11_CSA_MODE_NO_TX		1	/* no transmission upon receiving CSA frame. */
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel {
+	uint8	category;
+	uint8	action;
+	dot11_chan_switch_ie_t chan_switch_ie;	/* for switch IE */
+	dot11_brcm_extch_ie_t extch_ie;		/* extension channel offset */
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11_csa_body {
+	uint8 mode;	/* mode 0 or 1 */
+	uint8 reg;	/* regulatory class */
+	uint8 channel;	/* channel switch to */
+	uint8 count;	/* number of beacons before switching */
+} BWL_POST_PACKED_STRUCT;
+
+/** 11n Extended Channel Switch IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_ext_csa {
+	uint8 id;	/* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */
+	uint8 len;	/* length of IE */
+	struct dot11_csa_body b;	/* body of the ie */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ext_csa dot11_ext_csa_ie_t;
+#define DOT11_EXT_CSA_IE_LEN	4	/* length of extended channel switch IE body */
+
+BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa {
+	uint8	category;
+	uint8	action;
+	dot11_ext_csa_ie_t chan_switch_ie;	/* for switch IE */
+} BWL_POST_PACKED_STRUCT;
+
+BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa {
+	uint8	category;
+	uint8	action;
+	struct dot11_csa_body b;	/* body of the ie */
+} BWL_POST_PACKED_STRUCT;
+
+/**  Wide Bandwidth Channel Switch IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_wide_bw_channel_switch {
+	uint8 id;				/* id DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID */
+	uint8 len;				/* length of IE */
+	uint8 channel_width;			/* new channel width */
+	uint8 center_frequency_segment_0;	/* center frequency segment 0 */
+	uint8 center_frequency_segment_1;	/* 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       /* length of IE data, not including 2 byte header */
+
+/** Channel Switch Wrapper IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_channel_switch_wrapper {
+	uint8 id;				/* id DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID */
+	uint8 len;				/* length of IE */
+	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;
+
+typedef enum wide_bw_chan_width {
+	WIDE_BW_CHAN_WIDTH_20	= 0,
+	WIDE_BW_CHAN_WIDTH_40	= 1,
+	WIDE_BW_CHAN_WIDTH_80	= 2,
+	WIDE_BW_CHAN_WIDTH_160	= 3,
+	WIDE_BW_CHAN_WIDTH_80_80	= 4
+} wide_bw_chan_width_t;
+
+/**  Wide Bandwidth Channel IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_wide_bw_channel {
+	uint8 id;				/* id DOT11_MNG_WIDE_BW_CHANNEL_ID */
+	uint8 len;				/* length of IE */
+	uint8 channel_width;			/* channel width */
+	uint8 center_frequency_segment_0;	/* center frequency segment 0 */
+	uint8 center_frequency_segment_1;	/* center frequency segment 1 */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wide_bw_channel dot11_wide_bw_chan_ie_t;
+
+#define DOT11_WIDE_BW_IE_LEN     3       /* length of IE data, not including 2 byte header */
+/** VHT Transmit Power Envelope IE data structure */
+BWL_PRE_PACKED_STRUCT struct dot11_vht_transmit_power_envelope {
+	uint8 id;				/* id DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID */
+	uint8 len;				/* length of IE */
+	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;
+
+/* vht transmit power envelope IE length depends on channel width */
+#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_40MHZ	1
+#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_80MHZ	2
+#define DOT11_VHT_TRANSMIT_PWR_ENVELOPE_IE_LEN_160MHZ	3
+
+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	/* length of OBSS Coexistence INFO IE */
+
+#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	/* fixed length of regclass */
+
+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_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_BSSTRANS		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
+
+/* TDLS Capabilities */
+#define DOT11_TDLS_CAP_TDLS			37		/* TDLS support */
+#define DOT11_TDLS_CAP_PU_BUFFER_STA	28		/* TDLS Peer U-APSD buffer STA support */
+#define DOT11_TDLS_CAP_PEER_PSM		20		/* TDLS Peer PSM support */
+#define DOT11_TDLS_CAP_CH_SW			30		/* TDLS Channel switch */
+#define DOT11_TDLS_CAP_PROH			38		/* TDLS prohibited */
+#define DOT11_TDLS_CAP_CH_SW_PROH		39		/* TDLS Channel switch prohibited */
+#define DOT11_TDLS_CAP_TDLS_WIDER_BW	61	/* TDLS Wider Band-Width */
+
+#define TDLS_CAP_MAX_BIT		39		/* TDLS max bit defined in ext cap */
+
+/* 802.11h/802.11k Measurement Request/Report IEs */
+/* Measurement Type field */
+#define DOT11_MEASURE_TYPE_BASIC 	0   /* d11 measurement basic type */
+#define DOT11_MEASURE_TYPE_CCA 		1   /* d11 measurement CCA type */
+#define DOT11_MEASURE_TYPE_RPI		2   /* d11 measurement RPI type */
+#define DOT11_MEASURE_TYPE_CHLOAD	3   /* d11 measurement Channel Load type */
+#define DOT11_MEASURE_TYPE_NOISE	4   /* d11 measurement Noise Histogram type */
+#define DOT11_MEASURE_TYPE_BEACON	5   /* d11 measurement Beacon type */
+#define DOT11_MEASURE_TYPE_FRAME	6   /* d11 measurement Frame type */
+#define DOT11_MEASURE_TYPE_STAT		7   /* d11 measurement STA Statistics type */
+#define DOT11_MEASURE_TYPE_LCI		8   /* d11 measurement LCI type */
+#define DOT11_MEASURE_TYPE_TXSTREAM	9   /* d11 measurement TX Stream type */
+#define DOT11_MEASURE_TYPE_MCDIAGS	10  /* d11 measurement multicast diagnostics */
+#define DOT11_MEASURE_TYPE_CIVICLOC	11  /* d11 measurement location civic */
+#define DOT11_MEASURE_TYPE_LOC_ID	12  /* d11 measurement location identifier */
+#define DOT11_MEASURE_TYPE_DIRCHANQ	13  /* d11 measurement dir channel quality */
+#define DOT11_MEASURE_TYPE_DIRMEAS	14  /* d11 measurement directional */
+#define DOT11_MEASURE_TYPE_DIRSTATS	15  /* d11 measurement directional stats */
+#define DOT11_MEASURE_TYPE_FTMRANGE	16  /* d11 measurement Fine Timing */
+#define DOT11_MEASURE_TYPE_PAUSE	255	/* d11 measurement pause type */
+
+/* Measurement Request Modes */
+#define DOT11_MEASURE_MODE_PARALLEL 	(1<<0)	/* d11 measurement parallel */
+#define DOT11_MEASURE_MODE_ENABLE 	(1<<1)	/* d11 measurement enable */
+#define DOT11_MEASURE_MODE_REQUEST	(1<<2)	/* d11 measurement request */
+#define DOT11_MEASURE_MODE_REPORT 	(1<<3)	/* d11 measurement report */
+#define DOT11_MEASURE_MODE_DUR 	(1<<4)	/* d11 measurement dur mandatory */
+/* Measurement Report Modes */
+#define DOT11_MEASURE_MODE_LATE 	(1<<0)	/* d11 measurement late */
+#define DOT11_MEASURE_MODE_INCAPABLE	(1<<1)	/* d11 measurement incapable */
+#define DOT11_MEASURE_MODE_REFUSED	(1<<2)	/* d11 measurement refuse */
+/* Basic Measurement Map bits */
+#define DOT11_MEASURE_BASIC_MAP_BSS	((uint8)(1<<0))	/* d11 measurement basic map BSS */
+#define DOT11_MEASURE_BASIC_MAP_OFDM	((uint8)(1<<1))	/* d11 measurement map OFDM */
+#define DOT11_MEASURE_BASIC_MAP_UKNOWN	((uint8)(1<<2))	/* d11 measurement map unknown */
+#define DOT11_MEASURE_BASIC_MAP_RADAR	((uint8)(1<<3))	/* d11 measurement map radar */
+#define DOT11_MEASURE_BASIC_MAP_UNMEAS	((uint8)(1<<4))	/* d11 measurement map unmeasuremnt */
+
+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	/* d11 measurement request IE length */
+/* length of Measure Request IE data not including variable len */
+#define DOT11_MNG_IE_MREQ_FIXED_LEN 3	/* d11 measurement request IE fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_meas_req_loc {
+	uint8 id;
+	uint8 len;
+	uint8 token;
+	uint8 mode;
+	uint8 type;
+	BWL_PRE_PACKED_STRUCT union
+	{
+		BWL_PRE_PACKED_STRUCT struct {
+			uint8 subject;
+			uint8 data[1];
+		} BWL_POST_PACKED_STRUCT lci;
+		BWL_PRE_PACKED_STRUCT struct {
+			uint8 subject;
+			uint8 type;  /* type of civic location */
+			uint8 siu;   /* service interval units */
+			uint16 si; /* service interval */
+			uint8 data[1];
+		} BWL_POST_PACKED_STRUCT civic;
+		BWL_PRE_PACKED_STRUCT struct {
+			uint8 subject;
+			uint8 siu;   /* service interval units */
+			uint16 si; /* service interval */
+			uint8 data[1];
+		} BWL_POST_PACKED_STRUCT locid;
+		BWL_PRE_PACKED_STRUCT struct {
+			uint16 max_init_delay;		/* maximum random initial delay */
+			uint8 min_ap_count;
+			uint8 data[1];
+		} BWL_POST_PACKED_STRUCT ftm_range;
+	} BWL_POST_PACKED_STRUCT req;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_meas_req_loc dot11_meas_req_loc_t;
+#define DOT11_MNG_IE_MREQ_MIN_LEN           4	/* d11 measurement report IE length */
+#define DOT11_MNG_IE_MREQ_LCI_FIXED_LEN     4	/* d11 measurement report IE length */
+#define DOT11_MNG_IE_MREQ_CIVIC_FIXED_LEN   8	/* d11 measurement report IE length */
+#define DOT11_MNG_IE_MREQ_FRNG_FIXED_LEN    6	/* d11 measurement report IE length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_lci_subelement {
+	uint8 subelement;
+	uint8 length;
+	uint8 lci_data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_lci_subelement dot11_lci_subelement_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_civic_subelement {
+	uint8 type;  /* type of civic location */
+	uint8 subelement;
+	uint8 length;
+	uint8 civic_data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_civic_subelement dot11_civic_subelement_t;
+
+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;
+		BWL_PRE_PACKED_STRUCT struct {
+			uint8 subelement;
+			uint8 length;
+			uint8 data[1];
+		} BWL_POST_PACKED_STRUCT lci;
+		BWL_PRE_PACKED_STRUCT struct {
+			uint8 type;  /* type of civic location */
+			uint8 subelement;
+			uint8 length;
+			uint8 data[1];
+		} BWL_POST_PACKED_STRUCT civic;
+		BWL_PRE_PACKED_STRUCT struct {
+			uint8 exp_tsf[8];
+			uint8 subelement;
+			uint8 length;
+			uint8 data[1];
+		} BWL_POST_PACKED_STRUCT locid;
+		BWL_PRE_PACKED_STRUCT struct {
+			uint8 entry_count;
+			uint8 data[1];
+		} BWL_POST_PACKED_STRUCT ftm_range;
+		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_MIN_LEN           5	/* d11 measurement report IE length */
+#define DOT11_MNG_IE_MREP_LCI_FIXED_LEN     5	/* d11 measurement report IE length */
+#define DOT11_MNG_IE_MREP_CIVIC_FIXED_LEN   6	/* d11 measurement report IE length */
+#define DOT11_MNG_IE_MREP_LOCID_FIXED_LEN   13	/* d11 measurement report IE length */
+#define DOT11_MNG_IE_MREP_BASIC_FIXED_LEN   15	/* d11 measurement report IE length */
+#define DOT11_MNG_IE_MREP_FRNG_FIXED_LEN    4
+
+/* length of Measure Report IE data not including variable len */
+#define DOT11_MNG_IE_MREP_FIXED_LEN	3	/* d11 measurement response IE fixed length */
+
+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	/* d11 measurement basic report length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_quiet {
+	uint8 id;
+	uint8 len;
+	uint8 count;	/* TBTTs until beacon interval in quiet starts */
+	uint8 period;	/* Beacon intervals between periodic quiet periods ? */
+	uint16 duration;	/* Length of quiet period, in TU's */
+	uint16 offset;	/* TU's offset from TBTT in Count field */
+} 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;
+
+/* WME Elements */
+#define WME_OUI			"\x00\x50\xf2"	/* WME OUI */
+#define WME_OUI_LEN		3
+#define WME_OUI_TYPE		2	/* WME type */
+#define WME_TYPE		2	/* WME type, deprecated */
+#define WME_SUBTYPE_IE		0	/* Information Element */
+#define WME_SUBTYPE_PARAM_IE	1	/* Parameter Element */
+#define WME_SUBTYPE_TSPEC	2	/* Traffic Specification */
+#define WME_VER			1	/* WME version */
+
+/* WME Access Category Indices (ACIs) */
+#define AC_BE			0	/* Best Effort */
+#define AC_BK			1	/* Background */
+#define AC_VI			2	/* Video */
+#define AC_VO			3	/* Voice */
+#define AC_COUNT		4	/* number of ACs */
+
+typedef uint8 ac_bitmap_t;	/* AC bitmap of (1 << AC_xx) */
+
+#define AC_BITMAP_NONE		0x0	/* No ACs */
+#define AC_BITMAP_ALL		0xf	/* All ACs */
+#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))))
+
+/* Management PKT Lifetime indices */
+/* Removing flag checks 'BCMINTERNAL || WLTEST'
+ * while merging MERGE BIS120RC4 to DINGO2
+ */
+#define MGMT_ALL		0xffff
+#define MGMT_AUTH_LT	FC_SUBTYPE_AUTH
+#define MGMT_ASSOC_LT	FC_SUBTYPE_ASSOC_REQ
+
+/** WME Information Element (IE) */
+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	/* WME IE length */
+
+BWL_PRE_PACKED_STRUCT struct edcf_acparam {
+	uint8	ACI;
+	uint8	ECW;
+	uint16  TXOP;		/* stored in network order (ls octet first) */
+} BWL_POST_PACKED_STRUCT;
+typedef struct edcf_acparam edcf_acparam_t;
+
+/** WME Parameter Element (PE) */
+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          /* WME Parameter IE length */
+
+/* QoS Info field for IE as sent from AP */
+#define WME_QI_AP_APSD_MASK         0x80        /* U-APSD Supported mask */
+#define WME_QI_AP_APSD_SHIFT        7           /* U-APSD Supported shift */
+#define WME_QI_AP_COUNT_MASK        0x0f        /* Parameter set count mask */
+#define WME_QI_AP_COUNT_SHIFT       0           /* Parameter set count shift */
+
+/* QoS Info field for IE as sent from STA */
+#define WME_QI_STA_MAXSPLEN_MASK    0x60        /* Max Service Period Length mask */
+#define WME_QI_STA_MAXSPLEN_SHIFT   5           /* Max Service Period Length shift */
+#define WME_QI_STA_APSD_ALL_MASK    0xf         /* APSD all AC bits mask */
+#define WME_QI_STA_APSD_ALL_SHIFT   0           /* APSD all AC bits shift */
+#define WME_QI_STA_APSD_BE_MASK     0x8         /* APSD AC_BE mask */
+#define WME_QI_STA_APSD_BE_SHIFT    3           /* APSD AC_BE shift */
+#define WME_QI_STA_APSD_BK_MASK     0x4         /* APSD AC_BK mask */
+#define WME_QI_STA_APSD_BK_SHIFT    2           /* APSD AC_BK shift */
+#define WME_QI_STA_APSD_VI_MASK     0x2         /* APSD AC_VI mask */
+#define WME_QI_STA_APSD_VI_SHIFT    1           /* APSD AC_VI shift */
+#define WME_QI_STA_APSD_VO_MASK     0x1         /* APSD AC_VO mask */
+#define WME_QI_STA_APSD_VO_SHIFT    0           /* APSD AC_VO shift */
+
+/* ACI */
+#define EDCF_AIFSN_MIN               1           /* AIFSN minimum value */
+#define EDCF_AIFSN_MAX               15          /* AIFSN maximum value */
+#define EDCF_AIFSN_MASK              0x0f        /* AIFSN mask */
+#define EDCF_ACM_MASK                0x10        /* ACM mask */
+#define EDCF_ACI_MASK                0x60        /* ACI mask */
+#define EDCF_ACI_SHIFT               5           /* ACI shift */
+#define EDCF_AIFSN_SHIFT             12          /* 4 MSB(0xFFF) in ifs_ctl for AC idx */
+
+/* ECW */
+#define EDCF_ECW_MIN                 0           /* cwmin/cwmax exponent minimum value */
+#define EDCF_ECW_MAX                 15          /* cwmin/cwmax exponent maximum value */
+#define EDCF_ECW2CW(exp)             ((1 << (exp)) - 1)
+#define EDCF_ECWMIN_MASK             0x0f        /* cwmin exponent form mask */
+#define EDCF_ECWMAX_MASK             0xf0        /* cwmax exponent form mask */
+#define EDCF_ECWMAX_SHIFT            4           /* cwmax exponent form shift */
+
+/* TXOP */
+#define EDCF_TXOP_MIN                0           /* TXOP minimum value */
+#define EDCF_TXOP_MAX                65535       /* TXOP maximum value */
+#define EDCF_TXOP2USEC(txop)         ((txop) << 5)
+
+/* Default BE ACI value for non-WME connection STA */
+#define NON_EDCF_AC_BE_ACI_STA          0x02
+
+/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */
+#define EDCF_AC_BE_ACI_STA           0x03	/* STA ACI value for best effort AC */
+#define EDCF_AC_BE_ECW_STA           0xA4	/* STA ECW value for best effort AC */
+#define EDCF_AC_BE_TXOP_STA          0x0000	/* STA TXOP value for best effort AC */
+#define EDCF_AC_BK_ACI_STA           0x27	/* STA ACI value for background AC */
+#define EDCF_AC_BK_ECW_STA           0xA4	/* STA ECW value for background AC */
+#define EDCF_AC_BK_TXOP_STA          0x0000	/* STA TXOP value for background AC */
+#define EDCF_AC_VI_ACI_STA           0x42	/* STA ACI value for video AC */
+#define EDCF_AC_VI_ECW_STA           0x43	/* STA ECW value for video AC */
+#define EDCF_AC_VI_TXOP_STA          0x005e	/* STA TXOP value for video AC */
+#define EDCF_AC_VO_ACI_STA           0x62	/* STA ACI value for audio AC */
+#define EDCF_AC_VO_ECW_STA           0x32	/* STA ECW value for audio AC */
+#define EDCF_AC_VO_TXOP_STA          0x002f	/* STA TXOP value for audio AC */
+
+/* Default EDCF parameters that AP uses; WMM draft Table 14 */
+#define EDCF_AC_BE_ACI_AP            0x03	/* AP ACI value for best effort AC */
+#define EDCF_AC_BE_ECW_AP            0x64	/* AP ECW value for best effort AC */
+#define EDCF_AC_BE_TXOP_AP           0x0000	/* AP TXOP value for best effort AC */
+#define EDCF_AC_BK_ACI_AP            0x27	/* AP ACI value for background AC */
+#define EDCF_AC_BK_ECW_AP            0xA4	/* AP ECW value for background AC */
+#define EDCF_AC_BK_TXOP_AP           0x0000	/* AP TXOP value for background AC */
+#define EDCF_AC_VI_ACI_AP            0x41	/* AP ACI value for video AC */
+#define EDCF_AC_VI_ECW_AP            0x43	/* AP ECW value for video AC */
+#define EDCF_AC_VI_TXOP_AP           0x005e	/* AP TXOP value for video AC */
+#define EDCF_AC_VO_ACI_AP            0x61	/* AP ACI value for audio AC */
+#define EDCF_AC_VO_ECW_AP            0x32	/* AP ECW value for audio AC */
+#define EDCF_AC_VO_TXOP_AP           0x002f	/* AP TXOP value for audio AC */
+
+/** EDCA Parameter IE */
+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          /* EDCA Parameter IE length */
+
+/** QoS Capability IE */
+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; 			/* 11, DOT11_MNG_QBSS_LOAD_ID */
+	uint8 length;
+	uint16 station_count; 		/* total number of STAs associated */
+	uint8 channel_utilization;	/* % of time, normalized to 255, QAP sensed medium busy */
+	uint16 aac; 			/* available admission capacity */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t;
+#define BSS_LOAD_IE_SIZE 	7	/* BSS load IE size */
+
+#define WLC_QBSS_LOAD_CHAN_FREE_MAX	0xff	/* max for channel free score */
+
+/* nom_msdu_size */
+#define FIXED_MSDU_SIZE 0x8000		/* MSDU size is fixed */
+#define MSDU_SIZE_MASK	0x7fff		/* (Nominal or fixed) MSDU size */
+
+/* surplus_bandwidth */
+/* Represented as 3 bits of integer, binary point, 13 bits fraction */
+#define	INTEGER_SHIFT	13	/* integer shift */
+#define FRACTION_MASK	0x1FFF	/* fraction mask */
+
+/** Management Notification Frame */
+BWL_PRE_PACKED_STRUCT struct dot11_management_notification {
+	uint8 category;			/* DOT11_ACTION_NOTIFICATION */
+	uint8 action;
+	uint8 token;
+	uint8 status;
+	uint8 data[1];			/* Elements */
+} BWL_POST_PACKED_STRUCT;
+#define DOT11_MGMT_NOTIFICATION_LEN 4	/* Fixed length */
+
+/** Timeout Interval IE */
+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
+
+/* WME Action Codes */
+#define WME_ADDTS_REQUEST	0	/* WME ADDTS request */
+#define WME_ADDTS_RESPONSE	1	/* WME ADDTS response */
+#define WME_DELTS_REQUEST	2	/* WME DELTS request */
+
+/* WME Setup Response Status Codes */
+#define WME_ADMISSION_ACCEPTED		0	/* WME admission accepted */
+#define WME_INVALID_PARAMETERS		1	/* WME invalide parameters */
+#define WME_ADMISSION_REFUSED		3	/* WME admission refused */
+
+/* Macro to take a pointer to a beacon or probe response
+ * body and return the char* pointer to the SSID info element
+ */
+#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN)
+
+/* Authentication frame payload constants */
+#define DOT11_OPEN_SYSTEM	0	/* d11 open authentication */
+#define DOT11_SHARED_KEY	1	/* d11 shared authentication */
+#define DOT11_FAST_BSS		2	/* d11 fast bss authentication */
+#define DOT11_CHALLENGE_LEN	128	/* d11 challenge text length */
+
+/* Frame control macros */
+#define FC_PVER_MASK		0x3	/* PVER mask */
+#define FC_PVER_SHIFT		0	/* PVER shift */
+#define FC_TYPE_MASK		0xC	/* type mask */
+#define FC_TYPE_SHIFT		2	/* type shift */
+#define FC_SUBTYPE_MASK		0xF0	/* subtype mask */
+#define FC_SUBTYPE_SHIFT	4	/* subtype shift */
+#define FC_TODS			0x100	/* to DS */
+#define FC_TODS_SHIFT		8	/* to DS shift */
+#define FC_FROMDS		0x200	/* from DS */
+#define FC_FROMDS_SHIFT		9	/* from DS shift */
+#define FC_MOREFRAG		0x400	/* more frag. */
+#define FC_MOREFRAG_SHIFT	10	/* more frag. shift */
+#define FC_RETRY		0x800	/* retry */
+#define FC_RETRY_SHIFT		11	/* retry shift */
+#define FC_PM			0x1000	/* PM */
+#define FC_PM_SHIFT		12	/* PM shift */
+#define FC_MOREDATA		0x2000	/* more data */
+#define FC_MOREDATA_SHIFT	13	/* more data shift */
+#define FC_WEP			0x4000	/* WEP */
+#define FC_WEP_SHIFT		14	/* WEP shift */
+#define FC_ORDER		0x8000	/* order */
+#define FC_ORDER_SHIFT		15	/* order shift */
+
+/* sequence control macros */
+#define SEQNUM_SHIFT		4	/* seq. number shift */
+#define SEQNUM_MAX		0x1000	/* max seqnum + 1 */
+#define FRAGNUM_MASK		0xF	/* frag. number mask */
+
+/* Frame Control type/subtype defs */
+
+/* FC Types */
+#define FC_TYPE_MNG		0	/* management type */
+#define FC_TYPE_CTL		1	/* control type */
+#define FC_TYPE_DATA		2	/* data type */
+
+/* Management Subtypes */
+#define FC_SUBTYPE_ASSOC_REQ		0	/* assoc. request */
+#define FC_SUBTYPE_ASSOC_RESP		1	/* assoc. response */
+#define FC_SUBTYPE_REASSOC_REQ		2	/* reassoc. request */
+#define FC_SUBTYPE_REASSOC_RESP		3	/* reassoc. response */
+#define FC_SUBTYPE_PROBE_REQ		4	/* probe request */
+#define FC_SUBTYPE_PROBE_RESP		5	/* probe response */
+#define FC_SUBTYPE_BEACON		8	/* beacon */
+#define FC_SUBTYPE_ATIM			9	/* ATIM */
+#define FC_SUBTYPE_DISASSOC		10	/* disassoc. */
+#define FC_SUBTYPE_AUTH			11	/* authentication */
+#define FC_SUBTYPE_DEAUTH		12	/* de-authentication */
+#define FC_SUBTYPE_ACTION		13	/* action */
+#define FC_SUBTYPE_ACTION_NOACK		14	/* action no-ack */
+
+/* Control Subtypes */
+#define FC_SUBTYPE_CTL_WRAPPER		7	/* Control Wrapper */
+#define FC_SUBTYPE_BLOCKACK_REQ		8	/* Block Ack Req */
+#define FC_SUBTYPE_BLOCKACK		9	/* Block Ack */
+#define FC_SUBTYPE_PS_POLL		10	/* PS poll */
+#define FC_SUBTYPE_RTS			11	/* RTS */
+#define FC_SUBTYPE_CTS			12	/* CTS */
+#define FC_SUBTYPE_ACK			13	/* ACK */
+#define FC_SUBTYPE_CF_END		14	/* CF-END */
+#define FC_SUBTYPE_CF_END_ACK		15	/* CF-END ACK */
+
+/* Data Subtypes */
+#define FC_SUBTYPE_DATA			0	/* Data */
+#define FC_SUBTYPE_DATA_CF_ACK		1	/* Data + CF-ACK */
+#define FC_SUBTYPE_DATA_CF_POLL		2	/* Data + CF-Poll */
+#define FC_SUBTYPE_DATA_CF_ACK_POLL	3	/* Data + CF-Ack + CF-Poll */
+#define FC_SUBTYPE_NULL			4	/* Null */
+#define FC_SUBTYPE_CF_ACK		5	/* CF-Ack */
+#define FC_SUBTYPE_CF_POLL		6	/* CF-Poll */
+#define FC_SUBTYPE_CF_ACK_POLL		7	/* CF-Ack + CF-Poll */
+#define FC_SUBTYPE_QOS_DATA		8	/* QoS Data */
+#define FC_SUBTYPE_QOS_DATA_CF_ACK	9	/* QoS Data + CF-Ack */
+#define FC_SUBTYPE_QOS_DATA_CF_POLL	10	/* QoS Data + CF-Poll */
+#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL	11	/* QoS Data + CF-Ack + CF-Poll */
+#define FC_SUBTYPE_QOS_NULL		12	/* QoS Null */
+#define FC_SUBTYPE_QOS_CF_POLL		14	/* QoS CF-Poll */
+#define FC_SUBTYPE_QOS_CF_ACK_POLL	15	/* QoS CF-Ack + CF-Poll */
+
+/* Data Subtype Groups */
+#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_SUBTYPE_ANY_PSPOLL(s)	(((s) & 10) != 0)
+
+/* Type/Subtype Combos */
+#define FC_KIND_MASK		(FC_TYPE_MASK | FC_SUBTYPE_MASK)	/* FC kind mask */
+
+#define FC_KIND(t, s)	(((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT))	/* FC kind */
+
+#define FC_SUBTYPE(fc)	(((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT)	/* Subtype from FC */
+#define FC_TYPE(fc)	(((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT)	/* Type from FC */
+
+#define FC_ASSOC_REQ	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ)	/* assoc. request */
+#define FC_ASSOC_RESP	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP)	/* assoc. response */
+#define FC_REASSOC_REQ	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ)	/* reassoc. request */
+#define FC_REASSOC_RESP	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP)	/* reassoc. response */
+#define FC_PROBE_REQ	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ)	/* probe request */
+#define FC_PROBE_RESP	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP)	/* probe response */
+#define FC_BEACON	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON)		/* beacon */
+#define FC_ATIM		FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ATIM)		/* ATIM */
+#define FC_DISASSOC	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC)	/* disassoc */
+#define FC_AUTH		FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH)		/* authentication */
+#define FC_DEAUTH	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH)		/* deauthentication */
+#define FC_ACTION	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION)		/* action */
+#define FC_ACTION_NOACK	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK)	/* action no-ack */
+
+#define FC_CTL_WRAPPER	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER)	/* Control Wrapper */
+#define FC_BLOCKACK_REQ	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ)	/* Block Ack Req */
+#define FC_BLOCKACK	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK)	/* Block Ack */
+#define FC_PS_POLL	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL)	/* PS poll */
+#define FC_RTS		FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS)		/* RTS */
+#define FC_CTS		FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS)		/* CTS */
+#define FC_ACK		FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK)		/* ACK */
+#define FC_CF_END	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END)		/* CF-END */
+#define FC_CF_END_ACK	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK)	/* CF-END ACK */
+
+#define FC_DATA		FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA)		/* data */
+#define FC_NULL_DATA	FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL)		/* null data */
+#define FC_DATA_CF_ACK	FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK)	/* data CF ACK */
+#define FC_QOS_DATA	FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA)	/* QoS data */
+#define FC_QOS_NULL	FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL)	/* QoS null */
+
+/* QoS Control Field */
+
+/* 802.1D Priority */
+#define QOS_PRIO_SHIFT		0	/* QoS priority shift */
+#define QOS_PRIO_MASK		0x0007	/* QoS priority mask */
+#define QOS_PRIO(qos)		(((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT)	/* QoS priority */
+
+/* Traffic Identifier */
+#define QOS_TID_SHIFT		0	/* QoS TID shift */
+#define QOS_TID_MASK		0x000f	/* QoS TID mask */
+#define QOS_TID(qos)		(((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT)	/* QoS TID */
+
+/* End of Service Period (U-APSD) */
+#define QOS_EOSP_SHIFT		4	/* QoS End of Service Period shift */
+#define QOS_EOSP_MASK		0x0010	/* QoS End of Service Period mask */
+#define QOS_EOSP(qos)		(((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT)	/* Qos EOSP */
+
+/* Ack Policy */
+#define QOS_ACK_NORMAL_ACK	0	/* Normal Ack */
+#define QOS_ACK_NO_ACK		1	/* No Ack (eg mcast) */
+#define QOS_ACK_NO_EXP_ACK	2	/* No Explicit Ack */
+#define QOS_ACK_BLOCK_ACK	3	/* Block Ack */
+#define QOS_ACK_SHIFT		5	/* QoS ACK shift */
+#define QOS_ACK_MASK		0x0060	/* QoS ACK mask */
+#define QOS_ACK(qos)		(((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT)	/* QoS ACK */
+
+/* A-MSDU flag */
+#define QOS_AMSDU_SHIFT		7	/* AMSDU shift */
+#define QOS_AMSDU_MASK		0x0080	/* AMSDU mask */
+
+/* Management Frames */
+
+/* Management Frame Constants */
+
+/* Fixed fields */
+#define DOT11_MNG_AUTH_ALGO_LEN		2	/* d11 management auth. algo. length */
+#define DOT11_MNG_AUTH_SEQ_LEN		2	/* d11 management auth. seq. length */
+#define DOT11_MNG_BEACON_INT_LEN	2	/* d11 management beacon interval length */
+#define DOT11_MNG_CAP_LEN		2	/* d11 management cap. length */
+#define DOT11_MNG_AP_ADDR_LEN		6	/* d11 management AP address length */
+#define DOT11_MNG_LISTEN_INT_LEN	2	/* d11 management listen interval length */
+#define DOT11_MNG_REASON_LEN		2	/* d11 management reason length */
+#define DOT11_MNG_AID_LEN		2	/* d11 management AID length */
+#define DOT11_MNG_STATUS_LEN		2	/* d11 management status length */
+#define DOT11_MNG_TIMESTAMP_LEN		8	/* d11 management timestamp length */
+
+/* DUR/ID field in assoc resp is 0xc000 | AID */
+#define DOT11_AID_MASK			0x3fff	/* d11 AID mask */
+
+/* Reason Codes */
+#define DOT11_RC_RESERVED		0	/* d11 RC reserved */
+#define DOT11_RC_UNSPECIFIED		1	/* Unspecified reason */
+#define DOT11_RC_AUTH_INVAL		2	/* Previous authentication no longer valid */
+#define DOT11_RC_DEAUTH_LEAVING		3	/* Deauthenticated because sending station
+						 * is leaving (or has left) IBSS or ESS
+						 */
+#define DOT11_RC_INACTIVITY		4	/* Disassociated due to inactivity */
+#define DOT11_RC_BUSY			5	/* Disassociated because AP is unable to handle
+						 * all currently associated stations
+						 */
+#define DOT11_RC_INVAL_CLASS_2		6	/* Class 2 frame received from
+						 * nonauthenticated station
+						 */
+#define DOT11_RC_INVAL_CLASS_3		7	/* Class 3 frame received from
+						 *  nonassociated station
+						 */
+#define DOT11_RC_DISASSOC_LEAVING	8	/* Disassociated because sending station is
+						 * leaving (or has left) BSS
+						 */
+#define DOT11_RC_NOT_AUTH		9	/* Station requesting (re)association is not
+						 * authenticated with responding station
+						 */
+#define DOT11_RC_BAD_PC			10	/* Unacceptable power capability element */
+#define DOT11_RC_BAD_CHANNELS		11	/* Unacceptable supported channels element */
+
+/* 12 is unused by STA but could be used by AP/GO */
+#define DOT11_RC_DISASSOC_BTM		12	/* Disassociated due to BSS Transition Magmt */
+
+
+/* 32-39 are QSTA specific reasons added in 11e */
+#define DOT11_RC_UNSPECIFIED_QOS	32	/* unspecified QoS-related reason */
+#define DOT11_RC_INSUFFCIENT_BW		33	/* QAP lacks sufficient bandwidth */
+#define DOT11_RC_EXCESSIVE_FRAMES	34	/* excessive number of frames need ack */
+#define DOT11_RC_TX_OUTSIDE_TXOP	35	/* transmitting outside the limits of txop */
+#define DOT11_RC_LEAVING_QBSS		36	/* QSTA is leaving the QBSS (or restting) */
+#define DOT11_RC_BAD_MECHANISM		37	/* does not want to use the mechanism */
+#define DOT11_RC_SETUP_NEEDED		38	/* mechanism needs a setup */
+#define DOT11_RC_TIMEOUT		39	/* timeout */
+
+#define DOT11_RC_MESH_PEERING_CANCELLED		52
+#define DOT11_RC_MESH_MAX_PEERS			53
+#define DOT11_RC_MESH_CONFIG_POLICY_VIOLN	54
+#define DOT11_RC_MESH_CLOSE_RECVD		55
+#define DOT11_RC_MESH_MAX_RETRIES		56
+#define DOT11_RC_MESH_CONFIRM_TIMEOUT		57
+#define DOT11_RC_MESH_INVALID_GTK		58
+#define DOT11_RC_MESH_INCONSISTENT_PARAMS	59
+
+#define DOT11_RC_MESH_INVALID_SEC_CAP		60
+#define DOT11_RC_MESH_PATHERR_NOPROXYINFO	61
+#define DOT11_RC_MESH_PATHERR_NOFWINFO		62
+#define DOT11_RC_MESH_PATHERR_DSTUNREACH	63
+#define DOT11_RC_MESH_MBSSMAC_EXISTS		64
+#define DOT11_RC_MESH_CHANSWITCH_REGREQ		65
+#define DOT11_RC_MESH_CHANSWITCH_UNSPEC		66
+
+#define DOT11_RC_MAX			66	/* Reason codes > 66 are reserved */
+
+#define DOT11_RC_TDLS_PEER_UNREACH	25
+#define DOT11_RC_TDLS_DOWN_UNSPECIFIED	26
+
+/* Status Codes */
+#define DOT11_SC_SUCCESS		0	/* Successful */
+#define DOT11_SC_FAILURE		1	/* Unspecified failure */
+#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2	/* TDLS wakeup schedule rejected but alternative  */
+					/* schedule provided */
+#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3	/* TDLS wakeup schedule rejected */
+#define DOT11_SC_TDLS_SEC_DISABLED	5	/* TDLS Security disabled */
+#define DOT11_SC_LIFETIME_REJ		6	/* Unacceptable lifetime */
+#define DOT11_SC_NOT_SAME_BSS		7	/* Not in same BSS */
+#define DOT11_SC_CAP_MISMATCH		10	/* Cannot support all requested
+						 * capabilities in the Capability
+						 * Information field
+						 */
+#define DOT11_SC_REASSOC_FAIL		11	/* Reassociation denied due to inability
+						 * to confirm that association exists
+						 */
+#define DOT11_SC_ASSOC_FAIL		12	/* Association denied due to reason
+						 * outside the scope of this standard
+						 */
+#define DOT11_SC_AUTH_MISMATCH		13	/* Responding station does not support
+						 * the specified authentication
+						 * algorithm
+						 */
+#define DOT11_SC_AUTH_SEQ		14	/* Received an Authentication frame
+						 * with authentication transaction
+						 * sequence number out of expected
+						 * sequence
+						 */
+#define DOT11_SC_AUTH_CHALLENGE_FAIL	15	/* Authentication rejected because of
+						 * challenge failure
+						 */
+#define DOT11_SC_AUTH_TIMEOUT		16	/* Authentication rejected due to timeout
+						 * waiting for next frame in sequence
+						 */
+#define DOT11_SC_ASSOC_BUSY_FAIL	17	/* Association denied because AP is
+						 * unable to handle additional
+						 * associated stations
+						 */
+#define DOT11_SC_ASSOC_RATE_MISMATCH	18	/* Association denied due to requesting
+						 * station not supporting all of the
+						 * data rates in the BSSBasicRateSet
+						 * parameter
+						 */
+#define DOT11_SC_ASSOC_SHORT_REQUIRED	19	/* Association denied due to requesting
+						 * station not supporting the Short
+						 * Preamble option
+						 */
+#define DOT11_SC_ASSOC_PBCC_REQUIRED	20	/* Association denied due to requesting
+						 * station not supporting the PBCC
+						 * Modulation option
+						 */
+#define DOT11_SC_ASSOC_AGILITY_REQUIRED	21	/* Association denied due to requesting
+						 * station not supporting the Channel
+						 * Agility option
+						 */
+#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED	22	/* Association denied because Spectrum
+							 * Management capability is required.
+							 */
+#define DOT11_SC_ASSOC_BAD_POWER_CAP	23	/* Association denied because the info
+						 * in the Power Cap element is
+						 * unacceptable.
+						 */
+#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS	24	/* Association denied because the info
+						 * in the Supported Channel element is
+						 * unacceptable
+						 */
+#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED	25	/* Association denied due to requesting
+							 * station not supporting the Short Slot
+							 * Time option
+							 */
+#define DOT11_SC_ASSOC_DSSSOFDM_REQUIRED 26	/* Association denied because requesting station
+						 * does not support the DSSS-OFDM option
+						 */
+#define DOT11_SC_ASSOC_HT_REQUIRED	27	/* Association denied because the requesting
+						 * station does not support HT features
+						 */
+#define DOT11_SC_ASSOC_R0KH_UNREACHABLE	28	/* Association denied due to AP
+						 * being unable to reach the R0 Key Holder
+						 */
+#define DOT11_SC_ASSOC_TRY_LATER	30	/* Association denied temporarily, try again later
+						 */
+#define DOT11_SC_ASSOC_MFP_VIOLATION	31	/* Association denied due to Robust Management
+						 * frame policy violation
+						 */
+
+#define	DOT11_SC_DECLINED		37	/* request declined */
+#define	DOT11_SC_INVALID_PARAMS		38	/* One or more params have invalid values */
+#define DOT11_SC_INVALID_PAIRWISE_CIPHER	42 /* invalid pairwise cipher */
+#define	DOT11_SC_INVALID_AKMP		43	/* Association denied due to invalid AKMP */
+#define DOT11_SC_UNSUP_RSNIE_VER	44	/* Unsupported RSN IE version */
+#define DOT11_SC_INVALID_RSNIE_CAP	45	/* invalid RSN IE capabilities */
+#define DOT11_SC_DLS_NOT_ALLOWED	48	/* DLS is not allowed in the BSS by policy */
+#define	DOT11_SC_INVALID_PMKID		53	/* Association denied due to invalid PMKID */
+#define	DOT11_SC_INVALID_MDID		54	/* Association denied due to invalid MDID */
+#define	DOT11_SC_INVALID_FTIE		55	/* Association denied due to invalid FTIE */
+
+#define DOT11_SC_ADV_PROTO_NOT_SUPPORTED	59	/* ad proto not supported */
+#define DOT11_SC_NO_OUTSTAND_REQ			60	/* no outstanding req */
+#define DOT11_SC_RSP_NOT_RX_FROM_SERVER		61	/* no response from server */
+#define DOT11_SC_TIMEOUT					62	/* timeout */
+#define DOT11_SC_QUERY_RSP_TOO_LARGE		63	/* query rsp too large */
+#define DOT11_SC_SERVER_UNREACHABLE			65	/* server unreachable */
+
+#define DOT11_SC_UNEXP_MSG			70	/* Unexpected message */
+#define DOT11_SC_INVALID_SNONCE		71	/* Invalid SNonce */
+#define DOT11_SC_INVALID_RSNIE		72	/* Invalid contents of RSNIE */
+
+#define DOT11_SC_ANTICLOG_TOCKEN_REQUIRED	76	/* Anti-clogging tocken required */
+#define DOT11_SC_INVALID_FINITE_CYCLIC_GRP	77	/* Invalid contents of RSNIE */
+
+#define DOT11_SC_ASSOC_VHT_REQUIRED	104	/* Association denied because the requesting
+						 * station does not support VHT features.
+						 */
+
+#define DOT11_SC_TRANSMIT_FAILURE	79	/* transmission failure */
+
+/* Info Elts, length of INFORMATION portion of Info Elts */
+#define DOT11_MNG_DS_PARAM_LEN			1	/* d11 management DS parameter length */
+#define DOT11_MNG_IBSS_PARAM_LEN		2	/* d11 management IBSS parameter length */
+
+/* TIM Info element has 3 bytes fixed info in INFORMATION field,
+ * followed by 1 to 251 bytes of Partial Virtual Bitmap
+ */
+#define DOT11_MNG_TIM_FIXED_LEN			3	/* d11 management TIM fixed length */
+#define DOT11_MNG_TIM_DTIM_COUNT		0	/* d11 management DTIM count */
+#define DOT11_MNG_TIM_DTIM_PERIOD		1	/* d11 management DTIM period */
+#define DOT11_MNG_TIM_BITMAP_CTL		2	/* d11 management TIM BITMAP control  */
+#define DOT11_MNG_TIM_PVB			3	/* d11 management TIM PVB */
+
+/* TLV defines */
+#define TLV_TAG_OFF		0	/* tag offset */
+#define TLV_LEN_OFF		1	/* length offset */
+#define TLV_HDR_LEN		2	/* header length */
+#define TLV_BODY_OFF		2	/* body offset */
+#define TLV_BODY_LEN_MAX	255	/* max body length */
+
+/* Management Frame Information Element IDs */
+#define DOT11_MNG_SSID_ID			0	/* d11 management SSID id */
+#define DOT11_MNG_RATES_ID			1	/* d11 management rates id */
+#define DOT11_MNG_FH_PARMS_ID			2	/* d11 management FH parameter id */
+#define DOT11_MNG_DS_PARMS_ID			3	/* d11 management DS parameter id */
+#define DOT11_MNG_CF_PARMS_ID			4	/* d11 management CF parameter id */
+#define DOT11_MNG_TIM_ID			5	/* d11 management TIM id */
+#define DOT11_MNG_IBSS_PARMS_ID			6	/* d11 management IBSS parameter id */
+#define DOT11_MNG_COUNTRY_ID			7	/* d11 management country id */
+#define DOT11_MNG_HOPPING_PARMS_ID		8	/* d11 management hopping parameter id */
+#define DOT11_MNG_HOPPING_TABLE_ID		9	/* d11 management hopping table id */
+#define DOT11_MNG_FTM_SYNC_INFO_ID		9	/* 11mc D4.3 */
+#define DOT11_MNG_REQUEST_ID			10	/* d11 management request id */
+#define DOT11_MNG_QBSS_LOAD_ID 			11	/* d11 management QBSS Load id */
+#define DOT11_MNG_EDCA_PARAM_ID			12	/* 11E EDCA Parameter id */
+#define DOT11_MNG_TSPEC_ID			13	/* d11 management TSPEC id */
+#define DOT11_MNG_TCLAS_ID			14	/* d11 management TCLAS id */
+#define DOT11_MNG_CHALLENGE_ID			16	/* d11 management chanllenge id */
+#define DOT11_MNG_PWR_CONSTRAINT_ID		32	/* 11H PowerConstraint */
+#define DOT11_MNG_PWR_CAP_ID			33	/* 11H PowerCapability */
+#define DOT11_MNG_TPC_REQUEST_ID 		34	/* 11H TPC Request */
+#define DOT11_MNG_TPC_REPORT_ID			35	/* 11H TPC Report */
+#define DOT11_MNG_SUPP_CHANNELS_ID		36	/* 11H Supported Channels */
+#define DOT11_MNG_CHANNEL_SWITCH_ID		37	/* 11H ChannelSwitch Announcement */
+#define DOT11_MNG_MEASURE_REQUEST_ID		38	/* 11H MeasurementRequest */
+#define DOT11_MNG_MEASURE_REPORT_ID		39	/* 11H MeasurementReport */
+#define DOT11_MNG_QUIET_ID			40	/* 11H Quiet */
+#define DOT11_MNG_IBSS_DFS_ID			41	/* 11H IBSS_DFS */
+#define DOT11_MNG_ERP_ID			42	/* d11 management ERP id */
+#define DOT11_MNG_TS_DELAY_ID			43	/* d11 management TS Delay id */
+#define DOT11_MNG_TCLAS_PROC_ID			44	/* d11 management TCLAS processing id */
+#define	DOT11_MNG_HT_CAP			45	/* d11 mgmt HT cap id */
+#define DOT11_MNG_QOS_CAP_ID			46	/* 11E QoS Capability id */
+#define DOT11_MNG_NONERP_ID			47	/* d11 management NON-ERP id */
+#define DOT11_MNG_RSN_ID			48	/* d11 management RSN id */
+#define DOT11_MNG_EXT_RATES_ID			50	/* d11 management ext. rates id */
+#define DOT11_MNG_AP_CHREP_ID			51	/* 11k AP Channel report id */
+#define DOT11_MNG_NEIGHBOR_REP_ID		52	/* 11k & 11v Neighbor report id */
+#define DOT11_MNG_RCPI_ID			53	/* 11k RCPI */
+#define DOT11_MNG_MDIE_ID			54	/* 11r Mobility domain id */
+#define DOT11_MNG_FTIE_ID			55	/* 11r Fast Bss Transition id */
+#define DOT11_MNG_FT_TI_ID			56	/* 11r Timeout Interval id */
+#define DOT11_MNG_RDE_ID			57	/* 11r RIC Data Element id */
+#define	DOT11_MNG_REGCLASS_ID			59	/* d11 management regulatory class id */
+#define DOT11_MNG_EXT_CSA_ID			60	/* d11 Extended CSA */
+#define	DOT11_MNG_HT_ADD			61	/* d11 mgmt additional HT info */
+#define	DOT11_MNG_EXT_CHANNEL_OFFSET		62	/* d11 mgmt ext channel offset */
+#define DOT11_MNG_BSS_AVR_ACCESS_DELAY_ID	63	/* 11k bss average access delay */
+#define DOT11_MNG_ANTENNA_ID			64	/* 11k antenna id */
+#define DOT11_MNG_RSNI_ID			65	/* 11k RSNI id */
+#define DOT11_MNG_MEASUREMENT_PILOT_TX_ID	66	/* 11k measurement pilot tx info id */
+#define DOT11_MNG_BSS_AVAL_ADMISSION_CAP_ID	67	/* 11k bss aval admission cap id */
+#define DOT11_MNG_BSS_AC_ACCESS_DELAY_ID	68	/* 11k bss AC access delay id */
+#define DOT11_MNG_WAPI_ID			68	/* d11 management WAPI id */
+#define DOT11_MNG_TIME_ADVERTISE_ID	69	/* 11p time advertisement */
+#define DOT11_MNG_RRM_CAP_ID		70	/* 11k radio measurement capability */
+#define DOT11_MNG_MULTIPLE_BSSID_ID		71	/* 11k multiple BSSID id */
+#define	DOT11_MNG_HT_BSS_COEXINFO_ID		72	/* d11 mgmt OBSS Coexistence INFO */
+#define	DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID	73	/* d11 mgmt OBSS Intolerant Channel list */
+#define	DOT11_MNG_HT_OBSS_ID			74	/* d11 mgmt OBSS HT info */
+#define DOT11_MNG_MMIE_ID			76	/* d11 mgmt MIC IE */
+#define DOT11_MNG_FMS_DESCR_ID			86	/* 11v FMS descriptor */
+#define DOT11_MNG_FMS_REQ_ID			87	/* 11v FMS request id */
+#define DOT11_MNG_FMS_RESP_ID			88	/* 11v FMS response id */
+#define DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID	90	/* 11v bss max idle id */
+#define DOT11_MNG_TFS_REQUEST_ID		91	/* 11v tfs request id */
+#define DOT11_MNG_TFS_RESPONSE_ID		92	/* 11v tfs response id */
+#define DOT11_MNG_WNM_SLEEP_MODE_ID		93	/* 11v wnm-sleep mode id */
+#define DOT11_MNG_TIMBC_REQ_ID			94	/* 11v TIM broadcast request id */
+#define DOT11_MNG_TIMBC_RESP_ID			95	/* 11v TIM broadcast response id */
+#define DOT11_MNG_CHANNEL_USAGE			97	/* 11v channel usage */
+#define DOT11_MNG_TIME_ZONE_ID			98	/* 11v time zone */
+#define DOT11_MNG_DMS_REQUEST_ID		99	/* 11v dms request id */
+#define DOT11_MNG_DMS_RESPONSE_ID		100	/* 11v dms response id */
+#define DOT11_MNG_LINK_IDENTIFIER_ID		101	/* 11z TDLS Link Identifier IE */
+#define DOT11_MNG_WAKEUP_SCHEDULE_ID		102	/* 11z TDLS Wakeup Schedule IE */
+#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID	104	/* 11z TDLS Channel Switch Timing IE */
+#define DOT11_MNG_PTI_CONTROL_ID		105	/* 11z TDLS PTI Control IE */
+#define DOT11_MNG_PU_BUFFER_STATUS_ID		106	/* 11z TDLS PU Buffer Status IE */
+#define DOT11_MNG_INTERWORKING_ID		107	/* 11u interworking */
+#define DOT11_MNG_ADVERTISEMENT_ID		108	/* 11u advertisement protocol */
+#define DOT11_MNG_EXP_BW_REQ_ID			109	/* 11u expedited bandwith request */
+#define DOT11_MNG_QOS_MAP_ID			110	/* 11u QoS map set */
+#define DOT11_MNG_ROAM_CONSORT_ID		111	/* 11u roaming consortium */
+#define DOT11_MNG_EMERGCY_ALERT_ID		112	/* 11u emergency alert identifier */
+#define DOT11_MNG_MESH_CONFIG			113	/* Mesh Configuration */
+#define DOT11_MNG_MESH_ID			114	/* Mesh ID */
+#define DOT11_MNG_MESH_PEER_MGMT_ID		117	/* Mesh PEER MGMT IE */
+#define DOT11_MNG_EXT_CAP_ID			127	/* d11 mgmt ext capability */
+#define DOT11_MNG_EXT_PREQ_ID			130	/* Mesh PREQ IE */
+#define DOT11_MNG_EXT_PREP_ID			131	/* Mesh PREP IE */
+#define DOT11_MNG_EXT_PERR_ID			132	/* Mesh PERR IE */
+#define	DOT11_MNG_VHT_CAP_ID			191	/* d11 mgmt VHT cap id */
+#define	DOT11_MNG_VHT_OPERATION_ID		192	/* d11 mgmt VHT op id */
+#define	DOT11_MNG_EXT_BSSLOAD_ID		193	/* d11 mgmt VHT extended bss load id */
+#define DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID	194	/* Wide BW Channel Switch IE */
+#define DOT11_MNG_VHT_TRANSMIT_POWER_ENVELOPE_ID 195	/* VHT transmit Power Envelope IE */
+#define DOT11_MNG_CHANNEL_SWITCH_WRAPPER_ID	196	/* Channel Switch Wrapper IE */
+#define DOT11_MNG_AID_ID			197	/* Association ID  IE */
+#define	DOT11_MNG_OPER_MODE_NOTIF_ID		199	/* d11 mgmt VHT oper mode notif */
+#define DOT11_MNG_HE_CAP_ID			201
+#define DOT11_MNG_HE_OP_ID			202
+#define DOT11_MNG_FTM_PARAMS_ID			206
+#define DOT11_MNG_TWT_ID			216	/* 11ah D5.0 */
+#define DOT11_MNG_WPA_ID			221	/* d11 management WPA id */
+#define DOT11_MNG_PROPR_ID			221
+/* should start using this one instead of above two */
+#define DOT11_MNG_VS_ID				221	/* d11 management Vendor Specific IE */
+
+#define DOT11_MNG_ID_EXT_ID			255	/* Element ID Extension 11mc D4.3 */
+
+#define DOT11_MNG_IE_ID_EXT_MATCH(_ie, _id) (\
+	((_ie)->id == DOT11_MNG_ID_EXT_ID) && \
+	((_ie)->len > 0) && \
+	((_id) == ((uint8 *)(_ie) + TLV_HDR_LEN)[0]))
+
+#define DOT11_MNG_IE_ID_EXT_INIT(_ie, _id, _len) do {\
+		(_ie)->id = DOT11_MNG_ID_EXT_ID; \
+		(_ie)->len = _len; \
+		(_ie)->id_ext = _id; \
+	} while (0)
+
+/* Rate Defines */
+
+/* Valid rates for the Supported Rates and Extended Supported Rates IEs.
+ * Encoding is the rate in 500kbps units, rouding up for fractional values.
+ * 802.11-2012, section 6.5.5.2, DATA_RATE parameter enumerates all the values.
+ * The rate values cover DSSS, HR/DSSS, ERP, and OFDM phy rates.
+ * The defines below do not cover the rates specific to 10MHz, {3, 4.5, 27},
+ * and 5MHz, {1.5, 2.25, 3, 4.5, 13.5}, which are not supported by Broadcom devices.
+ */
+
+#define DOT11_RATE_1M   2       /* 1  Mbps in 500kbps units */
+#define DOT11_RATE_2M   4       /* 2  Mbps in 500kbps units */
+#define DOT11_RATE_5M5  11      /* 5.5 Mbps in 500kbps units */
+#define DOT11_RATE_11M  22      /* 11 Mbps in 500kbps units */
+#define DOT11_RATE_6M   12      /* 6  Mbps in 500kbps units */
+#define DOT11_RATE_9M   18      /* 9  Mbps in 500kbps units */
+#define DOT11_RATE_12M  24      /* 12 Mbps in 500kbps units */
+#define DOT11_RATE_18M  36      /* 18 Mbps in 500kbps units */
+#define DOT11_RATE_24M  48      /* 24 Mbps in 500kbps units */
+#define DOT11_RATE_36M  72      /* 36 Mbps in 500kbps units */
+#define DOT11_RATE_48M  96      /* 48 Mbps in 500kbps units */
+#define DOT11_RATE_54M  108     /* 54 Mbps in 500kbps units */
+#define DOT11_RATE_MAX  108     /* highest rate (54 Mbps) in 500kbps units */
+
+/* Supported Rates and Extended Supported Rates IEs
+ * The supported rates octets are defined a the MSB indicatin a Basic Rate
+ * and bits 0-6 as the rate value
+ */
+#define DOT11_RATE_BASIC                0x80 /* flag for a Basic Rate */
+#define DOT11_RATE_MASK                 0x7F /* mask for numeric part of rate */
+
+/* BSS Membership Selector parameters
+ * 802.11-2012 and 802.11ac_D4.0 sec 8.4.2.3
+ * These selector values are advertised in Supported Rates and Extended Supported Rates IEs
+ * in the supported rates list with the Basic rate bit set.
+ * Constants below include the basic bit.
+ */
+#define DOT11_BSS_MEMBERSHIP_HT         0xFF  /* Basic 0x80 + 127, HT Required to join */
+#define DOT11_BSS_MEMBERSHIP_VHT        0xFE  /* Basic 0x80 + 126, VHT Required to join */
+
+/* ERP info element bit values */
+#define DOT11_MNG_ERP_LEN			1	/* ERP is currently 1 byte long */
+#define DOT11_MNG_NONERP_PRESENT		0x01	/* NonERP (802.11b) STAs are present
+							 *in the BSS
+							 */
+#define DOT11_MNG_USE_PROTECTION		0x02	/* Use protection mechanisms for
+							 *ERP-OFDM frames
+							 */
+#define DOT11_MNG_BARKER_PREAMBLE		0x04	/* Short Preambles: 0 == allowed,
+							 * 1 == not allowed
+							 */
+/* TS Delay element offset & size */
+#define DOT11_MGN_TS_DELAY_LEN		4	/* length of TS DELAY IE */
+#define TS_DELAY_FIELD_SIZE			4	/* TS DELAY field size */
+
+/* Capability Information Field */
+#define DOT11_CAP_ESS				0x0001	/* d11 cap. ESS */
+#define DOT11_CAP_IBSS				0x0002	/* d11 cap. IBSS */
+#define DOT11_CAP_POLLABLE			0x0004	/* d11 cap. pollable */
+#define DOT11_CAP_POLL_RQ			0x0008	/* d11 cap. poll request */
+#define DOT11_CAP_PRIVACY			0x0010	/* d11 cap. privacy */
+#define DOT11_CAP_SHORT				0x0020	/* d11 cap. short */
+#define DOT11_CAP_PBCC				0x0040	/* d11 cap. PBCC */
+#define DOT11_CAP_AGILITY			0x0080	/* d11 cap. agility */
+#define DOT11_CAP_SPECTRUM			0x0100	/* d11 cap. spectrum */
+#define DOT11_CAP_QOS				0x0200	/* d11 cap. qos */
+#define DOT11_CAP_SHORTSLOT			0x0400	/* d11 cap. shortslot */
+#define DOT11_CAP_APSD				0x0800	/* d11 cap. apsd */
+#define DOT11_CAP_RRM				0x1000	/* d11 cap. 11k radio measurement */
+#define DOT11_CAP_CCK_OFDM			0x2000	/* d11 cap. CCK/OFDM */
+#define DOT11_CAP_DELAY_BA			0x4000	/* d11 cap. delayed block ack */
+#define DOT11_CAP_IMMEDIATE_BA			0x8000	/* d11 cap. immediate block ack */
+
+/* Extended capabilities IE bitfields */
+/* 20/40 BSS Coexistence Management support bit position */
+#define DOT11_EXT_CAP_OBSS_COEX_MGMT		0
+/* Extended Channel Switching support bit position */
+#define DOT11_EXT_CAP_EXT_CHAN_SWITCHING	2
+/* scheduled PSMP support bit position */
+#define DOT11_EXT_CAP_SPSMP			6
+/*  Flexible Multicast Service */
+#define DOT11_EXT_CAP_FMS			11
+/* proxy ARP service support bit position */
+#define DOT11_EXT_CAP_PROXY_ARP			12
+/* Civic Location */
+#define DOT11_EXT_CAP_CIVIC_LOC			14
+/* Geospatial Location */
+#define DOT11_EXT_CAP_LCI			15
+/* Traffic Filter Service */
+#define DOT11_EXT_CAP_TFS			16
+/* WNM-Sleep Mode */
+#define DOT11_EXT_CAP_WNM_SLEEP			17
+/* TIM Broadcast service */
+#define DOT11_EXT_CAP_TIMBC			18
+/* BSS Transition Management support bit position */
+#define DOT11_EXT_CAP_BSSTRANS_MGMT		19
+/* Direct Multicast Service */
+#define DOT11_EXT_CAP_DMS			26
+/* Interworking support bit position */
+#define DOT11_EXT_CAP_IW			31
+/* QoS map support bit position */
+#define DOT11_EXT_CAP_QOS_MAP		32
+/* service Interval granularity bit position and mask */
+#define DOT11_EXT_CAP_SI			41
+#define DOT11_EXT_CAP_SI_MASK			0x0E
+/* Location Identifier service */
+#define DOT11_EXT_CAP_IDENT_LOC			44
+/* WNM notification */
+#define DOT11_EXT_CAP_WNM_NOTIF			46
+/* Operating mode notification - VHT (11ac D3.0 - 8.4.2.29) */
+#define DOT11_EXT_CAP_OPER_MODE_NOTIF		62
+/* Fine timing measurement - D3.0 */
+#define DOT11_EXT_CAP_FTM_RESPONDER		70
+#define DOT11_EXT_CAP_FTM_INITIATOR		71 /* tentative 11mcd3.0 */
+#ifdef WL_FTM
+#define DOT11_EXT_CAP_MAX_BIT_IDX		95	/* !!!update this please!!! */
+#else
+#define DOT11_EXT_CAP_MAX_BIT_IDX		62	/* !!!update this please!!! */
+#endif
+
+/* extended capability */
+#ifndef DOT11_EXTCAP_LEN_MAX
+#define DOT11_EXTCAP_LEN_MAX ((DOT11_EXT_CAP_MAX_BIT_IDX + 8) >> 3)
+#endif
+
+BWL_PRE_PACKED_STRUCT struct dot11_extcap {
+	uint8 extcap[DOT11_EXTCAP_LEN_MAX];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_extcap dot11_extcap_t;
+
+/* VHT Operating mode bit fields -  (11ac D3.0 - 8.4.1.50) */
+#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)
+
+/* Operating mode information element 802.11ac D3.0 - 8.4.2.168 */
+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
+
+/* Extended Capability Information Field */
+#define DOT11_OBSS_COEX_MNG_SUPPORT	0x01	/* 20/40 BSS Coexistence Management support */
+
+/*
+ * Action Frame Constants
+ */
+#define DOT11_ACTION_HDR_LEN		2	/* action frame category + action field */
+#define DOT11_ACTION_CAT_OFF		0	/* category offset */
+#define DOT11_ACTION_ACT_OFF		1	/* action offset */
+
+/* Action Category field (sec 8.4.1.11) */
+#define DOT11_ACTION_CAT_ERR_MASK	0x80	/* category error mask */
+#define DOT11_ACTION_CAT_MASK		0x7F	/* category mask */
+#define DOT11_ACTION_CAT_SPECT_MNG	0	/* category spectrum management */
+#define DOT11_ACTION_CAT_QOS		1	/* category QoS */
+#define DOT11_ACTION_CAT_DLS		2	/* category DLS */
+#define DOT11_ACTION_CAT_BLOCKACK	3	/* category block ack */
+#define DOT11_ACTION_CAT_PUBLIC		4	/* category public */
+#define DOT11_ACTION_CAT_RRM		5	/* category radio measurements */
+#define DOT11_ACTION_CAT_FBT	6	/* category fast bss transition */
+#define DOT11_ACTION_CAT_HT		7	/* category for HT */
+#define	DOT11_ACTION_CAT_SA_QUERY	8	/* security association query */
+#define	DOT11_ACTION_CAT_PDPA		9	/* protected dual of public action */
+#define DOT11_ACTION_CAT_WNM		10	/* category for WNM */
+#define DOT11_ACTION_CAT_UWNM		11	/* category for Unprotected WNM */
+#define DOT11_ACTION_CAT_MESH		13	/* category for Mesh */
+#define DOT11_ACTION_CAT_SELFPROT	15	/* category for Mesh, self protected */
+#define DOT11_ACTION_NOTIFICATION	17
+#define DOT11_ACTION_CAT_VHT		21	/* VHT action */
+#define DOT11_ACTION_CAT_HE		26	/* HE action frame */
+#define DOT11_ACTION_CAT_VSP		126	/* protected vendor specific */
+#define DOT11_ACTION_CAT_VS		127	/* category Vendor Specific */
+
+/* Spectrum Management Action IDs (sec 7.4.1) */
+#define DOT11_SM_ACTION_M_REQ		0	/* d11 action measurement request */
+#define DOT11_SM_ACTION_M_REP		1	/* d11 action measurement response */
+#define DOT11_SM_ACTION_TPC_REQ		2	/* d11 action TPC request */
+#define DOT11_SM_ACTION_TPC_REP		3	/* d11 action TPC response */
+#define DOT11_SM_ACTION_CHANNEL_SWITCH	4	/* d11 action channel switch */
+#define DOT11_SM_ACTION_EXT_CSA		5	/* d11 extened CSA for 11n */
+
+/* QoS action ids */
+#define DOT11_QOS_ACTION_ADDTS_REQ	0	/* d11 action ADDTS request */
+#define DOT11_QOS_ACTION_ADDTS_RESP	1	/* d11 action ADDTS response */
+#define DOT11_QOS_ACTION_DELTS		2	/* d11 action DELTS */
+#define DOT11_QOS_ACTION_SCHEDULE	3	/* d11 action schedule */
+#define DOT11_QOS_ACTION_QOS_MAP	4	/* d11 action QOS map */
+
+/* HT action ids */
+#define DOT11_ACTION_ID_HT_CH_WIDTH	0	/* notify channel width action id */
+#define DOT11_ACTION_ID_HT_MIMO_PS	1	/* mimo ps action id */
+
+/* Public action ids */
+#define DOT11_PUB_ACTION_BSS_COEX_MNG	0	/* 20/40 Coexistence Management action id */
+#define DOT11_PUB_ACTION_CHANNEL_SWITCH	4	/* d11 action channel switch */
+#define DOT11_PUB_ACTION_GAS_CB_REQ	12	/* GAS Comeback Request */
+#define DOT11_PUB_ACTION_FTM_REQ	32		/* FTM request */
+#define DOT11_PUB_ACTION_FTM		33		/* FTM measurement */
+
+/* Block Ack action types */
+#define DOT11_BA_ACTION_ADDBA_REQ	0	/* ADDBA Req action frame type */
+#define DOT11_BA_ACTION_ADDBA_RESP	1	/* ADDBA Resp action frame type */
+#define DOT11_BA_ACTION_DELBA		2	/* DELBA action frame type */
+
+/* ADDBA action parameters */
+#define DOT11_ADDBA_PARAM_AMSDU_SUP	0x0001	/* AMSDU supported under BA */
+#define DOT11_ADDBA_PARAM_POLICY_MASK	0x0002	/* policy mask(ack vs delayed) */
+#define DOT11_ADDBA_PARAM_POLICY_SHIFT	1	/* policy shift */
+#define DOT11_ADDBA_PARAM_TID_MASK	0x003c	/* tid mask */
+#define DOT11_ADDBA_PARAM_TID_SHIFT	2	/* tid shift */
+#define DOT11_ADDBA_PARAM_BSIZE_MASK	0xffc0	/* buffer size mask */
+#define DOT11_ADDBA_PARAM_BSIZE_SHIFT	6	/* buffer size shift */
+
+#define DOT11_ADDBA_POLICY_DELAYED	0	/* delayed BA policy */
+#define DOT11_ADDBA_POLICY_IMMEDIATE	1	/* immediate BA policy */
+
+/* Fast Transition action types */
+#define DOT11_FT_ACTION_FT_RESERVED		0
+#define DOT11_FT_ACTION_FT_REQ			1	/* FBT request - for over-the-DS FBT */
+#define DOT11_FT_ACTION_FT_RES			2	/* FBT response - for over-the-DS FBT */
+#define DOT11_FT_ACTION_FT_CON			3	/* FBT confirm - for OTDS with RRP */
+#define DOT11_FT_ACTION_FT_ACK			4	/* FBT ack */
+
+/* DLS action types */
+#define DOT11_DLS_ACTION_REQ			0	/* DLS Request */
+#define DOT11_DLS_ACTION_RESP			1	/* DLS Response */
+#define DOT11_DLS_ACTION_TD			2	/* DLS Teardown */
+
+/* Wireless Network Management (WNM) action types */
+#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_BSSTRANS_QUERY		6
+#define DOT11_WNM_ACTION_BSSTRANS_REQ		7
+#define DOT11_WNM_ACTION_BSSTRANS_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_REQ		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_RESP		27
+#define DOT11_WNM_ACTION_TFS_NOTIFY_RESP	28
+
+/* Unprotected Wireless Network Management (WNM) action types */
+#define DOT11_UWNM_ACTION_TIM			0
+#define DOT11_UWNM_ACTION_TIMING_MEASUREMENT	1
+
+#define DOT11_MNG_COUNTRY_ID_LEN 3
+
+/* VHT category action types - 802.11ac D3.0 - 8.5.23.1 */
+#define DOT11_VHT_ACTION_CBF				0	/* Compressed Beamforming */
+#define DOT11_VHT_ACTION_GID_MGMT			1	/* Group ID Management */
+#define DOT11_VHT_ACTION_OPER_MODE_NOTIF	2	/* Operating mode notif'n */
+
+/** DLS Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_dls_req {
+	uint8 category;			/* category of action frame (2) */
+	uint8 action;				/* DLS action: req (0) */
+	struct ether_addr	da;		/* destination address */
+	struct ether_addr	sa;		/* source address */
+	uint16 cap;				/* capability */
+	uint16 timeout;			/* timeout value */
+	uint8 data[1];				/* IE:support rate, extend support rate, HT cap */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dls_req dot11_dls_req_t;
+#define DOT11_DLS_REQ_LEN 18	/* Fixed length */
+
+/** DLS response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_dls_resp {
+	uint8 category;			/* category of action frame (2) */
+	uint8 action;				/* DLS action: req (0) */
+	uint16 status;				/* status code field */
+	struct ether_addr	da;		/* destination address */
+	struct ether_addr	sa;		/* source address */
+	uint8 data[1];				/* optional: capability, rate ... */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dls_resp dot11_dls_resp_t;
+#define DOT11_DLS_RESP_LEN 16	/* Fixed length */
+
+
+/* ************* 802.11v related definitions. ************* */
+
+/** BSS Management Transition Query frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_query {
+	uint8 category;			/* category of action frame (10) */
+	uint8 action;			/* WNM action: trans_query (6) */
+	uint8 token;			/* dialog token */
+	uint8 reason;			/* transition query reason */
+	uint8 data[1];			/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bsstrans_query dot11_bsstrans_query_t;
+#define DOT11_BSSTRANS_QUERY_LEN 4	/* Fixed length */
+
+/* BTM transition reason */
+#define DOT11_BSSTRANS_REASON_UNSPECIFIED		0
+#define DOT11_BSSTRANS_REASON_EXC_FRAME_LOSS		1
+#define DOT11_BSSTRANS_REASON_EXC_TRAFFIC_DELAY		2
+#define DOT11_BSSTRANS_REASON_INSUFF_QOS_CAPACITY	3
+#define DOT11_BSSTRANS_REASON_FIRST_ASSOC		4
+#define DOT11_BSSTRANS_REASON_LOAD_BALANCING		5
+#define DOT11_BSSTRANS_REASON_BETTER_AP_FOUND		6
+#define DOT11_BSSTRANS_REASON_DEAUTH_RX			7
+#define DOT11_BSSTRANS_REASON_8021X_EAP_AUTH_FAIL	8
+#define DOT11_BSSTRANS_REASON_4WAY_HANDSHK_FAIL		9
+#define DOT11_BSSTRANS_REASON_MANY_REPLAYCNT_FAIL	10
+#define DOT11_BSSTRANS_REASON_MANY_DATAMIC_FAIL		11
+#define DOT11_BSSTRANS_REASON_EXCEED_MAX_RETRANS	12
+#define DOT11_BSSTRANS_REASON_MANY_BCAST_DISASSOC_RX	13
+#define DOT11_BSSTRANS_REASON_MANY_BCAST_DEAUTH_RX	14
+#define DOT11_BSSTRANS_REASON_PREV_TRANSITION_FAIL	15
+#define DOT11_BSSTRANS_REASON_LOW_RSSI			16
+#define DOT11_BSSTRANS_REASON_ROAM_FROM_NON_80211	17
+#define DOT11_BSSTRANS_REASON_RX_BTM_REQ		18
+#define DOT11_BSSTRANS_REASON_PREF_LIST_INCLUDED	19
+#define DOT11_BSSTRANS_REASON_LEAVING_ESS		20
+
+/** BSS Management Transition Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_req {
+	uint8 category;			/* category of action frame (10) */
+	uint8 action;			/* WNM action: trans_req (7) */
+	uint8 token;			/* dialog token */
+	uint8 reqmode;			/* transition request mode */
+	uint16 disassoc_tmr;		/* disassociation timer */
+	uint8 validity_intrvl;		/* validity interval */
+	uint8 data[1];			/* optional: BSS term duration, ... */
+						/* ...session info URL, candidate list */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bsstrans_req dot11_bsstrans_req_t;
+#define DOT11_BSSTRANS_REQ_LEN 7	/* Fixed length */
+
+/* BSS Mgmt Transition Request Mode Field - 802.11v */
+#define DOT11_BSSTRANS_REQMODE_PREF_LIST_INCL		0x01
+#define DOT11_BSSTRANS_REQMODE_ABRIDGED			0x02
+#define DOT11_BSSTRANS_REQMODE_DISASSOC_IMMINENT	0x04
+#define DOT11_BSSTRANS_REQMODE_BSS_TERM_INCL		0x08
+#define DOT11_BSSTRANS_REQMODE_ESS_DISASSOC_IMNT	0x10
+
+/** BSS Management transition response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_bsstrans_resp {
+	uint8 category;			/* category of action frame (10) */
+	uint8 action;			/* WNM action: trans_resp (8) */
+	uint8 token;			/* dialog token */
+	uint8 status;			/* transition status */
+	uint8 term_delay;		/* validity interval */
+	uint8 data[1];			/* optional: BSSID target, candidate list */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_bsstrans_resp dot11_bsstrans_resp_t;
+#define DOT11_BSSTRANS_RESP_LEN 5	/* Fixed length */
+
+/* BSS Mgmt Transition Response Status Field */
+#define DOT11_BSSTRANS_RESP_STATUS_ACCEPT			0
+#define DOT11_BSSTRANS_RESP_STATUS_REJECT			1
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_INSUFF_BCN		2
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_INSUFF_CAP		3
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_TERM_UNDESIRED		4
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_TERM_DELAY_REQ		5
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_BSS_LIST_PROVIDED	6
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_NO_SUITABLE_BSS		7
+#define DOT11_BSSTRANS_RESP_STATUS_REJ_LEAVING_ESS		8
+
+
+/** BSS Max Idle Period element */
+BWL_PRE_PACKED_STRUCT struct dot11_bss_max_idle_period_ie {
+	uint8 id;				/* 90, DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID */
+	uint8 len;
+	uint16 max_idle_period;			/* in unit of 1000 TUs */
+	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	/* bss max idle period IE size */
+#define DOT11_BSS_MAX_IDLE_PERIOD_OPT_PROTECTED	1	/* BSS max idle option */
+
+/** TIM Broadcast request element */
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_req_ie {
+	uint8 id;				/* 94, DOT11_MNG_TIMBC_REQ_ID */
+	uint8 len;
+	uint8 interval;				/* in unit of beacon interval */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_req_ie dot11_timbc_req_ie_t;
+#define DOT11_TIMBC_REQ_IE_LEN		1	/* Fixed length */
+
+/** TIM Broadcast request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_req {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: DOT11_WNM_ACTION_TIMBC_REQ(18) */
+	uint8 token;				/* dialog token */
+	uint8 data[1];				/* TIM broadcast request element */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_req dot11_timbc_req_t;
+#define DOT11_TIMBC_REQ_LEN		3	/* Fixed length */
+
+/** TIM Broadcast response element */
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_resp_ie {
+	uint8 id;				/* 95, DOT11_MNG_TIM_BROADCAST_RESP_ID */
+	uint8 len;
+	uint8 status;				/* status of add request */
+	uint8 interval;				/* in unit of beacon interval */
+	int32 offset;				/* in unit of ms */
+	uint16 high_rate;			/* in unit of 0.5 Mb/s */
+	uint16 low_rate;			/* in unit of 0.5 Mb/s */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_resp_ie dot11_timbc_resp_ie_t;
+#define DOT11_TIMBC_DENY_RESP_IE_LEN	1	/* Deny. Fixed length */
+#define DOT11_TIMBC_ACCEPT_RESP_IE_LEN	10	/* Accept. Fixed length */
+
+#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
+#define DOT11_TIMBC_STATUS_RESERVED		4
+
+/** TIM Broadcast request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_timbc_resp {
+	uint8 category;			/* category of action frame (10) */
+	uint8 action;			/* action: DOT11_WNM_ACTION_TIMBC_RESP(19) */
+	uint8 token;			/* dialog token */
+	uint8 data[1];			/* TIM broadcast response element */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timbc_resp dot11_timbc_resp_t;
+#define DOT11_TIMBC_RESP_LEN	3	/* Fixed length */
+
+/** TIM element */
+BWL_PRE_PACKED_STRUCT struct dot11_tim_ie {
+	uint8 id;			/* 5, DOT11_MNG_TIM_ID	 */
+	uint8 len;			/* 4 - 255 */
+	uint8 dtim_count;		/* DTIM decrementing counter */
+	uint8 dtim_period;		/* DTIM period */
+	uint8 bitmap_control;		/* AID 0 + bitmap offset */
+	uint8 pvb[1];			/* Partial Virtual Bitmap, variable length */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tim_ie dot11_tim_ie_t;
+#define DOT11_TIM_IE_FIXED_LEN	3	/* Fixed length, without id and len */
+#define DOT11_TIM_IE_FIXED_TOTAL_LEN	5	/* Fixed length, with id and len */
+
+/** TIM Broadcast frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_timbc {
+	uint8 category;			/* category of action frame (11) */
+	uint8 action;			/* action: TIM (0) */
+	uint8 check_beacon;		/* need to check-beacon */
+	uint8 tsf[8];			/* Time Synchronization Function */
+	dot11_tim_ie_t tim_ie;		/* TIM element */
+} 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)	/* Fixed length */
+#define DOT11_TIMBC_LEN			11	/* Fixed length */
+
+/** TCLAS frame classifier type */
+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	/* Fixed length */
+
+#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
+
+/** TCLAS frame classifier type 0 parameters for Ethernet */
+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
+
+/** TCLAS frame classifier type 1 parameters for IPV4 */
+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
+
+/** TCLAS frame classifier type 2 parameters for 802.1Q */
+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
+
+/** TCLAS frame classifier type 3 parameters for filter offset */
+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
+
+/** TCLAS frame classifier type 4 parameters for IPV4 is the same as TCLAS type 1 */
+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
+
+/** TCLAS frame classifier type 4 parameters for IPV6 */
+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
+
+/** TCLAS frame classifier type 5 parameters for 802.1D */
+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
+
+/** TCLAS frame classifier type parameters */
+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	/* Classifier Type 2 has the min size */
+#define DOT11_TCLAS_FC_MAX_LEN		254
+
+/** TCLAS element */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_ie {
+	uint8 id;				/* 14, DOT11_MNG_TCLAS_ID */
+	uint8 len;
+	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	/* Fixed length, include id and len */
+
+/** TCLAS processing element */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_proc_ie {
+	uint8 id;				/* 44, DOT11_MNG_TCLAS_PROC_ID */
+	uint8 len;
+	uint8 process;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_proc_ie dot11_tclas_proc_ie_t;
+#define DOT11_TCLAS_PROC_IE_LEN		3	/* Fixed length, include id and len */
+
+#define DOT11_TCLAS_PROC_MATCHALL	0	/* All high level element need to match */
+#define DOT11_TCLAS_PROC_MATCHONE	1	/* One high level element need to match */
+#define DOT11_TCLAS_PROC_NONMATCH	2	/* Non match to any high level element */
+
+
+/* TSPEC element defined in 802.11 std section 8.4.2.32 - Not supported */
+#define DOT11_TSPEC_IE_LEN		57	/* Fixed length */
+
+/** TFS request element */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_req_ie {
+	uint8 id;				/* 91, DOT11_MNG_TFS_REQUEST_ID */
+	uint8 len;
+	uint8 tfs_id;
+	uint8 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		2	/* Fixed length, without id and len */
+
+/** TFS request action codes (bitfield) */
+#define DOT11_TFS_ACTCODE_DELETE	1
+#define DOT11_TFS_ACTCODE_NOTIFY	2
+
+/** TFS request subelement IDs */
+#define DOT11_TFS_REQ_TFS_SE_ID		1
+#define DOT11_TFS_REQ_VENDOR_SE_ID	221
+
+/** TFS subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 data[1];				/* TCLAS element(s) + optional TCLAS proc */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_se dot11_tfs_se_t;
+
+
+/** TFS response element */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp_ie {
+	uint8 id;				/* 92, DOT11_MNG_TFS_RESPONSE_ID */
+	uint8 len;
+	uint8 tfs_id;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_resp_ie dot11_tfs_resp_ie_t;
+#define DOT11_TFS_RESP_IE_LEN		1	/* Fixed length, without id and len */
+
+/** TFS response subelement IDs (same subelments, but different IDs than in TFS request */
+#define DOT11_TFS_RESP_TFS_STATUS_SE_ID		1
+#define DOT11_TFS_RESP_TFS_SE_ID		2
+#define DOT11_TFS_RESP_VENDOR_SE_ID		221
+
+/** TFS status subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_status_se {
+	uint8 sub_id;				/* 92, DOT11_MNG_TFS_RESPONSE_ID */
+	uint8 len;
+	uint8 resp_st;
+	uint8 data[1];				/* Potential dot11_tfs_se_t included */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_status_se dot11_tfs_status_se_t;
+#define DOT11_TFS_STATUS_SE_LEN			1	/* Fixed length, without id and len */
+
+/* Following Definition should be merged to FMS_TFS macro below */
+/* TFS Response status code. Identical to FMS Element status, without N/A  */
+#define DOT11_TFS_STATUS_ACCEPT			0
+#define DOT11_TFS_STATUS_DENY_FORMAT		1
+#define DOT11_TFS_STATUS_DENY_RESOURCE		2
+#define DOT11_TFS_STATUS_DENY_POLICY		4
+#define DOT11_TFS_STATUS_DENY_UNSPECIFIED	5
+#define DOT11_TFS_STATUS_ALTPREF_POLICY		7
+#define DOT11_TFS_STATUS_ALTPREF_TCLAS_UNSUPP	14
+
+/* FMS Element Status and TFS Response Status Definition */
+#define DOT11_FMS_TFS_STATUS_ACCEPT		0
+#define DOT11_FMS_TFS_STATUS_DENY_FORMAT	1
+#define DOT11_FMS_TFS_STATUS_DENY_RESOURCE	2
+#define DOT11_FMS_TFS_STATUS_DENY_MULTIPLE_DI	3
+#define DOT11_FMS_TFS_STATUS_DENY_POLICY	4
+#define DOT11_FMS_TFS_STATUS_DENY_UNSPECIFIED	5
+#define DOT11_FMS_TFS_STATUS_ALT_DIFF_DI	6
+#define DOT11_FMS_TFS_STATUS_ALT_POLICY		7
+#define DOT11_FMS_TFS_STATUS_ALT_CHANGE_DI	8
+#define DOT11_FMS_TFS_STATUS_ALT_MCRATE		9
+#define DOT11_FMS_TFS_STATUS_TERM_POLICY	10
+#define DOT11_FMS_TFS_STATUS_TERM_RESOURCE	11
+#define DOT11_FMS_TFS_STATUS_TERM_HIGHER_PRIO	12
+#define DOT11_FMS_TFS_STATUS_ALT_CHANGE_MDI	13
+#define DOT11_FMS_TFS_STATUS_ALT_TCLAS_UNSUPP	14
+
+/** TFS Management Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_req {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: TFS request (13) */
+	uint8 token;				/* dialog token */
+	uint8 data[1];				/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_req dot11_tfs_req_t;
+#define DOT11_TFS_REQ_LEN		3	/* Fixed length */
+
+/** TFS Management Response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: TFS request (14) */
+	uint8 token;				/* dialog token */
+	uint8 data[1];				/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_resp dot11_tfs_resp_t;
+#define DOT11_TFS_RESP_LEN		3	/* Fixed length */
+
+/** TFS Management Notify frame request header */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_notify_req {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: TFS notify request (15) */
+	uint8 tfs_id_cnt;			/* TFS IDs count */
+	uint8 tfs_id[1];			/* Array of TFS IDs */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_notify_req dot11_tfs_notify_req_t;
+#define DOT11_TFS_NOTIFY_REQ_LEN	3	/* Fixed length */
+
+/** TFS Management Notify frame response header */
+BWL_PRE_PACKED_STRUCT struct dot11_tfs_notify_resp {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: TFS notify response (28) */
+	uint8 tfs_id_cnt;			/* TFS IDs count */
+	uint8 tfs_id[1];			/* Array of TFS IDs */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tfs_notify_resp dot11_tfs_notify_resp_t;
+#define DOT11_TFS_NOTIFY_RESP_LEN	3	/* Fixed length */
+
+
+/** WNM-Sleep Management Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_req {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: wnm-sleep request (16) */
+	uint8 token;				/* dialog token */
+	uint8 data[1];				/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_req dot11_wnm_sleep_req_t;
+#define DOT11_WNM_SLEEP_REQ_LEN		3	/* Fixed length */
+
+/** WNM-Sleep Management Response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_resp {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: wnm-sleep request (17) */
+	uint8 token;				/* dialog token */
+	uint16 key_len;				/* key data length */
+	uint8 data[1];				/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_sleep_resp dot11_wnm_sleep_resp_t;
+#define DOT11_WNM_SLEEP_RESP_LEN	5	/* Fixed length */
+
+#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 len;
+	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	/* without sub_id, len, and key */
+#define DOT11_WNM_SLEEP_SUBELEM_GTK_MAX_LEN	43	/* without sub_id and len */
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_subelem_igtk {
+	uint8 sub_id;
+	uint8 len;
+	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	/* Fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_ie {
+	uint8 id;				/* 93, DOT11_MNG_WNM_SLEEP_MODE_ID */
+	uint8 len;
+	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	/* Fixed length */
+
+#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
+
+/** DMS Management Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: dms request (23) */
+	uint8 token;				/* dialog token */
+	uint8 data[1];				/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_req dot11_dms_req_t;
+#define DOT11_DMS_REQ_LEN		3	/* Fixed length */
+
+/** DMS Management Response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: dms request (24) */
+	uint8 token;				/* dialog token */
+	uint8 data[1];				/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_dms_resp dot11_dms_resp_t;
+#define DOT11_DMS_RESP_LEN		3	/* Fixed length */
+
+/** DMS request element */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req_ie {
+	uint8 id;				/* 99, DOT11_MNG_DMS_REQUEST_ID */
+	uint8 len;
+	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	/* Fixed length */
+
+/** DMS response element */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp_ie {
+	uint8 id;				/* 100, DOT11_MNG_DMS_RESPONSE_ID */
+	uint8 len;
+	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	/* Fixed length */
+
+/** DMS request descriptor */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_req_desc {
+	uint8 dms_id;
+	uint8 len;
+	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	/* Fixed length */
+
+#define DOT11_DMS_REQ_TYPE_ADD		0
+#define DOT11_DMS_REQ_TYPE_REMOVE	1
+#define DOT11_DMS_REQ_TYPE_CHANGE	2
+
+/** DMS response status */
+BWL_PRE_PACKED_STRUCT struct dot11_dms_resp_st {
+	uint8 dms_id;
+	uint8 len;
+	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	/* Fixed length */
+
+#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
+
+/** WNM-Notification Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_wnm_notif_req {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: Notification request (26) */
+	uint8 token;				/* dialog token */
+	uint8 type;				   /* type */
+	uint8 data[1];				/* Sub-elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_wnm_notif_req dot11_wnm_notif_req_t;
+#define DOT11_WNM_NOTIF_REQ_LEN		4	/* Fixed length */
+
+/** FMS Management Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_req {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: fms request (9) */
+	uint8 token;				/* dialog token */
+	uint8 data[1];				/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_req dot11_fms_req_t;
+#define DOT11_FMS_REQ_LEN		3	/* Fixed length */
+
+/** FMS Management Response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_resp {
+	uint8 category;				/* category of action frame (10) */
+	uint8 action;				/* WNM action: fms request (10) */
+	uint8 token;				/* dialog token */
+	uint8 data[1];				/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_resp dot11_fms_resp_t;
+#define DOT11_FMS_RESP_LEN		3	/* Fixed length */
+
+/** FMS Descriptor element */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_desc {
+	uint8 id;
+	uint8 len;
+	uint8 num_fms_cnt;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_desc dot11_fms_desc_t;
+#define DOT11_FMS_DESC_LEN		1	/* Fixed length */
+
+#define DOT11_FMS_CNTR_MAX		0x8
+#define DOT11_FMS_CNTR_ID_MASK		0x7
+#define DOT11_FMS_CNTR_ID_SHIFT		0x0
+#define DOT11_FMS_CNTR_COUNT_MASK	0xf1
+#define DOT11_FMS_CNTR_SHIFT		0x3
+
+/** FMS request element */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_req_ie {
+	uint8 id;
+	uint8 len;
+	uint8 fms_token;			/* token used to identify fms stream set */
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_req_ie dot11_fms_req_ie_t;
+#define DOT11_FMS_REQ_IE_FIX_LEN		1	/* Fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_rate_id_field {
+	uint8 mask;
+	uint8 mcs_idx;
+	uint16 rate;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rate_id_field dot11_rate_id_field_t;
+#define DOT11_RATE_ID_FIELD_MCS_SEL_MASK	0x7
+#define DOT11_RATE_ID_FIELD_MCS_SEL_OFFSET	0
+#define DOT11_RATE_ID_FIELD_RATETYPE_MASK	0x18
+#define DOT11_RATE_ID_FIELD_RATETYPE_OFFSET	3
+#define DOT11_RATE_ID_FIELD_LEN		sizeof(dot11_rate_id_field_t)
+
+/** FMS request subelements */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 interval;
+	uint8 max_interval;
+	dot11_rate_id_field_t rate;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_se dot11_fms_se_t;
+#define DOT11_FMS_REQ_SE_LEN		6	/* Fixed length */
+
+#define DOT11_FMS_REQ_SE_ID_FMS		1	/* FMS subelement */
+#define DOT11_FMS_REQ_SE_ID_VS		221	/* Vendor Specific subelement */
+
+/** FMS response element */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_resp_ie {
+	uint8 id;
+	uint8 len;
+	uint8 fms_token;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_resp_ie dot11_fms_resp_ie_t;
+#define DOT11_FMS_RESP_IE_FIX_LEN		1	/* Fixed length */
+
+/* FMS status subelements */
+#define DOT11_FMS_STATUS_SE_ID_FMS	1	/* FMS Status */
+#define DOT11_FMS_STATUS_SE_ID_TCLAS	2	/* TCLAS Status */
+#define DOT11_FMS_STATUS_SE_ID_VS	221	/* Vendor Specific subelement */
+
+/** FMS status subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_fms_status_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 status;
+	uint8 interval;
+	uint8 max_interval;
+	uint8 fmsid;
+	uint8 counter;
+	dot11_rate_id_field_t rate;
+	uint8 mcast_addr[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_fms_status_se dot11_fms_status_se_t;
+#define DOT11_FMS_STATUS_SE_LEN		15	/* Fixed length */
+
+/** TCLAS status subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_tclas_status_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 fmsid;
+	uint8 data[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_tclas_status_se dot11_tclas_status_se_t;
+#define DOT11_TCLAS_STATUS_SE_LEN		1	/* Fixed length */
+
+BWL_PRE_PACKED_STRUCT struct dot11_addba_req {
+	uint8 category;				/* category of action frame (3) */
+	uint8 action;				/* action: addba req */
+	uint8 token;				/* identifier */
+	uint16 addba_param_set;		/* parameter set */
+	uint16 timeout;				/* timeout in seconds */
+	uint16 start_seqnum;		/* starting sequence number */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_addba_req dot11_addba_req_t;
+#define DOT11_ADDBA_REQ_LEN		9	/* length of addba req frame */
+
+BWL_PRE_PACKED_STRUCT struct dot11_addba_resp {
+	uint8 category;				/* category of action frame (3) */
+	uint8 action;				/* action: addba resp */
+	uint8 token;				/* identifier */
+	uint16 status;				/* status of add request */
+	uint16 addba_param_set;			/* negotiated parameter set */
+	uint16 timeout;				/* negotiated timeout in seconds */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_addba_resp dot11_addba_resp_t;
+#define DOT11_ADDBA_RESP_LEN		9	/* length of addba resp frame */
+
+/* DELBA action parameters */
+#define DOT11_DELBA_PARAM_INIT_MASK	0x0800	/* initiator mask */
+#define DOT11_DELBA_PARAM_INIT_SHIFT	11	/* initiator shift */
+#define DOT11_DELBA_PARAM_TID_MASK	0xf000	/* tid mask */
+#define DOT11_DELBA_PARAM_TID_SHIFT	12	/* tid shift */
+
+BWL_PRE_PACKED_STRUCT struct dot11_delba {
+	uint8 category;				/* category of action frame (3) */
+	uint8 action;				/* action: addba req */
+	uint16 delba_param_set;			/* paarmeter set */
+	uint16 reason;				/* reason for dellba */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_delba dot11_delba_t;
+#define DOT11_DELBA_LEN			6	/* length of delba frame */
+
+/* SA Query action field value */
+#define SA_QUERY_REQUEST		0
+#define SA_QUERY_RESPONSE		1
+
+/* ************* 802.11r related definitions. ************* */
+
+/** Over-the-DS Fast Transition Request frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_ft_req {
+	uint8 category;			/* category of action frame (6) */
+	uint8 action;			/* action: ft req */
+	uint8 sta_addr[ETHER_ADDR_LEN];
+	uint8 tgt_ap_addr[ETHER_ADDR_LEN];
+	uint8 data[1];			/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_req dot11_ft_req_t;
+#define DOT11_FT_REQ_FIXED_LEN 14
+
+/** Over-the-DS Fast Transition Response frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_ft_res {
+	uint8 category;			/* category of action frame (6) */
+	uint8 action;			/* action: ft resp */
+	uint8 sta_addr[ETHER_ADDR_LEN];
+	uint8 tgt_ap_addr[ETHER_ADDR_LEN];
+	uint16 status;			/* status code */
+	uint8 data[1];			/* Elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ft_res dot11_ft_res_t;
+#define DOT11_FT_RES_FIXED_LEN 16
+
+/** RDE RIC Data Element. */
+BWL_PRE_PACKED_STRUCT struct dot11_rde_ie {
+	uint8 id;			/* 11r, DOT11_MNG_RDE_ID */
+	uint8 length;
+	uint8 rde_id;			/* RDE identifier. */
+	uint8 rd_count;			/* Resource Descriptor Count. */
+	uint16 status;			/* Status Code. */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rde_ie dot11_rde_ie_t;
+
+/* 11r - Size of the RDE (RIC Data Element) IE, including TLV header. */
+#define DOT11_MNG_RDE_IE_LEN sizeof(dot11_rde_ie_t)
+
+
+/* ************* 802.11k related definitions. ************* */
+
+/* Radio measurements enabled capability ie */
+#define DOT11_RRM_CAP_LEN		5	/* length of rrm cap bitmap */
+#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;
+
+/* Bitmap definitions for cap ie */
+#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_FM		8
+#define DOT11_RRM_CAP_CLM		9
+#define DOT11_RRM_CAP_NHM		10
+#define DOT11_RRM_CAP_SM		11
+#define DOT11_RRM_CAP_LCIM		12
+#define DOT11_RRM_CAP_LCIA		13
+#define DOT11_RRM_CAP_TSCM		14
+#define DOT11_RRM_CAP_TTSCM		15
+#define DOT11_RRM_CAP_AP_CHANREP	16
+#define DOT11_RRM_CAP_RMMIB		17
+/* bit18-bit23, not used for RRM_IOVAR */
+#define DOT11_RRM_CAP_MPC0		24
+#define DOT11_RRM_CAP_MPC1		25
+#define DOT11_RRM_CAP_MPC2		26
+#define DOT11_RRM_CAP_MPTI		27
+#define DOT11_RRM_CAP_NBRTSFO		28
+#define DOT11_RRM_CAP_RCPI		29
+#define DOT11_RRM_CAP_RSNI		30
+#define DOT11_RRM_CAP_BSSAAD		31
+#define DOT11_RRM_CAP_BSSAAC		32
+#define DOT11_RRM_CAP_AI		33
+#define DOT11_RRM_CAP_FTM_RANGE		34
+#define DOT11_RRM_CAP_CIVIC_LOC		35
+#define DOT11_RRM_CAP_IDENT_LOC		36
+#define DOT11_RRM_CAP_LAST		36
+
+#define DOT11_RRM_CAP_MPA_MASK		0x7
+/* Operating Class (formerly "Regulatory Class") definitions */
+#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;
+
+/* Radio Measurements action ids */
+#define DOT11_RM_ACTION_RM_REQ		0	/* Radio measurement request */
+#define DOT11_RM_ACTION_RM_REP		1	/* Radio measurement report */
+#define DOT11_RM_ACTION_LM_REQ		2	/* Link measurement request */
+#define DOT11_RM_ACTION_LM_REP		3	/* Link measurement report */
+#define DOT11_RM_ACTION_NR_REQ		4	/* Neighbor report request */
+#define DOT11_RM_ACTION_NR_REP		5	/* Neighbor report response */
+#define DOT11_PUB_ACTION_MP		7	/* Measurement Pilot public action id */
+
+/** Generic radio measurement action frame header */
+BWL_PRE_PACKED_STRUCT struct dot11_rm_action {
+	uint8 category;				/* category of action frame (5) */
+	uint8 action;				/* radio measurement action */
+	uint8 token;				/* dialog 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;				/* category of action frame (5) */
+	uint8 action;				/* radio measurement action */
+	uint8 token;				/* dialog token */
+	uint16 reps;				/* no. of repetitions */
+	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
+
+/* Definitions for "mode" bits in rm req */
+#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	/* Duration Mandatory */
+
+/* Definitions for "mode" bits in rm rep */
+#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
+
+/* Beacon request measurement mode */
+#define DOT11_RMREQ_BCN_PASSIVE	0
+#define DOT11_RMREQ_BCN_ACTIVE	1
+#define DOT11_RMREQ_BCN_TABLE	2
+
+/* Sub-element IDs for Beacon Request */
+#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
+
+/* Reporting Detail element definition */
+#define DOT11_RMREQ_BCN_REPDET_FIXED	0	/* Fixed length fields only */
+#define DOT11_RMREQ_BCN_REPDET_REQUEST	1	/* + requested information elems */
+#define DOT11_RMREQ_BCN_REPDET_ALL	2	/* All fields */
+
+/* Reporting Information (reporting condition) element definition */
+#define DOT11_RMREQ_BCN_REPINFO_LEN	2	/* Beacon Reporting Information length */
+#define DOT11_RMREQ_BCN_REPCOND_DEFAULT	0	/* Report to be issued after each measurement */
+
+/* Sub-element IDs for Beacon Report */
+#define DOT11_RMREP_BCN_FRM_BODY	1
+#define DOT11_RMREP_BCN_FRM_BODY_LEN_MAX	224 /* 802.11k-2008 7.3.2.22.6 */
+
+/* Sub-element IDs for Frame Report */
+#define DOT11_RMREP_FRAME_COUNT_REPORT 1
+
+/* Channel load request */
+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
+
+/** Channel load report */
+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
+
+/** Noise histogram request */
+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
+
+/** Noise histogram report */
+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
+
+/** Frame request */
+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
+
+/** Frame report */
+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
+
+/** Frame report entry */
+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
+
+/** STA statistics request */
+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
+
+/** STA statistics report */
+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;
+
+/* Statistics Group Report: Group IDs */
+enum {
+	DOT11_RRM_STATS_GRP_ID_0 = 0,
+	DOT11_RRM_STATS_GRP_ID_1,
+	DOT11_RRM_STATS_GRP_ID_2,
+	DOT11_RRM_STATS_GRP_ID_3,
+	DOT11_RRM_STATS_GRP_ID_4,
+	DOT11_RRM_STATS_GRP_ID_5,
+	DOT11_RRM_STATS_GRP_ID_6,
+	DOT11_RRM_STATS_GRP_ID_7,
+	DOT11_RRM_STATS_GRP_ID_8,
+	DOT11_RRM_STATS_GRP_ID_9,
+	DOT11_RRM_STATS_GRP_ID_10,
+	DOT11_RRM_STATS_GRP_ID_11,
+	DOT11_RRM_STATS_GRP_ID_12,
+	DOT11_RRM_STATS_GRP_ID_13,
+	DOT11_RRM_STATS_GRP_ID_14,
+	DOT11_RRM_STATS_GRP_ID_15,
+	DOT11_RRM_STATS_GRP_ID_16
+};
+
+/* Statistics Group Report: Group Data length  */
+#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_0	28
+typedef struct rrm_stat_group_0 {
+	uint32	txfrag;
+	uint32	txmulti;
+	uint32	txfail;
+	uint32	rxframe;
+	uint32	rxmulti;
+	uint32	rxbadfcs;
+	uint32	txframe;
+} rrm_stat_group_0_t;
+
+#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_1	24
+typedef struct rrm_stat_group_1 {
+	uint32	txretry;
+	uint32	txretries;
+	uint32	rxdup;
+	uint32	txrts;
+	uint32	rtsfail;
+	uint32	ackfail;
+} rrm_stat_group_1_t;
+
+/* group 2-9 use same qos data structure (tid 0-7), total 52 bytes */
+#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_2_9	52
+typedef struct rrm_stat_group_qos {
+	uint32	txfrag;
+	uint32	txfail;
+	uint32	txretry;
+	uint32	txretries;
+	uint32	rxdup;
+	uint32	txrts;
+	uint32	rtsfail;
+	uint32	ackfail;
+	uint32	rxfrag;
+	uint32	txframe;
+	uint32	txdrop;
+	uint32	rxmpdu;
+	uint32	rxretries;
+} rrm_stat_group_qos_t;
+
+/* dot11BSSAverageAccessDelay Group (only available at an AP): 8 byte */
+#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_10	8
+typedef BWL_PRE_PACKED_STRUCT struct rrm_stat_group_10 {
+	uint8	apavgdelay;
+	uint8	avgdelaybe;
+	uint8	avgdelaybg;
+	uint8	avgdelayvi;
+	uint8	avgdelayvo;
+	uint16	stacount;
+	uint8	chanutil;
+} BWL_POST_PACKED_STRUCT rrm_stat_group_10_t;
+
+/* AMSDU, 40 bytes */
+#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_11	40
+typedef struct rrm_stat_group_11 {
+	uint32	txamsdu;
+	uint32	amsdufail;
+	uint32	amsduretry;
+	uint32	amsduretries;
+	uint32	txamsdubyte_h;
+	uint32	txamsdubyte_l;
+	uint32	amsduackfail;
+	uint32	rxamsdu;
+	uint32	rxamsdubyte_h;
+	uint32	rxamsdubyte_l;
+} rrm_stat_group_11_t;
+
+/* AMPDU, 36 bytes */
+#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_12	36
+typedef struct rrm_stat_group_12 {
+	uint32	txampdu;
+	uint32	txmpdu;
+	uint32	txampdubyte_h;
+	uint32	txampdubyte_l;
+	uint32	rxampdu;
+	uint32	rxmpdu;
+	uint32	rxampdubyte_h;
+	uint32	rxampdubyte_l;
+	uint32	ampducrcfail;
+} rrm_stat_group_12_t;
+
+/* BACK etc, 36 bytes */
+#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_13	36
+typedef struct rrm_stat_group_13 {
+	uint32	rximpbarfail;
+	uint32	rxexpbarfail;
+	uint32	chanwidthsw;
+	uint32	txframe20mhz;
+	uint32	txframe40mhz;
+	uint32	rxframe20mhz;
+	uint32	rxframe40mhz;
+	uint32	psmpgrantdur;
+	uint32	psmpuseddur;
+} rrm_stat_group_13_t;
+
+/* RD Dual CTS etc, 36 bytes */
+#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_14	36
+typedef struct rrm_stat_group_14 {
+	uint32	grantrdgused;
+	uint32	grantrdgunused;
+	uint32	txframeingrantrdg;
+	uint32	txbyteingrantrdg_h;
+	uint32	txbyteingrantrdg_l;
+	uint32	dualcts;
+	uint32	dualctsfail;
+	uint32	rtslsi;
+	uint32	rtslsifail;
+} rrm_stat_group_14_t;
+
+/* bf and STBC etc, 20 bytes */
+#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_15	20
+typedef struct rrm_stat_group_15 {
+	uint32	bfframe;
+	uint32	stbccts;
+	uint32	stbcctsfail;
+	uint32	nonstbccts;
+	uint32	nonstbcctsfail;
+} rrm_stat_group_15_t;
+
+/* RSNA, 28 bytes */
+#define DOT11_RRM_STATS_RPT_LEN_GRP_ID_16	28
+typedef struct rrm_stat_group_16 {
+	uint32	rsnacmacicverr;
+	uint32	rsnacmacreplay;
+	uint32	rsnarobustmgmtccmpreplay;
+	uint32	rsnatkipicverr;
+	uint32	rsnatkipicvreplay;
+	uint32	rsnaccmpdecrypterr;
+	uint32	rsnaccmpreplay;
+} rrm_stat_group_16_t;
+
+/* Transmit stream/category measurement request */
+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;
+#define DOT11_RMREQ_TXSTREAM_LEN	17
+
+/** Transmit stream/category measurement report */
+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;
+#define DOT11_RMREP_TXSTREAM_LEN	71
+
+typedef struct rrm_tscm {
+	uint32 msdu_tx;
+	uint32 msdu_exp;
+	uint32 msdu_fail;
+	uint32 msdu_retries;
+	uint32 cfpolls_lost;
+	uint32 queue_delay;
+	uint32 tx_delay_sum;
+	uint32 tx_delay_cnt;
+	uint32 bin0_range_us;
+	uint32 bin0;
+	uint32 bin1;
+	uint32 bin2;
+	uint32 bin3;
+	uint32 bin4;
+	uint32 bin5;
+} rrm_tscm_t;
+enum {
+	DOT11_FTM_LOCATION_SUBJ_LOCAL = 0, 		/* Where am I? */
+	DOT11_FTM_LOCATION_SUBJ_REMOTE = 1,		/* Where are you? */
+	DOT11_FTM_LOCATION_SUBJ_THIRDPARTY = 2   /* Where is he/she? */
+};
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_ftm_lci {
+	uint8 id;
+	uint8 len;
+	uint8 token;
+	uint8 mode;
+	uint8 type;
+	uint8 subj;
+
+	/* Following 3 fields are unused. Keep for ROM compatibility. */
+	uint8 lat_res;
+	uint8 lon_res;
+	uint8 alt_res;
+
+	/* optional sub-elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_ftm_lci dot11_rmreq_ftm_lci_t;
+#define DOT11_RMREQ_LCI_LEN	9
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_ftm_lci {
+	uint8 id;
+	uint8 len;
+	uint8 token;
+	uint8 mode;
+	uint8 type;
+	uint8 lci_sub_id;
+	uint8 lci_sub_len;
+	/* optional LCI field */
+	/* optional sub-elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_ftm_lci dot11_rmrep_ftm_lci_t;
+
+#define DOT11_FTM_LCI_SUBELEM_ID 		0
+#define DOT11_FTM_LCI_SUBELEM_LEN 		2
+#define DOT11_FTM_LCI_FIELD_LEN 		16
+#define DOT11_FTM_LCI_UNKNOWN_LEN 		2
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_ftm_civic {
+	uint8 id;
+	uint8 len;
+	uint8 token;
+	uint8 mode;
+	uint8 type;
+	uint8 subj;
+	uint8 civloc_type;
+	uint8 siu;	/* service interval units */
+	uint16 si;  /* service interval */
+	/* optional sub-elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_ftm_civic dot11_rmreq_ftm_civic_t;
+#define DOT11_RMREQ_CIVIC_LEN	10
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_ftm_civic {
+	uint8 id;
+	uint8 len;
+	uint8 token;
+	uint8 mode;
+	uint8 type;
+	uint8 civloc_type;
+	uint8 civloc_sub_id;
+	uint8 civloc_sub_len;
+	/* optional location civic field */
+	/* optional sub-elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_ftm_civic dot11_rmrep_ftm_civic_t;
+
+#define DOT11_FTM_CIVIC_LOC_TYPE_RFC4776	0
+#define DOT11_FTM_CIVIC_SUBELEM_ID 			0
+#define DOT11_FTM_CIVIC_SUBELEM_LEN 		2
+#define DOT11_FTM_CIVIC_LOC_SI_NONE			0
+#define DOT11_FTM_CIVIC_TYPE_LEN			1
+#define DOT11_FTM_CIVIC_UNKNOWN_LEN 		3
+
+/* Location Identifier measurement request */
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_locid {
+	uint8 id;
+	uint8 len;
+	uint8 token;
+	uint8 mode;
+	uint8 type;
+	uint8 subj;
+	uint8 siu;
+	uint16 si;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_locid dot11_rmreq_locid_t;
+#define DOT11_RMREQ_LOCID_LEN	9
+
+/* Location Identifier measurement report */
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_locid {
+	uint8 id;
+	uint8 len;
+	uint8 token;
+	uint8 mode;
+	uint8 type;
+	uint8 exp_tsf[8];
+	uint8 locid_sub_id;
+	uint8 locid_sub_len;
+	/* optional location identifier field */
+	/* optional sub-elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_locid dot11_rmrep_locid_t;
+#define DOT11_LOCID_UNKNOWN_LEN		10
+#define DOT11_LOCID_SUBELEM_ID		0
+
+BWL_PRE_PACKED_STRUCT struct dot11_ftm_range_subel {
+	uint8 id;
+	uint8 len;
+	uint16 max_age;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ftm_range_subel dot11_ftm_range_subel_t;
+#define DOT11_FTM_RANGE_SUBELEM_ID      4
+#define DOT11_FTM_RANGE_SUBELEM_LEN     2
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmreq_ftm_range {
+	uint8 id;
+	uint8 len;
+	uint8 token;
+	uint8 mode;
+	uint8 type;
+	uint16 max_init_delay;		/* maximum random initial delay */
+	uint8 min_ap_count;
+	uint8 data[1];
+	/* neighbor report sub-elements */
+	/* optional sub-elements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmreq_ftm_range dot11_rmreq_ftm_range_t;
+#define DOT11_RMREQ_FTM_RANGE_LEN 8
+
+#define DOT11_FTM_RANGE_LEN		3
+BWL_PRE_PACKED_STRUCT struct dot11_ftm_range_entry {
+	uint32 start_tsf;		/* 4 lsb of tsf */
+	struct ether_addr bssid;
+	uint8 range[DOT11_FTM_RANGE_LEN];
+	uint8 max_err[DOT11_FTM_RANGE_LEN];
+	uint8  rsvd;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ftm_range_entry dot11_ftm_range_entry_t;
+#define DOT11_FTM_RANGE_ENTRY_MAX_COUNT   15
+
+enum {
+	DOT11_FTM_RANGE_ERROR_AP_INCAPABLE = 2,
+	DOT11_FTM_RANGE_ERROR_AP_FAILED = 3,
+	DOT11_FTM_RANGE_ERROR_TX_FAILED = 8,
+	DOT11_FTM_RANGE_ERROR_MAX
+};
+
+BWL_PRE_PACKED_STRUCT struct dot11_ftm_range_error_entry {
+	uint32 start_tsf;		/* 4 lsb of tsf */
+	struct ether_addr bssid;
+	uint8  code;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ftm_range_error_entry dot11_ftm_range_error_entry_t;
+#define DOT11_FTM_RANGE_ERROR_ENTRY_MAX_COUNT   11
+
+BWL_PRE_PACKED_STRUCT struct dot11_rmrep_ftm_range {
+    uint8 id;
+    uint8 len;
+    uint8 token;
+    uint8 mode;
+    uint8 type;
+    uint8 entry_count;
+    uint8 data[2]; /* includes pad */
+	/*
+	dot11_ftm_range_entry_t entries[entry_count];
+	uint8 error_count;
+	dot11_ftm_error_entry_t errors[error_count];
+	 */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_rmrep_ftm_range dot11_rmrep_ftm_range_t;
+
+#define DOT11_FTM_RANGE_REP_MIN_LEN     6       /* No extra byte for error_count */
+#define DOT11_FTM_RANGE_ENTRY_CNT_MAX   15
+#define DOT11_FTM_RANGE_ERROR_CNT_MAX   11
+#define DOT11_FTM_RANGE_REP_FIXED_LEN   1       /* No extra byte for error_count */
+/** Measurement pause request */
+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;
+#define DOT11_RMREQ_PAUSE_LEN	7
+
+
+/* Neighbor Report subelements ID (11k & 11v) */
+#define DOT11_NGBR_TSF_INFO_SE_ID	1
+#define DOT11_NGBR_CCS_SE_ID		2
+#define DOT11_NGBR_BSSTRANS_PREF_SE_ID	3
+#define DOT11_NGBR_BSS_TERM_DUR_SE_ID	4
+#define DOT11_NGBR_BEARING_SE_ID	5
+#define DOT11_NGBR_WIDE_BW_CHAN_SE_ID	6
+
+/** Neighbor Report, BSS Transition Candidate Preference subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_ngbr_bsstrans_pref_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 preference;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ngbr_bsstrans_pref_se dot11_ngbr_bsstrans_pref_se_t;
+#define DOT11_NGBR_BSSTRANS_PREF_SE_LEN	1
+
+/** Neighbor Report, BSS Termination Duration subelement */
+BWL_PRE_PACKED_STRUCT struct dot11_ngbr_bss_term_dur_se {
+	uint8 sub_id;
+	uint8 len;
+	uint8 tsf[8];
+	uint16 duration;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ngbr_bss_term_dur_se dot11_ngbr_bss_term_dur_se_t;
+#define DOT11_NGBR_BSS_TERM_DUR_SE_LEN	10
+
+/* Neighbor Report BSSID Information Field */
+#define DOT11_NGBR_BI_REACHABILTY_UNKN	0x0002
+#define DOT11_NGBR_BI_REACHABILTY	0x0003
+#define DOT11_NGBR_BI_SEC		0x0004
+#define DOT11_NGBR_BI_KEY_SCOPE		0x0008
+#define DOT11_NGBR_BI_CAP		0x03f0
+#define DOT11_NGBR_BI_CAP_SPEC_MGMT	0x0010
+#define DOT11_NGBR_BI_CAP_QOS		0x0020
+#define DOT11_NGBR_BI_CAP_APSD		0x0040
+#define DOT11_NGBR_BI_CAP_RDIO_MSMT	0x0080
+#define DOT11_NGBR_BI_CAP_DEL_BA	0x0100
+#define DOT11_NGBR_BI_CAP_IMM_BA	0x0200
+#define DOT11_NGBR_BI_MOBILITY		0x0400
+#define DOT11_NGBR_BI_HT		0x0800
+#define DOT11_NGBR_BI_VHT		0x1000
+#define DOT11_NGBR_BI_FTM		0x2000
+
+/** Neighbor Report element (11k & 11v) */
+BWL_PRE_PACKED_STRUCT struct dot11_neighbor_rep_ie {
+	uint8 id;
+	uint8 len;
+	struct ether_addr bssid;
+	uint32 bssid_info;
+	uint8 reg;		/* Operating class */
+	uint8 channel;
+	uint8 phytype;
+	uint8 data[1]; 		/* Variable size subelements */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_neighbor_rep_ie dot11_neighbor_rep_ie_t;
+#define DOT11_NEIGHBOR_REP_IE_FIXED_LEN	13
+
+
+/* MLME Enumerations */
+#define DOT11_BSSTYPE_INFRASTRUCTURE		0	/* d11 infrastructure */
+#define DOT11_BSSTYPE_INDEPENDENT		1	/* d11 independent */
+#define DOT11_BSSTYPE_ANY			2	/* d11 any BSS type */
+#define DOT11_BSSTYPE_MESH			3	/* d11 Mesh */
+#define DOT11_SCANTYPE_ACTIVE			0	/* d11 scan active */
+#define DOT11_SCANTYPE_PASSIVE			1	/* d11 scan passive */
+
+/** Link Measurement */
+BWL_PRE_PACKED_STRUCT struct dot11_lmreq {
+	uint8 category;				/* category of action frame (5) */
+	uint8 action;				/* radio measurement action */
+	uint8 token;				/* dialog token */
+	uint8 txpwr;				/* Transmit Power Used */
+	uint8 maxtxpwr;				/* Max Transmit Power */
+} 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;				/* category of action frame (5) */
+	uint8 action;				/* radio measurement action */
+	uint8 token;				/* dialog token */
+	dot11_tpc_rep_t tpc;			/* TPC element */
+	uint8 rxant;				/* Receive Antenna ID */
+	uint8 txant;				/* Transmit Antenna ID */
+	uint8 rcpi;				/* RCPI */
+	uint8 rsni;				/* RSNI */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_lmrep dot11_lmrep_t;
+#define DOT11_LMREP_LEN	11
+
+#define DOT11_MP_CAP_SPECTRUM			0x01	/* d11 cap. spectrum */
+#define DOT11_MP_CAP_SHORTSLOT			0x02	/* d11 cap. shortslot */
+/* Measurement Pilot */
+BWL_PRE_PACKED_STRUCT struct dot11_mprep {
+	uint8 cap_info;				/* Condensed capability Info. */
+	uint8 country[2];				/* Condensed country string */
+	uint8 opclass;				/* Op. Class */
+	uint8 channel;				/* Channel */
+	uint8 mp_interval;			/* Measurement Pilot Interval */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_mprep dot11_mprep_t;
+#define DOT11_MPREP_LEN	6
+
+/* 802.11 BRCM "Compromise" Pre N constants */
+#define PREN_PREAMBLE		24	/* green field preamble time */
+#define PREN_MM_EXT		12	/* extra mixed mode preamble time */
+#define PREN_PREAMBLE_EXT	4	/* extra preamble (multiply by unique_streams-1) */
+
+/* 802.11N PHY constants */
+#define RIFS_11N_TIME		2	/* NPHY RIFS time */
+
+/* 802.11 HT PLCP format 802.11n-2009, sec 20.3.9.4.3
+ * HT-SIG is composed of two 24 bit parts, HT-SIG1 and HT-SIG2
+ */
+/* HT-SIG1 */
+#define HT_SIG1_MCS_MASK        0x00007F
+#define HT_SIG1_CBW             0x000080
+#define HT_SIG1_HT_LENGTH       0xFFFF00
+
+/* HT-SIG2 */
+#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
+
+/* HT Timing-related parameters (802.11-2012, sec 20.3.6) */
+#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       /* bits in SERVICE field */
+#define HT_N_TAIL               6       /* tail bits per BCC encoder */
+
+/* 802.11 A PHY constants */
+#define APHY_SLOT_TIME          9       /* APHY slot time */
+#define APHY_SIFS_TIME          16      /* APHY SIFS time */
+#define APHY_DIFS_TIME          (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME))  /* APHY DIFS time */
+#define APHY_PREAMBLE_TIME      16      /* APHY preamble time */
+#define APHY_SIGNAL_TIME        4       /* APHY signal time */
+#define APHY_SYMBOL_TIME        4       /* APHY symbol time */
+#define APHY_SERVICE_NBITS      16      /* APHY service nbits */
+#define APHY_TAIL_NBITS         6       /* APHY tail nbits */
+#define APHY_CWMIN              15      /* APHY cwmin */
+#define APHY_PHYHDR_DUR		20	/* APHY PHY Header Duration */
+
+/* 802.11 B PHY constants */
+#define BPHY_SLOT_TIME          20      /* BPHY slot time */
+#define BPHY_SIFS_TIME          10      /* BPHY SIFS time */
+#define BPHY_DIFS_TIME          50      /* BPHY DIFS time */
+#define BPHY_PLCP_TIME          192     /* BPHY PLCP time */
+#define BPHY_PLCP_SHORT_TIME    96      /* BPHY PLCP short time */
+#define BPHY_CWMIN              31      /* BPHY cwmin */
+#define BPHY_SHORT_PHYHDR_DUR	96	/* BPHY Short PHY Header Duration */
+#define BPHY_LONG_PHYHDR_DUR	192	/* BPHY Long PHY Header Duration */
+
+/* 802.11 G constants */
+#define DOT11_OFDM_SIGNAL_EXTENSION	6	/* d11 OFDM signal extension */
+
+#define PHY_CWMAX		1023	/* PHY cwmax */
+
+#define	DOT11_MAXNUMFRAGS	16	/* max # fragments per MSDU */
+
+/* 802.11 VHT constants */
+
+typedef int vht_group_id_t;
+
+/* for VHT-A1 */
+/* SIG-A1 reserved bits */
+#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_MAX_USERPOS           3
+
+#define VHT_SIGA1_PARTIAL_AID_MASK      0x3fe000
+#define VHT_SIGA1_PARTIAL_AID_SHIFT     13
+
+#define VHT_SIGA1_TXOP_PS_NOT_ALLOWED   0x400000
+
+/* for VHT-A2 */
+#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
+
+/* VHT Timing-related parameters (802.11ac D4.0, sec 22.3.6) */
+#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	/* bits in SERVICE field */
+#define VHT_N_TAIL               6	/* tail bits per BCC encoder */
+
+#define HE_LTF_1_GI_1_6us		(0)
+#define HE_LTF_2_GI_0_8us		(1)
+#define HE_LTF_2_GI_1_6us		(2)
+#define HE_LTF_4_GI_3_2us		(3)
+
+/** dot11Counters Table - 802.11 spec., Annex D */
+typedef struct d11cnt {
+	uint32		txfrag;		/* dot11TransmittedFragmentCount */
+	uint32		txmulti;	/* dot11MulticastTransmittedFrameCount */
+	uint32		txfail;		/* dot11FailedCount */
+	uint32		txretry;	/* dot11RetryCount */
+	uint32		txretrie;	/* dot11MultipleRetryCount */
+	uint32		rxdup;		/* dot11FrameduplicateCount */
+	uint32		txrts;		/* dot11RTSSuccessCount */
+	uint32		txnocts;	/* dot11RTSFailureCount */
+	uint32		txnoack;	/* dot11ACKFailureCount */
+	uint32		rxfrag;		/* dot11ReceivedFragmentCount */
+	uint32		rxmulti;	/* dot11MulticastReceivedFrameCount */
+	uint32		rxcrc;		/* dot11FCSErrorCount */
+	uint32		txfrmsnt;	/* dot11TransmittedFrameCount */
+	uint32		rxundec;	/* dot11WEPUndecryptableCount */
+} d11cnt_t;
+
+#define BRCM_PROP_OUI		"\x00\x90\x4C"
+
+
+#define BRCM_FTM_IE_TYPE			14
+
+/* #define HT_CAP_IE_TYPE			51
+ * #define HT_ADD_IE_TYPE			52
+ * #define BRCM_EXTCH_IE_TYPE		53
+ * #define MEMBER_OF_BRCM_PROP_IE_TYPE	54
+ * #define BRCM_RELMACST_IE_TYPE		55
+ * #define BRCM_EVT_WL_BSS_INFO		64
+ * #define RWL_ACTION_WIFI_FRAG_TYPE	85
+ * #define BTC_INFO_BRCM_PROP_IE_TYPE	90
+ * #define ULB_BRCM_PROP_IE_TYPE	91
+ */
+
+/* Action frame type for RWL */
+#define RWL_WIFI_DEFAULT		0
+#define RWL_WIFI_FIND_MY_PEER		9 /* Used while finding server */
+#define RWL_WIFI_FOUND_PEER		10 /* Server response to the client  */
+#define RWL_ACTION_WIFI_FRAG_TYPE	85 /* Fragment indicator for receiver */
+
+#define PROXD_AF_TYPE			11 /* Wifi proximity action frame type */
+#define BRCM_RELMACST_AF_TYPE	        12 /* RMC action frame type */
+
+/* Action frame type for FTM Initiator Report */
+#define BRCM_FTM_VS_AF_TYPE	14
+enum {
+	BRCM_FTM_VS_INITIATOR_RPT_SUBTYPE = 1,	/* FTM Initiator Report */
+	BRCM_FTM_VS_COLLECT_SUBTYPE = 2,	/* FTM Collect debug protocol */
+};
+
+
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/*
+ * This BRCM_PROP_OUI types is intended for use in events to embed additional
+ * data, and would not be expected to appear on the air -- but having an IE
+ * format allows IE frame data with extra data in events in that allows for
+ * more flexible parsing.
+ */
+#define BRCM_EVT_WL_BSS_INFO	64
+
+/**
+ * Following is the generic structure for brcm_prop_ie (uses BRCM_PROP_OUI).
+ * DPT uses this format with type set to DPT_IE_TYPE
+ */
+BWL_PRE_PACKED_STRUCT struct brcm_prop_ie_s {
+	uint8 id;		/* IE ID, 221, DOT11_MNG_PROPR_ID */
+	uint8 len;		/* IE length */
+	uint8 oui[3];
+	uint8 type;		/* type of this IE */
+	uint16 cap;		/* DPT capabilities */
+} BWL_POST_PACKED_STRUCT;
+typedef struct brcm_prop_ie_s brcm_prop_ie_t;
+
+#define BRCM_PROP_IE_LEN	6	/* len of fixed part of brcm_prop ie */
+
+#define DPT_IE_TYPE             2
+
+
+#define BRCM_SYSCAP_IE_TYPE	3
+#define WET_TUNNEL_IE_TYPE	3
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* brcm syscap_ie cap */
+#define BRCM_SYSCAP_WET_TUNNEL	0x0100	/* Device with WET_TUNNEL support */
+
+#define BRCM_OUI		"\x00\x10\x18"	/* Broadcom OUI */
+
+/** BRCM info element */
+BWL_PRE_PACKED_STRUCT struct brcm_ie {
+	uint8	id;		/* IE ID, 221, DOT11_MNG_PROPR_ID */
+	uint8	len;		/* IE length */
+	uint8	oui[3];
+	uint8	ver;		/* type/ver of this IE */
+	uint8	assoc;		/* # of assoc STAs */
+	uint8	flags;		/* misc flags */
+	uint8	flags1;		/* misc flags */
+	uint16	amsdu_mtu_pref;	/* preferred A-MSDU MTU */
+} BWL_POST_PACKED_STRUCT;
+typedef	struct brcm_ie brcm_ie_t;
+#define BRCM_IE_LEN		11	/* BRCM IE length */
+#define BRCM_IE_VER		2	/* BRCM IE version */
+#define BRCM_IE_LEGACY_AES_VER	1	/* BRCM IE legacy AES version */
+
+/* brcm_ie flags */
+#define	BRF_ABCAP		0x1	/* afterburner is obsolete,  defined for backward compat */
+#define	BRF_ABRQRD		0x2	/* afterburner is obsolete,  defined for backward compat */
+#define	BRF_LZWDS		0x4	/* lazy wds enabled */
+#define	BRF_BLOCKACK		0x8	/* BlockACK capable */
+#define BRF_ABCOUNTER_MASK	0xf0	/* afterburner is obsolete,  defined for backward compat */
+#define BRF_PROP_11N_MCS	0x10	/* re-use afterburner bit */
+#define BRF_MEDIA_CLIENT	0x20	/* re-use afterburner bit to indicate media client device */
+
+#define GET_BRF_PROP_11N_MCS(brcm_ie) \
+	(!((brcm_ie)->flags & BRF_ABCAP) && ((brcm_ie)->flags & BRF_PROP_11N_MCS))
+
+/* brcm_ie flags1 */
+#define	BRF1_AMSDU		0x1	/* A-MSDU capable */
+#define	BRF1_WNM		0x2	/* WNM capable */
+#define BRF1_WMEPS		0x4	/* AP is capable of handling WME + PS w/o APSD */
+#define BRF1_PSOFIX		0x8	/* AP has fixed PS mode out-of-order packets */
+#define	BRF1_RX_LARGE_AGG	0x10	/* device can rx large aggregates */
+#define BRF1_RFAWARE_DCS	0x20    /* RFAWARE dynamic channel selection (DCS) */
+#define BRF1_SOFTAP		0x40    /* Configure as Broadcom SOFTAP */
+#define BRF1_DWDS		0x80    /* DWDS capable */
+
+/** Vendor IE structure */
+BWL_PRE_PACKED_STRUCT struct vndr_ie {
+	uchar id;
+	uchar len;
+	uchar oui [3];
+	uchar data [1]; 	/* Variable size data */
+} BWL_POST_PACKED_STRUCT;
+typedef struct vndr_ie vndr_ie_t;
+
+#define VNDR_IE_HDR_LEN		2	/* id + len field */
+#define VNDR_IE_MIN_LEN		3	/* size of the oui field */
+#define VNDR_IE_FIXED_LEN	(VNDR_IE_HDR_LEN + VNDR_IE_MIN_LEN)
+
+#define VNDR_IE_MAX_LEN		255	/* vendor IE max length, without ID and len */
+
+/** BRCM PROP DEVICE PRIMARY MAC ADDRESS IE */
+BWL_PRE_PACKED_STRUCT struct member_of_brcm_prop_ie {
+	uchar id;
+	uchar len;
+	uchar oui[3];
+	uint8	type;           /* type indicates what follows */
+	struct ether_addr ea;   /* Device Primary MAC Adrress */
+} 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	/* IE max length */
+#define MEMBER_OF_BRCM_PROP_IE_HDRLEN	        (sizeof(member_of_brcm_prop_ie_t))
+#define MEMBER_OF_BRCM_PROP_IE_TYPE		54
+
+/** BRCM Reliable Multicast IE */
+BWL_PRE_PACKED_STRUCT struct relmcast_brcm_prop_ie {
+	uint8 id;
+	uint8 len;
+	uint8 oui[3];
+	uint8 type;           /* type indicates what follows */
+	struct ether_addr ea;   /* The ack sender's MAC Adrress */
+	struct ether_addr mcast_ea;  /* The multicast MAC address */
+	uint8 updtmo; /* time interval(second) for client to send null packet to report its rssi */
+} BWL_POST_PACKED_STRUCT;
+typedef struct relmcast_brcm_prop_ie relmcast_brcm_prop_ie_t;
+
+/* IE length */
+/* BRCM_PROP_IE_LEN = sizeof(relmcast_brcm_prop_ie_t)-((sizeof (id) + sizeof (len)))? */
+#define RELMCAST_BRCM_PROP_IE_LEN	(sizeof(relmcast_brcm_prop_ie_t)-(2*sizeof(uint8)))
+
+#define RELMCAST_BRCM_PROP_IE_TYPE	55
+
+/* BRCM BTC IE */
+BWL_PRE_PACKED_STRUCT struct btc_brcm_prop_ie {
+	uint8 id;
+	uint8 len;
+	uint8 oui[3];
+	uint8 type;           /* type inidicates what follows */
+	uint32 info;
+} BWL_POST_PACKED_STRUCT;
+typedef struct btc_brcm_prop_ie btc_brcm_prop_ie_t;
+
+#define BTC_INFO_BRCM_PROP_IE_TYPE	90
+#define BRCM_BTC_INFO_TYPE_LEN	(sizeof(btc_brcm_prop_ie_t) - (2 * sizeof(uint8)))
+
+/* ************* HT definitions. ************* */
+#define MCSSET_LEN	16	/* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */
+#define MAX_MCS_NUM	(128)	/* max mcs number = 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;
+
+/* CAP IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */
+/* the capability IE is primarily used to convey this nodes abilities */
+BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie {
+	uint8	id;		/* IE ID, 221, DOT11_MNG_PROPR_ID */
+	uint8	len;		/* IE length */
+	uint8	oui[3];
+	uint8	type;           /* type indicates what follows */
+	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	/* overhead bytes for prop oui ie */
+#define HT_CAP_IE_LEN		26	/* HT capability len (based on .11n d2.0) */
+#define HT_CAP_IE_TYPE		51
+
+#define HT_CAP_LDPC_CODING	0x0001	/* Support for rx of LDPC coded pkts */
+#define HT_CAP_40MHZ		0x0002  /* FALSE:20Mhz, TRUE:20/40MHZ supported */
+#define HT_CAP_MIMO_PS_MASK	0x000C  /* Mimo PS mask */
+#define HT_CAP_MIMO_PS_SHIFT	0x0002	/* Mimo PS shift */
+#define HT_CAP_MIMO_PS_OFF	0x0003	/* Mimo PS, no restriction */
+#define HT_CAP_MIMO_PS_RTS	0x0001	/* Mimo PS, send RTS/CTS around MIMO frames */
+#define HT_CAP_MIMO_PS_ON	0x0000	/* Mimo PS, MIMO disallowed */
+#define HT_CAP_GF		0x0010	/* Greenfield preamble support */
+#define HT_CAP_SHORT_GI_20	0x0020	/* 20MHZ short guard interval support */
+#define HT_CAP_SHORT_GI_40	0x0040	/* 40Mhz short guard interval support */
+#define HT_CAP_TX_STBC		0x0080	/* Tx STBC support */
+#define HT_CAP_RX_STBC_MASK	0x0300	/* Rx STBC mask */
+#define HT_CAP_RX_STBC_SHIFT	8	/* Rx STBC shift */
+#define HT_CAP_DELAYED_BA	0x0400	/* delayed BA support */
+#define HT_CAP_MAX_AMSDU	0x0800	/* Max AMSDU size in bytes , 0=3839, 1=7935 */
+
+#define HT_CAP_DSSS_CCK	0x1000	/* DSSS/CCK supported by the BSS */
+#define HT_CAP_PSMP		0x2000	/* Power Save Multi Poll support */
+#define HT_CAP_40MHZ_INTOLERANT 0x4000	/* 40MHz Intolerant */
+#define HT_CAP_LSIG_TXOP	0x8000	/* L-SIG TXOP protection support */
+
+#define HT_CAP_RX_STBC_NO		0x0	/* no rx STBC support */
+#define HT_CAP_RX_STBC_ONE_STREAM	0x1	/* rx STBC support of 1 spatial stream */
+#define HT_CAP_RX_STBC_TWO_STREAM	0x2	/* rx STBC support of 1-2 spatial streams */
+#define HT_CAP_RX_STBC_THREE_STREAM	0x3	/* rx STBC support of 1-3 spatial streams */
+
+
+#define HT_CAP_TXBF_CAP_IMPLICIT_TXBF_RX	0x1
+#define HT_CAP_TXBF_CAP_NDP_RX			0x8
+#define HT_CAP_TXBF_CAP_NDP_TX			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 HT_CAP_TX_BF_CAP_EXPLICIT_CSI_FB_MASK	0x400
+#define HT_CAP_TX_BF_CAP_EXPLICIT_CSI_FB_SHIFT	10
+#define HT_CAP_TX_BF_CAP_EXPLICIT_COMPRESSED_FB_MASK 0x18000
+#define HT_CAP_TX_BF_CAP_EXPLICIT_COMPRESSED_FB_SHIFT 15
+
+#define HT_CAP_MCS_FLAGS_SUPP_BYTE 12 /* byte offset in HT Cap Supported MCS for various flags */
+#define HT_CAP_MCS_RX_8TO15_BYTE_OFFSET                1
+#define HT_CAP_MCS_FLAGS_TX_RX_UNEQUAL              0x02
+#define HT_CAP_MCS_FLAGS_MAX_SPATIAL_STREAM_MASK    0x0C
+
+#define VHT_MAX_MPDU		11454	/* max mpdu size for now (bytes) */
+#define VHT_MPDU_MSDU_DELTA	56		/* Difference in spec - vht mpdu, amsdu len */
+/* Max AMSDU len - per spec */
+#define VHT_MAX_AMSDU		(VHT_MAX_MPDU - VHT_MPDU_MSDU_DELTA)
+
+#define HT_MAX_AMSDU		7935	/* max amsdu size (bytes) per the HT spec */
+#define HT_MIN_AMSDU		3835	/* min amsdu size (bytes) per the HT spec */
+
+#define HT_PARAMS_RX_FACTOR_MASK	0x03	/* ampdu rcv factor mask */
+#define HT_PARAMS_DENSITY_MASK		0x1C	/* ampdu density mask */
+#define HT_PARAMS_DENSITY_SHIFT	2	/* ampdu density shift */
+
+/* HT/AMPDU specific define */
+#define AMPDU_MAX_MPDU_DENSITY  7       /* max mpdu density; in 1/4 usec units */
+#define AMPDU_DENSITY_NONE      0       /* No density requirement */
+#define AMPDU_DENSITY_1over4_US 1       /* 1/4 us density */
+#define AMPDU_DENSITY_1over2_US 2       /* 1/2 us density */
+#define AMPDU_DENSITY_1_US      3       /*   1 us density */
+#define AMPDU_DENSITY_2_US      4       /*   2 us density */
+#define AMPDU_DENSITY_4_US      5       /*   4 us density */
+#define AMPDU_DENSITY_8_US      6       /*   8 us density */
+#define AMPDU_DENSITY_16_US     7       /*  16 us density */
+#define AMPDU_RX_FACTOR_8K      0       /* max rcv ampdu len (8kb) */
+#define AMPDU_RX_FACTOR_16K     1       /* max rcv ampdu len (16kb) */
+#define AMPDU_RX_FACTOR_32K     2       /* max rcv ampdu len (32kb) */
+#define AMPDU_RX_FACTOR_64K     3       /* max rcv ampdu len (64kb) */
+
+/* AMPDU RX factors for VHT rates */
+#define AMPDU_RX_FACTOR_128K    4       /* max rcv ampdu len (128kb) */
+#define AMPDU_RX_FACTOR_256K    5       /* max rcv ampdu len (256kb) */
+#define AMPDU_RX_FACTOR_512K    6       /* max rcv ampdu len (512kb) */
+#define AMPDU_RX_FACTOR_1024K   7       /* max rcv ampdu len (1024kb) */
+
+#define AMPDU_RX_FACTOR_BASE    8*1024  /* ampdu factor base for rx len */
+#define AMPDU_RX_FACTOR_BASE_PWR	13	/* ampdu factor base for rx len in power of 2 */
+
+#define AMPDU_DELIMITER_LEN	4	/* length of ampdu delimiter */
+#define AMPDU_DELIMITER_LEN_MAX	63	/* max length of ampdu delimiter(enforced in HW) */
+
+#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
+
+/** 'ht_add' is called 'HT Operation' information element in the 802.11 standard */
+BWL_PRE_PACKED_STRUCT struct ht_add_ie {
+	uint8	ctl_ch;			/* control channel number */
+	uint8	byte1;			/* ext ch,rec. ch. width, RIFS support */
+	uint16	opmode;			/* operation mode */
+	uint16	misc_bits;		/* misc bits */
+	uint8	basic_mcs[MCSSET_LEN];  /* required MCS set */
+} BWL_POST_PACKED_STRUCT;
+typedef struct ht_add_ie ht_add_ie_t;
+
+/* ADD IE: HT 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */
+/* the additional IE is primarily used to convey the current BSS configuration */
+BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie {
+	uint8	id;		/* IE ID, 221, DOT11_MNG_PROPR_ID */
+	uint8	len;		/* IE length */
+	uint8	oui[3];
+	uint8	type;		/* indicates what follows */
+	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
+
+/* byte1 defn's */
+#define HT_BW_ANY		0x04	/* set, STA can use 20 or 40MHz */
+#define HT_RIFS_PERMITTED     	0x08	/* RIFS allowed */
+
+/* opmode defn's */
+#define HT_OPMODE_MASK	        0x0003	/* protection mode mask */
+#define HT_OPMODE_SHIFT		0	/* protection mode shift */
+#define HT_OPMODE_PURE		0x0000	/* protection mode PURE */
+#define HT_OPMODE_OPTIONAL	0x0001	/* protection mode optional */
+#define HT_OPMODE_HT20IN40	0x0002	/* protection mode 20MHz HT in 40MHz BSS */
+#define HT_OPMODE_MIXED	0x0003	/* protection mode Mixed Mode */
+#define HT_OPMODE_NONGF	0x0004	/* protection mode non-GF */
+#define DOT11N_TXBURST		0x0008	/* Tx burst limit */
+#define DOT11N_OBSS_NONHT	0x0010	/* OBSS Non-HT STA present */
+
+/* misc_bites defn's */
+#define HT_BASIC_STBC_MCS	0x007f	/* basic STBC MCS */
+#define HT_DUAL_STBC_PROT	0x0080	/* Dual STBC Protection */
+#define HT_SECOND_BCN		0x0100	/* Secondary beacon support */
+#define HT_LSIG_TXOP		0x0200	/* L-SIG TXOP Protection full support */
+#define HT_PCO_ACTIVE		0x0400	/* PCO active */
+#define HT_PCO_PHASE		0x0800	/* PCO phase */
+#define HT_DUALCTS_PROTECTION	0x0080	/* DUAL CTS protection needed */
+
+/* Tx Burst Limits */
+#define DOT11N_2G_TXBURST_LIMIT	6160	/* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */
+#define DOT11N_5G_TXBURST_LIMIT	3080	/* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */
+
+/* Macros for opmode */
+#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)	/* mixed mode present */
+#define HT_HT20_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+					== HT_OPMODE_HT20IN40)	/* 20MHz HT present */
+#define HT_OPTIONAL_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \
+					== HT_OPMODE_OPTIONAL)	/* Optional protection present */
+#define HT_USE_PROTECTION(add_ie)	(HT_HT20_PRESENT((add_ie)) || \
+					HT_MIXEDMODE_PRESENT((add_ie))) /* use protection */
+#define HT_NONGF_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \
+					== HT_OPMODE_NONGF)	/* non-GF present */
+#define DOT11N_TXBURST_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \
+					== DOT11N_TXBURST)	/* Tx Burst present */
+#define DOT11N_OBSS_NONHT_PRESENT(add_ie)	((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \
+					== DOT11N_OBSS_NONHT)	/* OBSS Non-HT present */
+/* Macros for HT MCS filed access */
+#define HT_CAP_MCS_BITMASK(supp_mcs)                 \
+	((supp_mcs)[HT_CAP_MCS_RX_8TO15_BYTE_OFFSET])
+#define HT_CAP_MCS_TX_RX_UNEQUAL(supp_mcs)          \
+	((supp_mcs)[HT_CAP_MCS_FLAGS_SUPP_BYTE] & HT_CAP_MCS_FLAGS_TX_RX_UNEQUAL)
+#define HT_CAP_MCS_TX_STREAM_SUPPORT(supp_mcs)          \
+		((supp_mcs)[HT_CAP_MCS_FLAGS_SUPP_BYTE] & HT_CAP_MCS_FLAGS_MAX_SPATIAL_STREAM_MASK)
+
+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)	/* HT OBSS len (based on 802.11n d3.0) */
+
+/* HT control field */
+#define HT_CTRL_LA_TRQ		0x00000002	/* sounding request */
+#define HT_CTRL_LA_MAI		0x0000003C	/* MCS request or antenna selection indication */
+#define HT_CTRL_LA_MAI_SHIFT	2
+#define HT_CTRL_LA_MAI_MRQ	0x00000004	/* MCS request */
+#define HT_CTRL_LA_MAI_MSI	0x00000038	/* MCS request sequence identifier */
+#define HT_CTRL_LA_MFSI		0x000001C0	/* MFB sequence identifier */
+#define HT_CTRL_LA_MFSI_SHIFT	6
+#define HT_CTRL_LA_MFB_ASELC	0x0000FE00	/* MCS feedback, antenna selection command/data */
+#define HT_CTRL_LA_MFB_ASELC_SH	9
+#define HT_CTRL_LA_ASELC_CMD	0x00000C00	/* ASEL command */
+#define HT_CTRL_LA_ASELC_DATA	0x0000F000	/* ASEL data */
+#define HT_CTRL_CAL_POS		0x00030000	/* Calibration position */
+#define HT_CTRL_CAL_SEQ		0x000C0000	/* Calibration sequence */
+#define HT_CTRL_CSI_STEERING	0x00C00000	/* CSI/Steering */
+#define HT_CTRL_CSI_STEER_SHIFT	22
+#define HT_CTRL_CSI_STEER_NFB	0		/* no fedback required */
+#define HT_CTRL_CSI_STEER_CSI	1		/* CSI, H matrix */
+#define HT_CTRL_CSI_STEER_NCOM	2		/* non-compressed beamforming */
+#define HT_CTRL_CSI_STEER_COM	3		/* compressed beamforming */
+#define HT_CTRL_NDP_ANNOUNCE	0x01000000	/* NDP announcement */
+#define HT_CTRL_AC_CONSTRAINT	0x40000000	/* AC Constraint */
+#define HT_CTRL_RDG_MOREPPDU	0x80000000	/* RDG/More PPDU */
+
+/* ************* VHT definitions. ************* */
+
+/**
+ * VHT Capabilites IE (sec 8.4.2.160)
+ */
+
+BWL_PRE_PACKED_STRUCT struct vht_cap_ie {
+	uint32  vht_cap_info;
+	/* supported MCS set - 64 bit field */
+	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;
+
+/* 4B cap_info + 8B supp_mcs */
+#define VHT_CAP_IE_LEN 12
+
+/* VHT Capabilities Info field - 32bit - in VHT Cap IE */
+#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
+
+/* VHT Supported MCS Set - 64-bit - in VHT Cap IE */
+#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK   0x1fff
+#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT  0
+#define VHT_CAP_SUPP_CHAN_WIDTH_SHIFT		5
+
+#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 /* num bits for 1-stream */
+#define VHT_CAP_MCS_MAP_M                       0x3 /* mask for 1-stream */
+/* assumes VHT_CAP_MCS_MAP_NONE is 3 and 2 bits are used for encoding */
+#define VHT_CAP_MCS_MAP_NONE_ALL                0xffff
+
+/* VHT rates bitmap */
+#define VHT_CAP_MCS_0_7_RATEMAP		0x00ff
+#define VHT_CAP_MCS_0_8_RATEMAP		0x01ff
+#define VHT_CAP_MCS_0_9_RATEMAP		0x03ff
+#define VHT_CAP_MCS_FULL_RATEMAP 	VHT_CAP_MCS_0_9_RATEMAP
+
+#define VHT_PROP_MCS_MAP_10_11                   0
+#define VHT_PROP_MCS_MAP_UNUSED1                 1
+#define VHT_PROP_MCS_MAP_UNUSED2                 2
+#define VHT_PROP_MCS_MAP_NONE                    3
+#define VHT_PROP_MCS_MAP_NONE_ALL                0xffff
+
+/* VHT prop rates bitmap */
+#define VHT_PROP_MCS_10_11_RATEMAP	0x0c00
+#define VHT_PROP_MCS_FULL_RATEMAP	VHT_PROP_MCS_10_11_RATEMAP
+
+#if !defined(VHT_CAP_MCS_MAP_0_9_NSS3)
+/* mcsmap with MCS0-9 for Nss = 3 */
+#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)))
+#endif /* !VHT_CAP_MCS_MAP_0_9_NSS3 */
+
+#define VHT_CAP_MCS_MAP_NSS_MAX                 8
+
+/* get mcsmap with given mcs for given nss streams */
+#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)
+
+/* Map the mcs code to mcs bit map */
+#define VHT_MCS_CODE_TO_MCS_MAP(mcs_code) \
+	((mcs_code == VHT_CAP_MCS_MAP_0_7) ? VHT_CAP_MCS_0_7_RATEMAP : \
+	 (mcs_code == VHT_CAP_MCS_MAP_0_8) ? VHT_CAP_MCS_0_8_RATEMAP : \
+	 (mcs_code == VHT_CAP_MCS_MAP_0_9) ? VHT_CAP_MCS_0_9_RATEMAP : 0)
+
+#define VHT_PROP_MCS_CODE_TO_PROP_MCS_MAP(mcs_code) \
+	((mcs_code == VHT_PROP_MCS_MAP_10_11) ? VHT_PROP_MCS_10_11_RATEMAP : 0)
+
+/* Map the mcs bit map to mcs code */
+#define VHT_MCS_MAP_TO_MCS_CODE(mcs_map) \
+	((mcs_map == VHT_CAP_MCS_0_7_RATEMAP) ? VHT_CAP_MCS_MAP_0_7 : \
+	 (mcs_map == VHT_CAP_MCS_0_8_RATEMAP) ? VHT_CAP_MCS_MAP_0_8 : \
+	 (mcs_map == VHT_CAP_MCS_0_9_RATEMAP) ? VHT_CAP_MCS_MAP_0_9 : VHT_CAP_MCS_MAP_NONE)
+
+#define VHT_PROP_MCS_MAP_TO_PROP_MCS_CODE(mcs_map) \
+	(((mcs_map & 0xc00) == 0xc00)  ? VHT_PROP_MCS_MAP_10_11 : VHT_PROP_MCS_MAP_NONE)
+
+/** VHT Capabilities Supported Channel Width */
+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;
+
+/** VHT Capabilities Supported max MPDU LEN (sec 8.4.2.160.2) */
+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;
+
+/* Maximum MPDU Length byte counts for the VHT Capabilities advertised limits */
+#define VHT_MPDU_LIMIT_4K        3895
+#define VHT_MPDU_LIMIT_8K        7991
+#define VHT_MPDU_LIMIT_11K      11454
+
+
+/**
+ * VHT Operation IE (sec 8.4.2.161)
+ */
+
+BWL_PRE_PACKED_STRUCT struct vht_op_ie {
+	uint8	chan_width;
+	uint8	chan1;
+	uint8	chan2;
+	uint16	supp_mcs;  /*  same def as above in vht cap */
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_op_ie vht_op_ie_t;
+
+/* 3B VHT Op info + 2B Basic MCS */
+#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;
+
+/* AID length */
+#define AID_IE_LEN		2
+/**
+ * BRCM vht features IE header
+ * The header if the fixed part of the IE
+ * On the 5GHz band this is the entire IE,
+ * on 2.4GHz the VHT IEs as defined in the 802.11ac
+ * specification follows
+ *
+ *
+ * VHT features rates  bitmap.
+ * Bit0:		5G MCS 0-9 BW 160MHz
+ * Bit1:		5G MCS 0-9 support BW 80MHz
+ * Bit2:		5G MCS 0-9 support BW 20MHz
+ * Bit3:		2.4G MCS 0-9 support BW 20MHz
+ * Bits:4-7	Reserved for future use
+ *
+ */
+#define VHT_FEATURES_IE_TYPE	0x4
+BWL_PRE_PACKED_STRUCT struct vht_features_ie_hdr {
+	uint8 oui[3];
+	uint8 type;		/* type of this IE = 4 */
+	uint8 rate_mask;	/* VHT rate mask */
+} BWL_POST_PACKED_STRUCT;
+typedef struct vht_features_ie_hdr vht_features_ie_hdr_t;
+
+/* Def for rx & tx basic mcs maps - ea ss num has 2 bits of info */
+#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)
+
+/* Get the max ss supported from the mcs map */
+#define VHT_MAX_SS_SUPPORTED(mcsMap) \
+	VHT_MCS_SS_SUPPORTED(8, mcsMap) ? 8 : \
+	VHT_MCS_SS_SUPPORTED(7, mcsMap) ? 7 : \
+	VHT_MCS_SS_SUPPORTED(6, mcsMap) ? 6 : \
+	VHT_MCS_SS_SUPPORTED(5, mcsMap) ? 5 : \
+	VHT_MCS_SS_SUPPORTED(4, mcsMap) ? 4 : \
+	VHT_MCS_SS_SUPPORTED(3, mcsMap) ? 3 : \
+	VHT_MCS_SS_SUPPORTED(2, mcsMap) ? 2 : \
+	VHT_MCS_SS_SUPPORTED(1, mcsMap) ? 1 : 0
+
+/* ************* WPA definitions. ************* */
+#define WPA_OUI			"\x00\x50\xF2"	/* WPA OUI */
+#define WPA_OUI_LEN		3		/* WPA OUI length */
+#define WPA_OUI_TYPE		1
+#define WPA_VERSION		1		/* WPA version */
+#define WPA2_OUI		"\x00\x0F\xAC"	/* WPA2 OUI */
+#define WPA2_OUI_LEN		3		/* WPA2 OUI length */
+#define WPA2_VERSION		1		/* WPA2 version */
+#define WPA2_VERSION_LEN	2		/* WAP2 version length */
+
+/* ************* WPS definitions. ************* */
+#define WPS_OUI			"\x00\x50\xF2"	/* WPS OUI */
+#define WPS_OUI_LEN		3		/* WPS OUI length */
+#define WPS_OUI_TYPE		4
+
+/* ************* WFA definitions. ************* */
+
+#ifdef P2P_IE_OVRD
+#define WFA_OUI			MAC_OUI
+#else
+#define WFA_OUI			"\x50\x6F\x9A"	/* WFA OUI */
+#endif /* P2P_IE_OVRD */
+#define WFA_OUI_LEN		3		/* WFA OUI length */
+#ifdef P2P_IE_OVRD
+#define WFA_OUI_TYPE_P2P	MAC_OUI_TYPE_P2P
+#else
+#define WFA_OUI_TYPE_TPC	8
+#define WFA_OUI_TYPE_P2P	9
+#endif
+
+#define WFA_OUI_TYPE_TPC	8
+#ifdef WLTDLS
+#define WFA_OUI_TYPE_TPQ	4	/* WFD Tunneled Probe ReQuest */
+#define WFA_OUI_TYPE_TPS	5	/* WFD Tunneled Probe ReSponse */
+#define WFA_OUI_TYPE_WFD	10
+#endif /* WTDLS */
+#define WFA_OUI_TYPE_HS20	0x10
+#define WFA_OUI_TYPE_OSEN	0x12
+#define WFA_OUI_TYPE_NAN	0x13
+#define WFA_OUI_TYPE_MBO	0x16
+#define WFA_OUI_TYPE_MBO_OCE	0x16
+
+/* RSN authenticated key managment suite */
+#define RSN_AKM_NONE		0	/* None (IBSS) */
+#define RSN_AKM_UNSPECIFIED	1	/* Over 802.1x */
+#define RSN_AKM_PSK		2	/* Pre-shared Key */
+#define RSN_AKM_FBT_1X		3	/* Fast Bss transition using 802.1X */
+#define RSN_AKM_FBT_PSK		4	/* Fast Bss transition using Pre-shared Key */
+/* RSN_AKM_MFP_1X and RSN_AKM_MFP_PSK are not used any more
+ * Just kept here to avoid build issue in BISON/CARIBOU branch
+ */
+#define RSN_AKM_MFP_1X		5	/* SHA256 key derivation, using 802.1X */
+#define RSN_AKM_MFP_PSK		6	/* SHA256 key derivation, using Pre-shared Key */
+#define RSN_AKM_SHA256_1X	5	/* SHA256 key derivation, using 802.1X */
+#define RSN_AKM_SHA256_PSK	6	/* SHA256 key derivation, using Pre-shared Key */
+#define RSN_AKM_TPK		7	/* TPK(TDLS Peer Key) handshake */
+
+/* OSEN authenticated key managment suite */
+#define OSEN_AKM_UNSPECIFIED	RSN_AKM_UNSPECIFIED	/* Over 802.1x */
+
+/* Key related defines */
+#define DOT11_MAX_DEFAULT_KEYS	4	/* number of default keys */
+#define DOT11_MAX_IGTK_KEYS		2
+#define DOT11_MAX_KEY_SIZE	32	/* max size of any key */
+#define DOT11_MAX_IV_SIZE	16	/* max size of any IV */
+#define DOT11_EXT_IV_FLAG	(1<<5)	/* flag to indicate IV is > 4 bytes */
+#define DOT11_WPA_KEY_RSC_LEN   8       /* WPA RSC key len */
+
+#define WEP1_KEY_SIZE		5	/* max size of any WEP key */
+#define WEP1_KEY_HEX_SIZE	10	/* size of WEP key in hex. */
+#define WEP128_KEY_SIZE		13	/* max size of any WEP key */
+#define WEP128_KEY_HEX_SIZE	26	/* size of WEP key in hex. */
+#define TKIP_MIC_SIZE		8	/* size of TKIP MIC */
+#define TKIP_EOM_SIZE		7	/* max size of TKIP EOM */
+#define TKIP_EOM_FLAG		0x5a	/* TKIP EOM flag byte */
+#define TKIP_KEY_SIZE		32	/* size of any TKIP key, includs MIC keys */
+#define TKIP_TK_SIZE		16
+#define TKIP_MIC_KEY_SIZE	8
+#define TKIP_MIC_AUTH_TX	16	/* offset to Authenticator MIC TX key */
+#define TKIP_MIC_AUTH_RX	24	/* offset to Authenticator MIC RX key */
+#define TKIP_MIC_SUP_RX		TKIP_MIC_AUTH_TX	/* offset to Supplicant MIC RX key */
+#define TKIP_MIC_SUP_TX		TKIP_MIC_AUTH_RX	/* offset to Supplicant MIC TX key */
+#define AES_KEY_SIZE		16	/* size of AES key */
+#define AES_MIC_SIZE		8	/* size of AES MIC */
+#define BIP_KEY_SIZE		16	/* size of BIP key */
+#define BIP_MIC_SIZE		8   /* sizeof BIP MIC */
+
+#define AES_GCM_MIC_SIZE	16	/* size of MIC for 128-bit GCM - .11adD9 */
+
+#define AES256_KEY_SIZE		32	/* size of AES 256 key - .11acD5 */
+#define AES256_MIC_SIZE		16	/* size of MIC for 256 bit keys, incl BIP */
+
+/* WCN */
+#define WCN_OUI			"\x00\x50\xf2"	/* WCN OUI */
+#define WCN_TYPE		4	/* WCN type */
+
+
+/* 802.11r protocol definitions */
+
+/** Mobility Domain IE */
+BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie {
+	uint8 id;
+	uint8 len;
+	uint16 mdid;		/* Mobility Domain Id */
+	uint8 cap;
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_mdid_ie dot11_mdid_ie_t;
+
+#define FBT_MDID_CAP_OVERDS	0x01	/* Fast Bss transition over the DS support */
+#define FBT_MDID_CAP_RRP	0x02	/* Resource request protocol support */
+
+/** Fast Bss Transition IE */
+BWL_PRE_PACKED_STRUCT struct dot11_ft_ie {
+	uint8 id;
+	uint8 len;
+	uint16 mic_control;		/* 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;		/* timeout interval type */
+	uint32 value;		/* timeout interval value */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_timeout_ie dot11_timeout_ie_t;
+
+/** GTK ie */
+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;
+
+/** Management MIC ie */
+BWL_PRE_PACKED_STRUCT struct mmic_ie {
+	uint8   id;					/* IE ID: DOT11_MNG_MMIE_ID */
+	uint8   len;				/* IE length */
+	uint16  key_id;				/* key id */
+	uint8   ipn[6];				/* ipn */
+	uint8   mic[16];			/* mic */
+} BWL_POST_PACKED_STRUCT;
+typedef struct mmic_ie mmic_ie_t;
+
+/* 802.11r-2008, 11A.10.3 - RRB frame format */
+BWL_PRE_PACKED_STRUCT struct dot11_ft_rrb_frame {
+	uint8  frame_type; /* 1 for RRB */
+	uint8  packet_type; /* 0 for Request 1 for Response */
+	uint16 len;
+	uint8  cur_ap_addr[ETHER_ADDR_LEN];
+	uint8  data[1];	/* IEs Received/Sent in FT Action Req/Resp Frame */
+} BWL_POST_PACKED_STRUCT;
+
+typedef struct dot11_ft_rrb_frame dot11_ft_rrb_frame_t;
+
+#define DOT11_FT_RRB_FIXED_LEN 10
+#define DOT11_FT_REMOTE_FRAME_TYPE 1
+#define DOT11_FT_PACKET_REQ 0
+#define DOT11_FT_PACKET_RESP 1
+
+#define BSSID_INVALID           "\x00\x00\x00\x00\x00\x00"
+#define BSSID_BROADCAST         "\xFF\xFF\xFF\xFF\xFF\xFF"
+
+#ifdef BCMWAPI_WAI
+#define WAPI_IE_MIN_LEN 	20	/* WAPI IE min length */
+#define WAPI_VERSION		1	/* WAPI version */
+#define WAPI_VERSION_LEN	2	/* WAPI version length */
+#define WAPI_OUI		"\x00\x14\x72"	/* WAPI OUI */
+#define WAPI_OUI_LEN		DOT11_OUI_LEN	/* WAPI OUI length */
+#endif /* BCMWAPI_WAI */
+
+/* ************* WMM Parameter definitions. ************* */
+#define WMM_OUI			"\x00\x50\xF2"	/* WNN OUI */
+#define WMM_OUI_LEN		3		/* WMM OUI length */
+#define WMM_OUI_TYPE	2		/* WMM OUT type */
+#define WMM_VERSION		1
+#define WMM_VERSION_LEN	1
+
+/* WMM OUI subtype */
+#define WMM_OUI_SUBTYPE_PARAMETER	1
+#define WMM_PARAMETER_IE_LEN		24
+
+/** Link Identifier Element */
+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
+
+/** Link Wakeup Schedule Element */
+BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie {
+	uint8 id;
+	uint8 len;
+	uint32 offset;			/* in ms between TSF0 and start of 1st Awake Window */
+	uint32 interval;		/* in ms bwtween the start of 2 Awake Windows */
+	uint32 awake_win_slots;	/* in backof slots, duration of Awake Window */
+	uint32 max_wake_win;	/* in ms, max duration of Awake Window */
+	uint16 idle_cnt;		/* number of consecutive Awake Windows */
+} BWL_POST_PACKED_STRUCT;
+typedef struct wakeup_sch_ie wakeup_sch_ie_t;
+#define TDLS_WAKEUP_SCH_IE_LEN		18
+
+/** Channel Switch Timing Element */
+BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie {
+	uint8 id;
+	uint8 len;
+	uint16 switch_time;		/* in ms, time to switch channels */
+	uint16 switch_timeout;	/* in ms */
+} BWL_POST_PACKED_STRUCT;
+typedef struct channel_switch_timing_ie channel_switch_timing_ie_t;
+#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN		4
+
+/** PTI Control Element */
+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
+
+/** PU Buffer Status Element */
+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
+
+/* TDLS Action Field Values */
+#define TDLS_SETUP_REQ				0
+#define TDLS_SETUP_RESP				1
+#define TDLS_SETUP_CONFIRM			2
+#define TDLS_TEARDOWN				3
+#define TDLS_PEER_TRAFFIC_IND			4
+#define TDLS_CHANNEL_SWITCH_REQ			5
+#define TDLS_CHANNEL_SWITCH_RESP		6
+#define TDLS_PEER_PSM_REQ			7
+#define TDLS_PEER_PSM_RESP			8
+#define TDLS_PEER_TRAFFIC_RESP			9
+#define TDLS_DISCOVERY_REQ			10
+
+/* 802.11z TDLS Public Action Frame action field */
+#define TDLS_DISCOVERY_RESP			14
+
+/* 802.11u GAS action frames */
+#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
+
+/* FTM - fine timing measurement public action frames */
+BWL_PRE_PACKED_STRUCT struct dot11_ftm_req {
+	uint8 category;				/* category of action frame (4) */
+	uint8 action;				/* public action (32) */
+	uint8 trigger;				/* trigger/continue? */
+	/* optional lci, civic loc, ftm params */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ftm_req dot11_ftm_req_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_ftm {
+	uint8 category;				/* category of action frame (4) */
+	uint8 action;				/* public action (33) */
+	uint8 dialog;				/* dialog token */
+	uint8 follow_up;			/* follow up dialog token */
+	uint8 tod[6];				/* t1 - last depart timestamp */
+	uint8 toa[6];				/* t4 - last ack arrival timestamp */
+	uint8 tod_err[2];			/* t1 error */
+	uint8 toa_err[2];			/* t4 error */
+	/* optional lci report, civic loc report, ftm params */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ftm dot11_ftm_t;
+
+
+#define DOT11_FTM_ERR_NOT_CONT_OFFSET 1
+#define DOT11_FTM_ERR_NOT_CONT_MASK 0x80
+#define DOT11_FTM_ERR_NOT_CONT_SHIFT 7
+#define DOT11_FTM_ERR_NOT_CONT(_err) (((_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET] & \
+	DOT11_FTM_ERR_NOT_CONT_MASK) >> DOT11_FTM_ERR_NOT_CONT_SHIFT)
+#define DOT11_FTM_ERR_SET_NOT_CONT(_err, _val) do {\
+	uint8 _err2 = (_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET]; \
+	_err2 &= ~DOT11_FTM_ERR_NOT_CONT_MASK; \
+	_err2 |= ((_val) << DOT11_FTM_ERR_NOT_CONT_SHIFT) & DOT11_FTM_ERR_NOT_CONT_MASK; \
+	(_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET] = _err2; \
+} while (0)
+
+#define DOT11_FTM_ERR_MAX_ERR_OFFSET 0
+#define DOT11_FTM_ERR_MAX_ERR_MASK 0x7fff
+#define DOT11_FTM_ERR_MAX_ERR_SHIFT 0
+#define DOT11_FTM_ERR_MAX_ERR(_err) (((((_err)[1] & 0x7f) << 8) | (_err)[0]))
+#define DOT11_FTM_ERR_SET_MAX_ERR(_err, _val) do {\
+	uint16 _val2; \
+	uint16 _not_cont; \
+	_val2 =  (((_val) & DOT11_FTM_ERR_MAX_ERR_MASK) << DOT11_FTM_ERR_MAX_ERR_SHIFT); \
+	_val2 = (_val2 > 0x3fff) ? 0 : _val2; /* not expecting > 16ns error */ \
+	_not_cont = DOT11_FTM_ERR_NOT_CONT(_err); \
+	(_err)[0] = _val2 & 0xff; \
+	(_err)[1] = (_val2 >> 8) & 0xff; \
+	DOT11_FTM_ERR_SET_NOT_CONT(_err, _not_cont); \
+} while (0)
+
+#if defined(DOT11_FTM_ERR_ROM_COMPAT)
+/* incorrect defs - here for ROM compatibiity */
+#undef DOT11_FTM_ERR_NOT_CONT_OFFSET
+#undef DOT11_FTM_ERR_NOT_CONT_MASK
+#undef DOT11_FTM_ERR_NOT_CONT_SHIFT
+#undef DOT11_FTM_ERR_NOT_CONT
+#undef DOT11_FTM_ERR_SET_NOT_CONT
+
+#define DOT11_FTM_ERR_NOT_CONT_OFFSET 0
+#define DOT11_FTM_ERR_NOT_CONT_MASK 0x0001
+#define DOT11_FTM_ERR_NOT_CONT_SHIFT 0
+#define DOT11_FTM_ERR_NOT_CONT(_err) (((_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET] & \
+	DOT11_FTM_ERR_NOT_CONT_MASK) >> DOT11_FTM_ERR_NOT_CONT_SHIFT)
+#define DOT11_FTM_ERR_SET_NOT_CONT(_err, _val) do {\
+	uint8 _err2 = (_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET]; \
+	_err2 &= ~DOT11_FTM_ERR_NOT_CONT_MASK; \
+	_err2 |= ((_val) << DOT11_FTM_ERR_NOT_CONT_SHIFT) & DOT11_FTM_ERR_NOT_CONT_MASK; \
+	(_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET] = _err2; \
+} while (0)
+
+#undef DOT11_FTM_ERR_MAX_ERR_OFFSET
+#undef DOT11_FTM_ERR_MAX_ERR_MASK
+#undef DOT11_FTM_ERR_MAX_ERR_SHIFT
+#undef DOT11_FTM_ERR_MAX_ERR
+#undef DOT11_FTM_ERR_SET_MAX_ERR
+
+#define DOT11_FTM_ERR_MAX_ERR_OFFSET 0
+#define DOT11_FTM_ERR_MAX_ERR_MASK 0xfff7
+#define DOT11_FTM_ERR_MAX_ERR_SHIFT 1
+#define DOT11_FTM_ERR_MAX_ERR(_err) ((((_err)[1] << 7) | (_err)[0]) >> 1)
+#define DOT11_FTM_ERR_SET_MAX_ERR(_err, _val) do {\
+	uint16 _val2; \
+	_val2 =  (((_val) << DOT11_FTM_ERR_MAX_ERR_SHIFT) |\
+		 ((_err)[DOT11_FTM_ERR_NOT_CONT_OFFSET] & DOT11_FTM_ERR_NOT_CONT_MASK)); \
+	(_err)[0] = _val2 & 0xff; \
+	(_err)[1] = _val2 >> 8 & 0xff; \
+} while (0)
+#endif /* DOT11_FTM_ERR_ROM_COMPAT */
+
+BWL_PRE_PACKED_STRUCT struct dot11_ftm_params {
+	uint8 id;		/* DOT11_MNG_FTM_PARAM_ID 8.4.2.166 11mcd2.6/2014 - revisit */
+	uint8 len;
+	uint8 info[9];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ftm_params dot11_ftm_params_t;
+#define DOT11_FTM_PARAMS_IE_LEN (sizeof(dot11_ftm_params_t) - 2)
+
+#define FTM_PARAMS_FIELD(_p, _off, _mask, _shift) (((_p)->info[(_off)] & (_mask)) >> (_shift))
+#define FTM_PARAMS_SET_FIELD(_p, _off, _mask, _shift, _val) do {\
+	uint8 _ptmp = (_p)->info[_off] & ~(_mask); \
+	(_p)->info[(_off)] = _ptmp | (((_val) << (_shift)) & (_mask)); \
+} while (0)
+
+#define FTM_PARAMS_STATUS_OFFSET 0
+#define FTM_PARAMS_STATUS_MASK 0x03
+#define FTM_PARAMS_STATUS_SHIFT 0
+#define FTM_PARAMS_STATUS(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_STATUS_OFFSET, \
+	FTM_PARAMS_STATUS_MASK, FTM_PARAMS_STATUS_SHIFT)
+#define FTM_PARAMS_SET_STATUS(_p, _status) FTM_PARAMS_SET_FIELD(_p, \
+	FTM_PARAMS_STATUS_OFFSET, FTM_PARAMS_STATUS_MASK, FTM_PARAMS_STATUS_SHIFT, _status)
+
+#define FTM_PARAMS_VALUE_OFFSET 0
+#define FTM_PARAMS_VALUE_MASK 0x7c
+#define FTM_PARAMS_VALUE_SHIFT 2
+#define FTM_PARAMS_VALUE(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_VALUE_OFFSET, \
+	FTM_PARAMS_VALUE_MASK, FTM_PARAMS_VALUE_SHIFT)
+#define FTM_PARAMS_SET_VALUE(_p, _value) FTM_PARAMS_SET_FIELD(_p, \
+	FTM_PARAMS_VALUE_OFFSET, FTM_PARAMS_VALUE_MASK, FTM_PARAMS_VALUE_SHIFT, _value)
+#define FTM_PARAMS_MAX_VALUE 32
+
+#define FTM_PARAMS_NBURSTEXP_OFFSET 1
+#define FTM_PARAMS_NBURSTEXP_MASK 0x0f
+#define FTM_PARAMS_NBURSTEXP_SHIFT 0
+#define FTM_PARAMS_NBURSTEXP(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_NBURSTEXP_OFFSET, \
+	FTM_PARAMS_NBURSTEXP_MASK, FTM_PARAMS_NBURSTEXP_SHIFT)
+#define FTM_PARAMS_SET_NBURSTEXP(_p, _bexp) FTM_PARAMS_SET_FIELD(_p, \
+	FTM_PARAMS_NBURSTEXP_OFFSET, FTM_PARAMS_NBURSTEXP_MASK, FTM_PARAMS_NBURSTEXP_SHIFT, \
+	_bexp)
+
+#define FTM_PARAMS_NBURST(_p) (1 << FTM_PARAMS_NBURSTEXP(_p))
+
+enum {
+	FTM_PARAMS_NBURSTEXP_NOPREF = 15
+};
+
+enum {
+	FTM_PARAMS_BURSTTMO_NOPREF = 15
+};
+
+#define FTM_PARAMS_BURSTTMO_OFFSET 1
+#define FTM_PARAMS_BURSTTMO_MASK 0xf0
+#define FTM_PARAMS_BURSTTMO_SHIFT 4
+#define FTM_PARAMS_BURSTTMO(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_BURSTTMO_OFFSET, \
+	FTM_PARAMS_BURSTTMO_MASK, FTM_PARAMS_BURSTTMO_SHIFT)
+/* set timeout in params using _tmo where timeout = 2^(_tmo) * 250us */
+#define FTM_PARAMS_SET_BURSTTMO(_p, _tmo) FTM_PARAMS_SET_FIELD(_p, \
+	FTM_PARAMS_BURSTTMO_OFFSET, FTM_PARAMS_BURSTTMO_MASK, FTM_PARAMS_BURSTTMO_SHIFT, (_tmo)+2)
+
+#define FTM_PARAMS_BURSTTMO_USEC(_val) ((1 << ((_val)-2)) * 250)
+#define FTM_PARAMS_BURSTTMO_VALID(_val) ((((_val) < 12 && (_val) > 1)) || \
+	(_val) == FTM_PARAMS_BURSTTMO_NOPREF)
+#define FTM_PARAMS_BURSTTMO_MAX_MSEC 128 /* 2^9 * 250us */
+#define FTM_PARAMS_BURSTTMO_MAX_USEC 128000 /* 2^9 * 250us */
+
+#define FTM_PARAMS_MINDELTA_OFFSET 2
+#define FTM_PARAMS_MINDELTA_USEC(_p) ((_p)->info[FTM_PARAMS_MINDELTA_OFFSET] * 100)
+#define FTM_PARAMS_SET_MINDELTA_USEC(_p, _delta) do { \
+	(_p)->info[FTM_PARAMS_MINDELTA_OFFSET] = (_delta) / 100; \
+} while (0)
+
+enum {
+	FTM_PARAMS_MINDELTA_NOPREF = 0
+};
+
+#define FTM_PARAMS_PARTIAL_TSF(_p) ((_p)->info[4] << 8 | (_p)->info[3])
+#define FTM_PARAMS_SET_PARTIAL_TSF(_p, _partial_tsf) do { \
+	(_p)->info[3] = (_partial_tsf) & 0xff; \
+	(_p)->info[4] = ((_partial_tsf) >> 8) & 0xff; \
+} while (0)
+
+#define FTM_PARAMS_PARTIAL_TSF_MASK 0x0000000003fffc00ULL
+#define FTM_PARAMS_PARTIAL_TSF_SHIFT 10
+#define FTM_PARAMS_PARTIAL_TSF_BIT_LEN 16
+#define FTM_PARAMS_PARTIAL_TSF_MAX 0xffff
+
+/* FTM can indicate upto 62k TUs forward and 1k TU backward */
+#define FTM_PARAMS_TSF_FW_HI (63487 << 10)	/* in micro sec */
+#define FTM_PARAMS_TSF_BW_LOW (64512 << 10)	/* in micro sec */
+#define FTM_PARAMS_TSF_BW_HI (65535 << 10)	/* in micro sec */
+#define FTM_PARAMS_TSF_FW_MAX FTM_PARAMS_TSF_FW_HI
+#define FTM_PARAMS_TSF_BW_MAX (FTM_PARAMS_TSF_BW_HI - FTM_PARAMS_TSF_BW_LOW)
+
+#define FTM_PARAMS_PTSFNOPREF_OFFSET 5
+#define FTM_PARAMS_PTSFNOPREF_MASK 0x1
+#define FTM_PARAMS_PTSFNOPREF_SHIFT 0
+#define FTM_PARAMS_PTSFNOPREF(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_PTSFNOPREF_OFFSET, \
+	FTM_PARAMS_PTSFNOPREF_MASK, FTM_PARAMS_PTSFNOPREF_SHIFT)
+#define FTM_PARAMS_SET_PTSFNOPREF(_p, _nopref) FTM_PARAMS_SET_FIELD(_p, \
+	FTM_PARAMS_PTSFNOPREF_OFFSET, FTM_PARAMS_PTSFNOPREF_MASK, \
+	FTM_PARAMS_PTSFNOPREF_SHIFT, _nopref)
+
+#define FTM_PARAMS_ASAP_OFFSET 5
+#define FTM_PARAMS_ASAP_MASK 0x4
+#define FTM_PARAMS_ASAP_SHIFT 2
+#define FTM_PARAMS_ASAP(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_ASAP_OFFSET, \
+	FTM_PARAMS_ASAP_MASK, FTM_PARAMS_ASAP_SHIFT)
+#define FTM_PARAMS_SET_ASAP(_p, _asap) FTM_PARAMS_SET_FIELD(_p, \
+	FTM_PARAMS_ASAP_OFFSET, FTM_PARAMS_ASAP_MASK, FTM_PARAMS_ASAP_SHIFT, _asap)
+
+/* FTM1 - AKA ASAP Capable */
+#define FTM_PARAMS_FTM1_OFFSET 5
+#define FTM_PARAMS_FTM1_MASK 0x02
+#define FTM_PARAMS_FTM1_SHIFT 1
+#define FTM_PARAMS_FTM1(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_FTM1_OFFSET, \
+	FTM_PARAMS_FTM1_MASK, FTM_PARAMS_FTM1_SHIFT)
+#define FTM_PARAMS_SET_FTM1(_p, _ftm1) FTM_PARAMS_SET_FIELD(_p, \
+	FTM_PARAMS_FTM1_OFFSET, FTM_PARAMS_FTM1_MASK, FTM_PARAMS_FTM1_SHIFT, _ftm1)
+
+#define FTM_PARAMS_FTMS_PER_BURST_OFFSET 5
+#define FTM_PARAMS_FTMS_PER_BURST_MASK 0xf8
+#define FTM_PARAMS_FTMS_PER_BURST_SHIFT 3
+#define FTM_PARAMS_FTMS_PER_BURST(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_FTMS_PER_BURST_OFFSET, \
+	FTM_PARAMS_FTMS_PER_BURST_MASK, FTM_PARAMS_FTMS_PER_BURST_SHIFT)
+#define FTM_PARAMS_SET_FTMS_PER_BURST(_p, _nftms) FTM_PARAMS_SET_FIELD(_p, \
+	FTM_PARAMS_FTMS_PER_BURST_OFFSET, FTM_PARAMS_FTMS_PER_BURST_MASK, \
+	FTM_PARAMS_FTMS_PER_BURST_SHIFT, _nftms)
+
+enum {
+	FTM_PARAMS_FTMS_PER_BURST_NOPREF = 0
+};
+
+#define FTM_PARAMS_CHAN_INFO_OFFSET 6
+#define FTM_PARAMS_CHAN_INFO_MASK 0xfc
+#define FTM_PARAMS_CHAN_INFO_SHIFT 2
+#define FTM_PARAMS_CHAN_INFO(_p) FTM_PARAMS_FIELD(_p, FTM_PARAMS_CHAN_INFO_OFFSET, \
+	FTM_PARAMS_CHAN_INFO_MASK, FTM_PARAMS_CHAN_INFO_SHIFT)
+#define FTM_PARAMS_SET_CHAN_INFO(_p, _ci) FTM_PARAMS_SET_FIELD(_p, \
+	FTM_PARAMS_CHAN_INFO_OFFSET, FTM_PARAMS_CHAN_INFO_MASK, FTM_PARAMS_CHAN_INFO_SHIFT, _ci)
+
+/* burst period - units of 100ms */
+#define FTM_PARAMS_BURST_PERIOD(_p) (((_p)->info[8] << 8) | (_p)->info[7])
+#define FTM_PARAMS_SET_BURST_PERIOD(_p, _bp) do {\
+	(_p)->info[7] = (_bp) & 0xff; \
+	(_p)->info[8] = ((_bp) >> 8) & 0xff; \
+} while (0)
+
+#define FTM_PARAMS_BURST_PERIOD_MS(_p) (FTM_PARAMS_BURST_PERIOD(_p) * 100)
+
+enum {
+	FTM_PARAMS_BURST_PERIOD_NOPREF = 0
+};
+
+/* FTM status values - last updated from 11mcD4.0 */
+enum {
+	FTM_PARAMS_STATUS_RESERVED	= 0,
+	FTM_PARAMS_STATUS_SUCCESSFUL = 1,
+	FTM_PARAMS_STATUS_INCAPABLE = 2,
+	FTM_PARAMS_STATUS_FAILED = 3,
+	/* Below are obsolte */
+	FTM_PARAMS_STATUS_OVERRIDDEN = 4,
+	FTM_PARAMS_STATUS_ASAP_INCAPABLE = 5,
+	FTM_PARAMS_STATUS_ASAP_FAILED = 6,
+	/* rest are reserved */
+};
+
+enum {
+	FTM_PARAMS_CHAN_INFO_NO_PREF 		= 0,
+	FTM_PARAMS_CHAN_INFO_RESERVE1 		= 1,
+	FTM_PARAMS_CHAN_INFO_RESERVE2 		= 2,
+	FTM_PARAMS_CHAN_INFO_RESERVE3 		= 3,
+	FTM_PARAMS_CHAN_INFO_NON_HT_5 		= 4,
+	FTM_PARAMS_CHAN_INFO_RESERVE5		= 5,
+	FTM_PARAMS_CHAN_INFO_NON_HT_10 		= 6,
+	FTM_PARAMS_CHAN_INFO_RESERVE7		= 7,
+	FTM_PARAMS_CHAN_INFO_NON_HT_20 		= 8, /* excludes 2.4G, and High rate DSSS */
+	FTM_PARAMS_CHAN_INFO_HT_MF_20 		= 9,
+	FTM_PARAMS_CHAN_INFO_VHT_20 		= 10,
+	FTM_PARAMS_CHAN_INFO_HT_MF_40 		= 11,
+	FTM_PARAMS_CHAN_INFO_VHT_40 		= 12,
+	FTM_PARAMS_CHAN_INFO_VHT_80 		= 13,
+	FTM_PARAMS_CHAN_INFO_VHT_80_80 		= 14,
+	FTM_PARAMS_CHAN_INFO_VHT_160_2_RFLOS 	= 15,
+	FTM_PARAMS_CHAN_INFO_VHT_160		= 16,
+	/* Reserved from 17 - 30 */
+	FTM_PARAMS_CHAN_INFO_DMG_2160 		= 31,
+	/* Reserved from 32 - 63 */
+	FTM_PARAMS_CHAN_INFO_MAX		= 63
+};
+
+/* tag_ID/length/value_buffer tuple */
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint8	id;
+	uint8	len;
+	uint8	data[1];
+} BWL_POST_PACKED_STRUCT ftm_vs_tlv_t;
+
+BWL_PRE_PACKED_STRUCT struct dot11_ftm_vs_ie {
+	uint8 id;						/* DOT11_MNG_VS_ID */
+	uint8 len;						/* length following */
+	uint8 oui[3];					/* BRCM_PROP_OUI (or Customer) */
+	uint8 sub_type;					/* BRCM_FTM_IE_TYPE (or Customer) */
+	uint8 version;
+	ftm_vs_tlv_t	tlvs[1];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ftm_vs_ie dot11_ftm_vs_ie_t;
+
+/* ftm vs api version */
+#define BCM_FTM_VS_PARAMS_VERSION 0x01
+
+/* ftm vendor specific information tlv types */
+enum {
+	FTM_VS_TLV_NONE = 0,
+	FTM_VS_TLV_REQ_PARAMS = 1,		/* additional request params (in FTM_REQ) */
+	FTM_VS_TLV_MEAS_INFO = 2,		/* measurement information (in FTM_MEAS) */
+	FTM_VS_TLV_SEC_PARAMS = 3,		/* security parameters (in either) */
+	FTM_VS_TLV_SEQ_PARAMS = 4,		/* toast parameters (FTM_REQ, BRCM proprietary) */
+	FTM_VS_TLV_MF_BUF = 5,			/* multi frame buffer - may span ftm vs ie's */
+	/* add additional types above */
+};
+
+/* the following definitions are *DEPRECATED* and moved to implemenetion files. They
+ * are retained here because previous (May 2016) some branches use them
+ */
+#define FTM_TPK_LEN            16
+#define FTM_RI_RR_BUF_LEN      32
+#define FTM_TPK_RI_RR_LEN      13
+#define FTM_TPK_DIGEST_LEN     32
+#define FTM_TPK_BUFFER_LEN     128
+#define FTM_TPK_RI_PHY_LEN     7
+#define FTM_TPK_RR_PHY_LEN     7
+#define FTM_TPK_DATA_BUFFER_LEN 88
+
+BWL_PRE_PACKED_STRUCT struct dot11_ftm_vs_params {
+	uint8 id;                       /* DOT11_MNG_VS_ID */
+	uint8 len;
+	uint8 oui[3];                   /* Proprietary OUI, BRCM_PROP_OUI */
+	uint8 bcm_vs_id;
+	ftm_vs_tlv_t ftm_tpk_ri_rr[1];          /* ftm_TPK_ri_rr place holder */
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ftm_vs_params dot11_ftm_vs_tpk_ri_rr_params_t;
+#define DOT11_FTM_VS_LEN  (sizeof(dot11_ftm_vs_tpk_ri_rr_params_t) - TLV_HDR_LEN)
+/* end *DEPRECATED* ftm definitions */
+
+BWL_PRE_PACKED_STRUCT struct dot11_ftm_sync_info {
+	uint8 id;		/* Extended - 255 11mc D4.3  */
+	uint8 len;
+	uint8 id_ext;
+	uint8 tsf_sync_info[4];
+} BWL_POST_PACKED_STRUCT;
+typedef struct dot11_ftm_sync_info dot11_ftm_sync_info_t;
+
+/* ftm tsf sync info ie len - includes id ext */
+#define DOT11_FTM_SYNC_INFO_IE_LEN (sizeof(dot11_ftm_sync_info_t) - TLV_HDR_LEN)
+
+#define DOT11_FTM_IS_SYNC_INFO_IE(_ie) (\
+	DOT11_MNG_IE_ID_EXT_MATCH(_ie, DOT11_MNG_FTM_SYNC_INFO) && \
+	(_ie)->len == DOT11_FTM_SYNC_INFO_IE_LEN)
+
+/* 802.11u interworking access network options */
+#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
+
+/* 802.11u interworking access network type */
+#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 IW_ANT_LEN			1
+#define IW_VENUE_LEN			2
+#define IW_HESSID_LEN			6
+#define IW_HESSID_OFF			(IW_ANT_LEN + IW_VENUE_LEN)
+#define IW_MAX_LEN			(IW_ANT_LEN + IW_VENUE_LEN + IW_HESSID_LEN)
+
+/* 802.11u advertisement protocol */
+#define ADVP_ANQP_PROTOCOL_ID				0
+#define ADVP_MIH_PROTOCOL_ID				1
+
+/* 802.11u advertisement protocol masks */
+#define ADVP_QRL_MASK					0x7f
+#define ADVP_PAME_BI_MASK				0x80
+
+/* 802.11u advertisement protocol values */
+#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
+
+/* 802.11u ANQP information ID */
+#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
+
+/* 802.11u ANQP OUI */
+#define ANQP_OUI_SUBTYPE				9
+
+/* 802.11u venue name */
+#define VENUE_LANGUAGE_CODE_SIZE			3
+#define VENUE_NAME_SIZE					255
+
+/* 802.11u venue groups */
+#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
+
+/* 802.11u network authentication type indicator */
+#define NATI_UNSPECIFIED				-1
+#define NATI_ACCEPTANCE_OF_TERMS_CONDITIONS		0
+#define NATI_ONLINE_ENROLLMENT_SUPPORTED		1
+#define NATI_HTTP_HTTPS_REDIRECTION			2
+#define NATI_DNS_REDIRECTION				3
+
+/* 802.11u IP address type availability - IPv6 */
+#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
+
+/* 802.11u IP address type availability - IPv4 */
+#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
+
+/* 802.11u NAI realm encoding */
+#define REALM_ENCODING_RFC4282				0
+#define REALM_ENCODING_UTF8				1
+
+/* 802.11u IANA EAP method type numbers */
+#define REALM_EAP_TLS					13
+#define REALM_EAP_LEAP					17
+#define REALM_EAP_SIM					18
+#define REALM_EAP_TTLS					21
+#define REALM_EAP_AKA					23
+#define REALM_EAP_PEAP					25
+#define REALM_EAP_FAST					43
+#define REALM_EAP_PSK					47
+#define REALM_EAP_AKAP					50
+#define REALM_EAP_EXPANDED				254
+
+/* 802.11u authentication ID */
+#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
+
+/* 802.11u non-EAP inner authentication type */
+#define REALM_RESERVED_AUTH				0
+#define REALM_PAP					1
+#define REALM_CHAP					2
+#define REALM_MSCHAP					3
+#define REALM_MSCHAPV2					4
+
+/* 802.11u credential type */
+#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 REALM_RESERVED_CRED				9
+#define REALM_VENDOR_SPECIFIC_CRED			10
+
+/* 802.11u 3GPP PLMN */
+#define G3PP_GUD_VERSION				0
+#define G3PP_PLMN_LIST_IE				0
+
+/** hotspot2.0 indication element (vendor specific) */
+BWL_PRE_PACKED_STRUCT struct hs20_ie {
+	uint8 oui[3];
+	uint8 type;
+	uint8 config;
+} BWL_POST_PACKED_STRUCT;
+typedef struct hs20_ie hs20_ie_t;
+#define HS20_IE_LEN 5	/* HS20 IE length */
+
+/** IEEE 802.11 Annex E */
+typedef enum {
+	DOT11_2GHZ_20MHZ_CLASS_12	= 81,	/* Ch 1-11 */
+	DOT11_5GHZ_20MHZ_CLASS_1	= 115,	/* Ch 36-48 */
+	DOT11_5GHZ_20MHZ_CLASS_2_DFS	= 118,	/* Ch 52-64 */
+	DOT11_5GHZ_20MHZ_CLASS_3	= 124,	/* Ch 149-161 */
+	DOT11_5GHZ_20MHZ_CLASS_4_DFS	= 121,	/* Ch 100-140 */
+	DOT11_5GHZ_20MHZ_CLASS_5	= 125,	/* Ch 149-165 */
+	DOT11_5GHZ_40MHZ_CLASS_22	= 116,	/* Ch 36-44,   lower */
+	DOT11_5GHZ_40MHZ_CLASS_23_DFS 	= 119,	/* Ch 52-60,   lower */
+	DOT11_5GHZ_40MHZ_CLASS_24_DFS	= 122,	/* Ch 100-132, lower */
+	DOT11_5GHZ_40MHZ_CLASS_25	= 126,	/* Ch 149-157, lower */
+	DOT11_5GHZ_40MHZ_CLASS_27	= 117,	/* Ch 40-48,   upper */
+	DOT11_5GHZ_40MHZ_CLASS_28_DFS	= 120,	/* Ch 56-64,   upper */
+	DOT11_5GHZ_40MHZ_CLASS_29_DFS	= 123,	/* Ch 104-136, upper */
+	DOT11_5GHZ_40MHZ_CLASS_30	= 127,	/* Ch 153-161, upper */
+	DOT11_2GHZ_40MHZ_CLASS_32	= 83,	/* Ch 1-7,     lower */
+	DOT11_2GHZ_40MHZ_CLASS_33	= 84,	/* Ch 5-11,    upper */
+} dot11_op_class_t;
+
+/* QoS map */
+#define QOS_MAP_FIXED_LENGTH	(8 * 2)	/* DSCP ranges fixed with 8 entries */
+
+#define BCM_AIBSS_IE_TYPE 56
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _802_11_H_ */
diff --git a/wl/components/shared/proto/802.11ah.h b/wl/components/shared/proto/802.11ah.h
new file mode 100644
index 0000000..1637d31
--- /dev/null
+++ b/wl/components/shared/proto/802.11ah.h
@@ -0,0 +1,175 @@
+/*
+ * Basic types and constants relating to 802.11ah standard.
+ * This is a portion of 802.11ah definition. The rest are in 802.11.h.
+ *
+ * Copyright (C) 2017, Broadcom. 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: 802.11ah.h 627195 2016-03-24 00:57:47Z $
+ */
+
+#ifndef _802_11ah_h_
+#define _802_11ah_h_
+
+#include <typedefs.h>
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/**
+ * TWT IE (sec 8.4.2.196)
+ */
+
+/* TWT element - top */
+BWL_PRE_PACKED_STRUCT struct twt_ie_top {
+	uint8 id;
+	uint8 len;
+	uint8 ctrl;		/* Control */
+	uint16 req_type;	/* Request Type */
+} BWL_POST_PACKED_STRUCT;
+
+typedef struct twt_ie_top twt_ie_top_t;
+
+/* Control field (figure 8-557ax) */
+#define TWT_CTRL_NDP_PAGING_IND	0x01	/* NDP Paging Indication */
+#define TWT_CTRL_RESP_PM_MODE	0x02	/* Respondor PM Mode */
+#define TWT_CTRL_BCAST		0x04	/* Broadcast */
+
+/* Requestor Type field (figure 8-557ay) */
+#define TWT_REQ_TYPE_REQUEST		0x0001	/* Request */
+#define TWT_REQ_TYPE_SETUP_CMD_MASK	0x000e	/* Setup Command */
+#define TWT_REQ_TYPE_SETUP_CMD_SHIFT	1
+#define TWT_REQ_TYPE_TRIGGER		0x0010	/* Trigger */
+#define TWT_REQ_TYPE_IMPLICIT		0x0020	/* Implicit */
+#define TWT_REQ_TYPE_FLOW_TYPE		0x0040	/* Flow Type */
+#define TWT_REQ_TYPE_FLOW_ID_MASK	0x0380	/* Flow Identifier */
+#define TWT_REQ_TYPE_FLOW_ID_SHIFT	7
+#define TWT_REQ_TYPE_WAKE_EXP_MASK	0x7c00	/* Wake Interval Exponent */
+#define TWT_REQ_TYPE_WAKE_EXP_SHIFT	10
+#define TWT_REQ_TYPE_PROTECTION		0x8000	/* Protection */
+
+/* Setup Command field (table 8-248I) */
+#define TWT_SETUP_CMD_REQUEST_TWT	0	/* Request TWT */
+#define TWT_SETUP_CMD_SUGGEST_TWT	1	/* Suggest TWT */
+#define TWT_SETUP_CMD_DEMAND_TWT	2	/* Demand TWT */
+#define TWT_SETUP_CMD_GRPING_TWT	3	/* Grouping TWT */
+#define TWT_SETUP_CMD_ACCEPT_TWT	4	/* Accept TWT */
+#define TWT_SETUP_CMD_ALTER_TWT		5	/* Alternate TWT */
+#define TWT_SETUP_CMD_DICTATE_TWT	6	/* Dictate TWT */
+#define TWT_SETUP_CMD_REJECT_TWT	7	/* Reject TWT */
+
+/* Flow Identifier field (table 8-248I1) */
+#define TWT_BCAST_FLOW_ID_NO_CONSTRAINS	0	/* No constrains on the frame transmitted during
+						 * a broadcast TWT SP.
+						 */
+#define TWT_BCAST_FLOW_ID_NO_RAND_RU	1	/* Do not contain RUs for random access */
+#define TWT_BCAST_FLOW_ID_RAND_RU	2	/* Contain RUs for random access */
+
+/* Target Wake Time - 8 octets or 0 octet */
+typedef uint64 twt_target_wake_time_t;	/* 64 bit TSF time of TWT Responding STA */
+
+/* TWT Group Assignment Info - 9 octets (long format) or 3 octets (short format) or 0 octet */
+/* Group Assignment Info field - short format - Zero Offset Preset field is 0 */
+BWL_PRE_PACKED_STRUCT struct twt_grp_short {
+	uint8 grpid_n_0off;	/* Group ID and Zero Offset Present */
+	uint16 unit_n_off;	/* TWT Unit and TWT Offset */
+} BWL_POST_PACKED_STRUCT;
+
+typedef struct twt_grp_short twt_grp_short_t;
+
+/* Group Assignment Info field - long format - Zero Offset Preset field is 1 */
+#define TWT_ZERO_OFF_GRP_LEN 6
+BWL_PRE_PACKED_STRUCT struct twt_grp_long {
+	uint8 grpid_n_0off;	/* Group ID and Zero Offset Present */
+	uint8 grp_0off[TWT_ZERO_OFF_GRP_LEN];	/* Zero Offset of Group */
+	uint16 unit_n_off;	/* Unit and Offset */
+} BWL_POST_PACKED_STRUCT;
+
+typedef struct twt_grp_long twt_grp_long_t;
+
+/* TWT Unit and TWT Offset field */
+#define TWT_UNIT_MASK		0x000f		/* TWT Unit */
+#define TWT_OFFSET_MASK		0xfff0		/* TWT Offset */
+#define TWT_OFFSET_SHIFT	4
+
+/* TWT Unit field (table 8-248m) */
+#define TWT_UNIT_32us		0
+#define TWT_UNIT_256us		1
+#define TWT_UNIT_1024us		2
+#define TWT_UNIT_8ms192us	3
+#define TWT_UNIT_32ms768us	4
+#define TWT_UNIT_262ms144us	5
+#define TWT_UNIT_1s048576us	6
+#define TWT_UNIT_8s388608us	7
+#define TWT_UNIT_33s554432us	8
+#define TWT_UNIT_268s435456us	9
+#define TWT_UNIT_1073s741824us	10
+#define TWT_UNIT_8589s934592us	11
+
+/* TWT element - bottom */
+BWL_PRE_PACKED_STRUCT struct twt_ie_bottom {
+	uint8 nom_wake_dur;		/* Nominal Minimum Wake Duration */
+	uint16 wake_int_mant;		/* TWT Wake Interval Mantissa */
+	uint8 channel;			/* TWT Channel */
+	/* NDP Paging field */
+} BWL_POST_PACKED_STRUCT;
+
+typedef struct twt_ie_bottom twt_ie_bottom_t;
+
+/* Nominal Minimum Wake Duration */
+#define TWT_NOM_WAKE_DUR_UNIT	256	/* Nominal Minimum Wake Duration is in 256us units */
+
+/* NDP Paging field - 4 octets or 0 octet */
+typedef uint32 twt_ndp_paging_t;
+
+#define TWT_NDP_PAGING_PID		0x000001ff	/* P-ID */
+#define TWT_NDP_PAGING_MAX_PERIOD	0x0001fe00	/* Max NDP Paging Period */
+#define TWT_NDP_PAGING_PART_TSF_OFF	0x001e0000	/* Partial TSF Offset */
+#define TWT_NDP_PAGING_ACTION		0x00e00000	/* Action */
+#define TWT_NDP_PAGING_MIN_SLEEP	0x3f000000	/* Min Sleep Duration */
+
+/* Action field (table 8-248n) */
+#define TWT_ACTION_SEND_PSP_TRIG	0	/* Send a PS-Poll or uplink trigger frame */
+#define TWT_ACTION_WAKE_MIN_SLEEP	1	/* Wake up at the time indicated by
+						 * Min Sleep Duration
+						 */
+#define TWT_ACTION_WAKE_RCV_BCN		2	/* Wake up to receive the Beacon */
+#define TWT_ACTION_WAKE_RCV_DTIM	3	/* Wake up to receive the DTIM Beacon */
+#define TWT_ACTION_WAKE_IND_TIME	4	/* Wakeup at the time indicated by the sum of
+						 * the Min Sleep Duration field and the ASD subfield
+						 * in the APDI field of the NDP Paging frame
+						 */
+
+/* TWT Teardown Flow field */
+#define TWT_TEARDOWN_FLOW_ID_MASK	0x07
+
+/* TWT Information field byte 0 */
+#define TWT_INFO_FLOW_ID_MASK		0x07
+#define TWT_INFO_RESP_REQ		0x08
+#define TWT_INFO_NEXT_TWT_REQ		0x10
+#define TWT_INFO_NEXT_TWT_SIZE_MASK	0x60
+#define TWT_INFO_NEXT_TWT_SIZE_SHIFT	0x5
+
+/* Next TWT Subfield Size field */
+#define TWT_INFO_NEXT_TWT_SIZE_0	0	/* 0 byte */
+#define TWT_INFO_NEXT_TWT_SIZE_32	1	/* 4 bytes */
+#define TWT_INFO_NEXT_TWT_SIZE_48	2	/* 6 bytes */
+#define TWT_INFO_NEXT_TWT_SIZE_64	3	/* 8 bytes */
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _802_11ah_h_ */
diff --git a/wl/components/shared/proto/802.11e.h b/wl/components/shared/proto/802.11e.h
new file mode 100644
index 0000000..ff479be
--- /dev/null
+++ b/wl/components/shared/proto/802.11e.h
@@ -0,0 +1,128 @@
+/*
+ * 802.11e protocol header file
+ *
+ * Copyright (C) 2017, Broadcom. 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: 802.11e.h 572688 2015-07-20 17:49:21Z $
+ */
+
+#ifndef _802_11e_H_
+#define _802_11e_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/* WME Traffic Specification (TSPEC) element */
+#define WME_TSPEC_HDR_LEN           2           /* WME TSPEC header length */
+#define WME_TSPEC_BODY_OFF          2           /* WME TSPEC body offset */
+
+#define WME_CATEGORY_CODE_OFFSET	0		/* WME Category code offset */
+#define WME_ACTION_CODE_OFFSET		1		/* WME Action code offset */
+#define WME_TOKEN_CODE_OFFSET		2		/* WME Token code offset */
+#define WME_STATUS_CODE_OFFSET		3		/* WME Status code offset */
+
+BWL_PRE_PACKED_STRUCT struct tsinfo {
+	uint8 octets[3];
+} BWL_POST_PACKED_STRUCT;
+
+typedef struct tsinfo tsinfo_t;
+
+/* 802.11e TSPEC IE */
+typedef BWL_PRE_PACKED_STRUCT struct tspec {
+	uint8 oui[DOT11_OUI_LEN];	/* WME_OUI */
+	uint8 type;					/* WME_TYPE */
+	uint8 subtype;				/* WME_SUBTYPE_TSPEC */
+	uint8 version;				/* WME_VERSION */
+	tsinfo_t tsinfo;			/* TS Info bit field */
+	uint16 nom_msdu_size;		/* (Nominal or fixed) MSDU Size (bytes) */
+	uint16 max_msdu_size;		/* Maximum MSDU Size (bytes) */
+	uint32 min_srv_interval;	/* Minimum Service Interval (us) */
+	uint32 max_srv_interval;	/* Maximum Service Interval (us) */
+	uint32 inactivity_interval;	/* Inactivity Interval (us) */
+	uint32 suspension_interval; /* Suspension Interval (us) */
+	uint32 srv_start_time;		/* Service Start Time (us) */
+	uint32 min_data_rate;		/* Minimum Data Rate (bps) */
+	uint32 mean_data_rate;		/* Mean Data Rate (bps) */
+	uint32 peak_data_rate;		/* Peak Data Rate (bps) */
+	uint32 max_burst_size;		/* Maximum Burst Size (bytes) */
+	uint32 delay_bound;			/* Delay Bound (us) */
+	uint32 min_phy_rate;		/* Minimum PHY Rate (bps) */
+	uint16 surplus_bw;			/* Surplus Bandwidth Allowance (range 1.0-8.0) */
+	uint16 medium_time;			/* Medium Time (32 us/s periods) */
+} BWL_POST_PACKED_STRUCT tspec_t;
+
+#define WME_TSPEC_LEN	(sizeof(tspec_t))		/* not including 2-bytes of header */
+
+/* ts_info */
+/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */
+#define TS_INFO_TID_SHIFT		1	/* TS info. TID shift */
+#define TS_INFO_TID_MASK		(0xf << TS_INFO_TID_SHIFT)	/* TS info. TID mask */
+#define TS_INFO_CONTENTION_SHIFT	7	/* TS info. contention shift */
+#define TS_INFO_CONTENTION_MASK	(0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */
+#define TS_INFO_DIRECTION_SHIFT	5	/* TS info. direction shift */
+#define TS_INFO_DIRECTION_MASK	(0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */
+#define TS_INFO_PSB_SHIFT		2		/* TS info. PSB bit Shift */
+#define TS_INFO_PSB_MASK		(1 << TS_INFO_PSB_SHIFT)	/* TS info. PSB mask */
+#define TS_INFO_UPLINK			(0 << TS_INFO_DIRECTION_SHIFT)	/* TS info. uplink */
+#define TS_INFO_DOWNLINK		(1 << TS_INFO_DIRECTION_SHIFT)	/* TS info. downlink */
+#define TS_INFO_BIDIRECTIONAL	(3 << TS_INFO_DIRECTION_SHIFT)	/* TS info. bidirectional */
+#define TS_INFO_USER_PRIO_SHIFT	3	/* TS info. user priority shift */
+/* TS info. user priority mask */
+#define TS_INFO_USER_PRIO_MASK	(0x7 << TS_INFO_USER_PRIO_SHIFT)
+
+/* Macro to get/set bit(s) field in TSINFO */
+#define WLC_CAC_GET_TID(pt)	((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT)
+#define WLC_CAC_GET_DIR(pt)	((((pt).octets[0]) & \
+	TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT)
+#define WLC_CAC_GET_PSB(pt)	((((pt).octets[1]) & TS_INFO_PSB_MASK) >> TS_INFO_PSB_SHIFT)
+#define WLC_CAC_GET_USER_PRIO(pt)	((((pt).octets[1]) & \
+	TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT)
+
+#define WLC_CAC_SET_TID(pt, id)	((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \
+	((id) << TS_INFO_TID_SHIFT))
+#define WLC_CAC_SET_USER_PRIO(pt, prio)	((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \
+	((prio) << TS_INFO_USER_PRIO_SHIFT))
+
+/* 802.11e QBSS Load IE */
+#define QBSS_LOAD_IE_LEN		5	/* QBSS Load IE length */
+#define QBSS_LOAD_AAC_OFF		3	/* AAC offset in IE */
+
+#define CAC_ADDTS_RESP_TIMEOUT		1000	/* default ADDTS response timeout in ms */
+						/* DEFVAL dot11ADDTSResponseTimeout = 1s */
+
+/* 802.11e ADDTS status code */
+#define DOT11E_STATUS_ADMISSION_ACCEPTED	0	/* TSPEC Admission accepted status */
+#define DOT11E_STATUS_ADDTS_INVALID_PARAM	1	/* TSPEC invalid parameter status */
+#define DOT11E_STATUS_ADDTS_REFUSED_NSBW	3	/* ADDTS refused (non-sufficient BW) */
+#define DOT11E_STATUS_ADDTS_REFUSED_AWHILE	47	/* ADDTS refused but could retry later */
+
+/* 802.11e DELTS status code */
+#define DOT11E_STATUS_QSTA_LEAVE_QBSS		36	/* STA leave QBSS */
+#define DOT11E_STATUS_END_TS				37	/* END TS */
+#define DOT11E_STATUS_UNKNOWN_TS			38	/* UNKNOWN TS */
+#define DOT11E_STATUS_QSTA_REQ_TIMEOUT		39	/* STA ADDTS request timeout */
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _802_11e_CAC_H_ */
diff --git a/wl/components/shared/proto/802.1d.h b/wl/components/shared/proto/802.1d.h
new file mode 100644
index 0000000..559dcff
--- /dev/null
+++ b/wl/components/shared/proto/802.1d.h
@@ -0,0 +1,47 @@
+/*
+ * Fundamental types and constants relating to 802.1D
+ *
+ * Copyright (C) 2017, Broadcom. 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: 802.1d.h 518342 2014-12-01 23:21:41Z $
+ */
+
+#ifndef _802_1_D_
+#define _802_1_D_
+
+/* 802.1D priority defines */
+#define	PRIO_8021D_NONE		2	/* None = - */
+#define	PRIO_8021D_BK		1	/* BK - Background */
+#define	PRIO_8021D_BE		0	/* BE - Best-effort */
+#define	PRIO_8021D_EE		3	/* EE - Excellent-effort */
+#define	PRIO_8021D_CL		4	/* CL - Controlled Load */
+#define	PRIO_8021D_VI		5	/* Vi - Video */
+#define	PRIO_8021D_VO		6	/* Vo - Voice */
+#define	PRIO_8021D_NC		7	/* NC - Network Control */
+#define	MAXPRIO			7	/* 0-7 */
+#define NUMPRIO			(MAXPRIO + 1)
+
+#define ALLPRIO		-1	/* All prioirty */
+
+/* Converts prio to precedence since the numerical value of
+ * PRIO_8021D_BE and PRIO_8021D_NONE are swapped.
+ */
+#define PRIO2PREC(prio) \
+	(((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio))
+
+#endif /* _802_1_D__ */
diff --git a/wl/components/shared/proto/802.3.h b/wl/components/shared/proto/802.3.h
new file mode 100644
index 0000000..c759d2b
--- /dev/null
+++ b/wl/components/shared/proto/802.3.h
@@ -0,0 +1,49 @@
+/*
+ * Fundamental constants relating to 802.3
+ *
+ * Copyright (C) 2017, Broadcom. 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: 802.3.h 518342 2014-12-01 23:21:41Z $
+ */
+
+#ifndef _802_3_h_
+#define _802_3_h_
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#define SNAP_HDR_LEN	6	/* 802.3 SNAP header length */
+#define DOT3_OUI_LEN	3	/* 802.3 oui length */
+
+BWL_PRE_PACKED_STRUCT struct dot3_mac_llc_snap_header {
+	uint8	ether_dhost[ETHER_ADDR_LEN];	/* dest mac */
+	uint8	ether_shost[ETHER_ADDR_LEN];	/* src mac */
+	uint16	length;				/* frame length incl header */
+	uint8	dsap;				/* always 0xAA */
+	uint8	ssap;				/* always 0xAA */
+	uint8	ctl;				/* always 0x03 */
+	uint8	oui[DOT3_OUI_LEN];		/* RFC1042: 0x00 0x00 0x00
+						 * Bridge-Tunnel: 0x00 0x00 0xF8
+						 */
+	uint16	type;				/* ethertype */
+} BWL_POST_PACKED_STRUCT;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif	/* #ifndef _802_3_h_ */
diff --git a/wl/components/shared/proto/bcmeth.h b/wl/components/shared/proto/bcmeth.h
new file mode 100644
index 0000000..4488807
--- /dev/null
+++ b/wl/components/shared/proto/bcmeth.h
@@ -0,0 +1,110 @@
+/*
+ * Broadcom Ethernettype  protocol definitions
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmeth.h 565501 2015-06-22 14:29:02Z $
+ */
+
+/*
+ * Broadcom Ethernet protocol defines
+ */
+
+#ifndef _BCMETH_H_
+#define _BCMETH_H_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/* ETHER_TYPE_BRCM is defined in ethernet.h */
+
+/*
+ * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field
+ * in one of two formats: (only subtypes 32768-65535 are in use now)
+ *
+ * subtypes 0-32767:
+ *     8 bit subtype (0-127)
+ *     8 bit length in bytes (0-255)
+ *
+ * subtypes 32768-65535:
+ *     16 bit big-endian subtype
+ *     16 bit big-endian length in bytes (0-65535)
+ *
+ * length is the number of additional bytes beyond the 4 or 6 byte header
+ *
+ * Reserved values:
+ * 0 reserved
+ * 5-15 reserved for iLine protocol assignments
+ * 17-126 reserved, assignable
+ * 127 reserved
+ * 32768 reserved
+ * 32769-65534 reserved, assignable
+ * 65535 reserved
+ */
+
+/*
+ * While adding the subtypes and their specific processing code make sure
+ * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition
+ */
+
+#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
+/*
+ * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded
+ * within BCMILCP_BCM_SUBTYPE_EVENT type messages
+ */
+/* #define BCMILCP_BCM_SUBTYPE_EAPOL		3 */
+#define BCMILCP_BCM_SUBTYPE_DPT                 4
+#define BCMILCP_BCM_SUBTYPE_DNGLEVENT       5
+
+#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH	8
+#define BCMILCP_BCM_SUBTYPEHDR_VERSION		0
+
+/* These fields are stored in network order */
+typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr
+{
+	uint16	subtype;	/* Vendor specific..32769 */
+	uint16	length;
+	uint8	version;	/* Version is 0 */
+	uint8	oui[3];		/* Broadcom OUI */
+	/* user specific Data */
+	uint16	usr_subtype;
+} BWL_POST_PACKED_STRUCT bcmeth_hdr_t;
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif	/*  _BCMETH_H_ */
diff --git a/wl/components/shared/proto/bcmevent.h b/wl/components/shared/proto/bcmevent.h
new file mode 100644
index 0000000..8fe52d1
--- /dev/null
+++ b/wl/components/shared/proto/bcmevent.h
@@ -0,0 +1,845 @@
+/*
+ * Broadcom Event  protocol definitions
+ *
+ * Dependencies: proto/bcmeth.h
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmevent.h 663597 2017-01-18 18:10:05Z $
+ *
+ */
+
+/*
+ * Broadcom Ethernet Events protocol defines
+ *
+ */
+
+#ifndef _BCMEVENT_H_
+#define _BCMEVENT_H_
+
+#include <typedefs.h>
+/* #include <ethernet.h> -- TODO: req., excluded to overwhelming coupling (break up ethernet.h) */
+#include <proto/bcmeth.h>
+#if defined(HEALTH_CHECK) || defined(DNGL_EVENT_SUPPORT)
+#include <proto/dnglevent.h>
+#endif /* HEALTH_CHECK || DNGL_EVENT_SUPPORT */
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#define BCM_EVENT_MSG_VERSION		2	/* wl_event_msg_t struct version */
+#define BCM_MSG_IFNAME_MAX		16	/* max length of interface name */
+
+/* flags */
+#define WLC_EVENT_MSG_LINK		0x01	/* link is up */
+#define WLC_EVENT_MSG_FLUSHTXQ		0x02	/* flush tx queue on MIC error */
+#define WLC_EVENT_MSG_GROUP		0x04	/* group MIC error */
+#define WLC_EVENT_MSG_UNKBSS		0x08	/* unknown source bsscfg */
+#define WLC_EVENT_MSG_UNKIF		0x10	/* unknown source OS i/f */
+
+/* these fields are stored in network order */
+
+/* version 1 */
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+	uint16	version;
+	uint16	flags;			/* see flags below */
+	uint32	event_type;		/* Message (see below) */
+	uint32	status;			/* Status code (see below) */
+	uint32	reason;			/* Reason code (if applicable) */
+	uint32	auth_type;		/* WLC_E_AUTH */
+	uint32	datalen;		/* data buf */
+	struct ether_addr	addr;	/* Station address (if applicable) */
+	char	ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */
+} BWL_POST_PACKED_STRUCT wl_event_msg_v1_t;
+
+/* the current version */
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+	uint16	version;
+	uint16	flags;			/* see flags below */
+	uint32	event_type;		/* Message (see below) */
+	uint32	status;			/* Status code (see below) */
+	uint32	reason;			/* Reason code (if applicable) */
+	uint32	auth_type;		/* WLC_E_AUTH */
+	uint32	datalen;		/* data buf */
+	struct ether_addr	addr;	/* Station address (if applicable) */
+	char	ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */
+	uint8	ifidx;			/* destination OS i/f index */
+	uint8	bsscfgidx;		/* source bsscfg index */
+} BWL_POST_PACKED_STRUCT wl_event_msg_t;
+
+/* used by driver msgs */
+typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
+	struct ether_header eth;
+	bcmeth_hdr_t		bcm_hdr;
+	wl_event_msg_t		event;
+	/* data portion follows */
+} BWL_POST_PACKED_STRUCT bcm_event_t;
+
+/*
+ * used by host event
+ * note: if additional event types are added, it should go with is_wlc_event_frame() as well.
+ */
+typedef union bcm_event_msg_u {
+	wl_event_msg_t		event;
+#if defined(HEALTH_CHECK) || defined(DNGL_EVENT_SUPPORT)
+	bcm_dngl_event_msg_t	dngl_event;
+#endif /* HEALTH_CHECK || DNGL_EVENT_SUPPORT */
+
+	/* add new event here */
+} bcm_event_msg_u_t;
+
+#define BCM_MSG_LEN	(sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header))
+
+/* Event messages */
+#define WLC_E_SET_SSID		0	/* indicates status of set SSID */
+#define WLC_E_JOIN		1	/* differentiates join IBSS from found (WLC_E_START) IBSS */
+#define WLC_E_START		2	/* STA founded an IBSS or AP started a BSS */
+#define WLC_E_AUTH		3	/* 802.11 AUTH request */
+#define WLC_E_AUTH_IND		4	/* 802.11 AUTH indication */
+#define WLC_E_DEAUTH		5	/* 802.11 DEAUTH request */
+#define WLC_E_DEAUTH_IND	6	/* 802.11 DEAUTH indication */
+#define WLC_E_ASSOC		7	/* 802.11 ASSOC request */
+#define WLC_E_ASSOC_IND		8	/* 802.11 ASSOC indication */
+#define WLC_E_REASSOC		9	/* 802.11 REASSOC request */
+#define WLC_E_REASSOC_IND	10	/* 802.11 REASSOC indication */
+#define WLC_E_DISASSOC		11	/* 802.11 DISASSOC request */
+#define WLC_E_DISASSOC_IND	12	/* 802.11 DISASSOC indication */
+#define WLC_E_QUIET_START	13	/* 802.11h Quiet period started */
+#define WLC_E_QUIET_END		14	/* 802.11h Quiet period ended */
+#define WLC_E_BEACON_RX		15	/* BEACONS received/lost indication */
+#define WLC_E_LINK		16	/* generic link indication */
+#define WLC_E_MIC_ERROR		17	/* TKIP MIC error occurred */
+#define WLC_E_NDIS_LINK		18	/* NDIS style link indication */
+#define WLC_E_ROAM		19	/* roam complete: indicate status & reason */
+#define WLC_E_TXFAIL		20	/* change in dot11FailedCount (txfail) */
+#define WLC_E_PMKID_CACHE	21	/* WPA2 pmkid cache indication */
+#define WLC_E_RETROGRADE_TSF	22	/* current AP's TSF value went backward */
+#define WLC_E_PRUNE		23	/* AP was pruned from join list for reason */
+#define WLC_E_AUTOAUTH		24	/* report AutoAuth table entry match for join attempt */
+#define WLC_E_EAPOL_MSG		25	/* Event encapsulating an EAPOL message */
+#define WLC_E_SCAN_COMPLETE	26	/* Scan results are ready or scan was aborted */
+#define WLC_E_ADDTS_IND		27	/* indicate to host addts fail/success */
+#define WLC_E_DELTS_IND		28	/* indicate to host delts fail/success */
+#define WLC_E_BCNSENT_IND	29	/* indicate to host of beacon transmit */
+#define WLC_E_BCNRX_MSG		30	/* Send the received beacon up to the host */
+#define WLC_E_BCNLOST_MSG	31	/* indicate to host loss of beacon */
+#define WLC_E_ROAM_PREP		32	/* before attempting to roam association */
+#define WLC_E_PFN_NET_FOUND	33	/* PFN network found event */
+#define WLC_E_PFN_NET_LOST	34	/* PFN network lost event */
+#define WLC_E_RESET_COMPLETE	35
+#define WLC_E_JOIN_START	36
+#define WLC_E_ROAM_START	37	/* roam attempt started: indicate reason */
+#define WLC_E_ASSOC_START	38
+#define WLC_E_IBSS_ASSOC	39
+#define WLC_E_RADIO		40
+#define WLC_E_PSM_WATCHDOG	41	/* PSM microcode watchdog fired */
+#define WLC_E_PROBREQ_MSG       44      /* probe request received */
+#define WLC_E_SCAN_CONFIRM_IND  45
+#define WLC_E_PSK_SUP		46	/* WPA Handshake fail */
+#define WLC_E_COUNTRY_CODE_CHANGED	47
+#define	WLC_E_EXCEEDED_MEDIUM_TIME	48	/* WMMAC excedded medium time */
+#define WLC_E_ICV_ERROR		49	/* WEP ICV error occurred */
+#define WLC_E_UNICAST_DECODE_ERROR	50	/* Unsupported unicast encrypted frame */
+#define WLC_E_MULTICAST_DECODE_ERROR	51	/* Unsupported multicast encrypted frame */
+#define WLC_E_TRACE		52
+#define WLC_E_IF		54	/* I/F change (for dongle host notification) */
+#define WLC_E_P2P_DISC_LISTEN_COMPLETE	55	/* listen state expires */
+#define WLC_E_RSSI		56	/* indicate RSSI change based on configured levels */
+#define WLC_E_PFN_BEST_BATCHING	57	/* PFN best network batching event */
+#define WLC_E_EXTLOG_MSG	58
+#define WLC_E_ACTION_FRAME      59	/* Action frame Rx */
+#define WLC_E_ACTION_FRAME_COMPLETE	60	/* Action frame Tx complete */
+#define WLC_E_PRE_ASSOC_IND	61	/* assoc request received */
+#define WLC_E_PRE_REASSOC_IND	62	/* re-assoc request received */
+#define WLC_E_CHANNEL_ADOPTED	63
+#define WLC_E_AP_STARTED	64	/* AP started */
+#define WLC_E_DFS_AP_STOP	65	/* AP stopped due to DFS */
+#define WLC_E_DFS_AP_RESUME	66	/* AP resumed due to DFS */
+#define WLC_E_WAI_STA_EVENT	67	/* WAI stations event */
+#define WLC_E_WAI_MSG 		68	/* event encapsulating an WAI message */
+#define WLC_E_ESCAN_RESULT 	69	/* escan result event */
+#define WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE 	70	/* action frame off channel complete */
+#define WLC_E_PROBRESP_MSG	71	/* probe response received */
+#define WLC_E_P2P_PROBREQ_MSG	72	/* P2P Probe request received */
+#define WLC_E_DCS_REQUEST	73
+#define WLC_E_FIFO_CREDIT_MAP	74	/* credits for D11 FIFOs. [AC0,AC1,AC2,AC3,BC_MC,ATIM] */
+#define WLC_E_ACTION_FRAME_RX	75	/* Received action frame event WITH
+					 * wl_event_rx_frame_data_t header
+					 */
+#define WLC_E_WAKE_EVENT	76	/* Wake Event timer fired, used for wake WLAN test mode */
+#define WLC_E_RM_COMPLETE	77	/* Radio measurement complete */
+#define WLC_E_HTSFSYNC		78	/* Synchronize TSF with the host */
+#define WLC_E_OVERLAY_REQ	79	/* request an overlay IOCTL/iovar from the host */
+#define WLC_E_CSA_COMPLETE_IND		80	/* 802.11 CHANNEL SWITCH ACTION completed */
+#define WLC_E_EXCESS_PM_WAKE_EVENT	81	/* excess PM Wake Event to inform host  */
+#define WLC_E_PFN_SCAN_NONE		82	/* no PFN networks around */
+/* PFN BSSID network found event, conflict/share with  WLC_E_PFN_SCAN_NONE */
+#define WLC_E_PFN_BSSID_NET_FOUND	82
+#define WLC_E_PFN_SCAN_ALLGONE		83	/* last found PFN network gets lost */
+/* PFN BSSID network lost event, conflict/share with WLC_E_PFN_SCAN_ALLGONE */
+#define WLC_E_PFN_BSSID_NET_LOST	83
+#define WLC_E_GTK_PLUMBED		84
+#define WLC_E_ASSOC_IND_NDIS		85	/* 802.11 ASSOC indication for NDIS only */
+#define WLC_E_REASSOC_IND_NDIS		86	/* 802.11 REASSOC indication for NDIS only */
+#define WLC_E_ASSOC_REQ_IE		87
+#define WLC_E_ASSOC_RESP_IE		88
+#define WLC_E_ASSOC_RECREATED		89	/* association recreated on resume */
+#define WLC_E_ACTION_FRAME_RX_NDIS	90	/* rx action frame event for NDIS only */
+#define WLC_E_AUTH_REQ			91	/* authentication request received */
+#define WLC_E_TDLS_PEER_EVENT		92	/* discovered peer, connected/disconnected peer */
+#define WLC_E_SPEEDY_RECREATE_FAIL	93	/* fast assoc recreation failed */
+#define WLC_E_NATIVE			94	/* port-specific event and payload (e.g. NDIS) */
+#define WLC_E_PKTDELAY_IND		95	/* event for tx pkt delay suddently jump */
+#define WLC_E_PSTA_PRIMARY_INTF_IND	99	/* psta primary interface indication */
+#define WLC_E_NAN			100     /* NAN event */
+#define WLC_E_BEACON_FRAME_RX		101
+#define WLC_E_SERVICE_FOUND		102	/* desired service found */
+#define WLC_E_GAS_FRAGMENT_RX		103	/* GAS fragment received */
+#define WLC_E_GAS_COMPLETE		104	/* GAS sessions all complete */
+#define WLC_E_P2PO_ADD_DEVICE		105	/* New device found by p2p offload */
+#define WLC_E_P2PO_DEL_DEVICE		106	/* device has been removed by p2p offload */
+#define WLC_E_WNM_STA_SLEEP		107	/* WNM event to notify STA enter sleep mode */
+#define WLC_E_TXFAIL_THRESH		108	/* Indication of MAC tx failures (exhaustion of
+						 * 802.11 retries) exceeding threshold(s)
+						 */
+#define WLC_E_PROXD			109	/* Proximity Detection event */
+#define WLC_E_IBSS_COALESCE		110	/* IBSS Coalescing */
+#define WLC_E_AIBSS_TXFAIL		110	/* TXFAIL event for AIBSS, re using event 110 */
+#define WLC_E_BSS_LOAD			114	/* Inform host of beacon bss load */
+#define WLC_E_MIMO_PWR_SAVE		115	/* Inform host MIMO PWR SAVE learning events */
+#define WLC_E_LEAKY_AP_STATS	116 /* Inform host leaky Ap stats events */
+#define WLC_E_ALLOW_CREDIT_BORROW 117	/* Allow or disallow wlfc credit borrowing in DHD */
+#define WLC_E_MSCH			120	/* Multiple channel scheduler event */
+#define WLC_E_CSA_START_IND		121
+#define WLC_E_CSA_DONE_IND		122
+#define WLC_E_CSA_FAILURE_IND		123
+#define WLC_E_CCA_CHAN_QUAL		124	/* CCA based channel quality report */
+#define WLC_E_BSSID		125	/* to report change in BSSID while roaming */
+#define WLC_E_TX_STAT_ERROR		126	/* tx error indication */
+#define WLC_E_BCMC_CREDIT_SUPPORT	127	/* credit check for BCMC supported */
+#define WLC_E_PEER_TIMEOUT	128 /* silently drop a STA because of inactivity */
+#define WLC_E_BT_WIFI_HANDOVER_REQ	130	/* Handover Request Initiated */
+#define WLC_E_SPW_TXINHIBIT		131     /* Southpaw TxInhibit notification */
+#define WLC_E_FBT_AUTH_REQ_IND		132	/* FBT Authentication Request Indication */
+#define WLC_E_RSSI_LQM			133	/* Enhancement addition for WLC_E_RSSI */
+#define WLC_E_PFN_GSCAN_FULL_RESULT		134 /* Full probe/beacon (IEs etc) results */
+#define WLC_E_PFN_SWC		135 /* Significant change in rssi of bssids being tracked */
+#define WLC_E_AUTHORIZED	136	/* a STA been authroized for traffic */
+#define WLC_E_PROBREQ_MSG_RX	137 /* probe req with wl_event_rx_frame_data_t header */
+#define WLC_E_PFN_SCAN_COMPLETE	138	/* PFN completed scan of network list */
+#define WLC_E_RMC_EVENT		139	/* RMC Event */
+#define WLC_E_DPSTA_INTF_IND	140	/* DPSTA interface indication */
+#define WLC_E_RRM		141	/* RRM Event */
+#define WLC_E_PFN_SSID_EXT	142	/* SSID EXT event */
+#define WLC_E_ROAM_EXP_EVENT	143	/* Expanded roam event */
+#define WLC_E_ULP			146	/* ULP entered indication */
+#define WLC_E_MACDBG			147	/* Ucode debugging event */
+#define WLC_E_RESERVED			148	/* reserved */
+#define WLC_E_PRE_ASSOC_RSEP_IND	149	/* assoc resp received */
+#define WLC_E_PSK_AUTH			150	/* PSK AUTH WPA2-PSK 4 WAY Handshake failure */
+#define WLC_E_TKO			151     /* TCP keepalive offload */
+#define WLC_E_SDB_TRANSITION            152     /* SDB mode-switch event */
+#define WLC_E_NATOE_NFCT		153     /* natoe event */
+#define WLC_E_TEMP_THROTTLE		154	/* Temperature throttling control event */
+#define WLC_E_LINK_QUALITY		155     /* Link quality measurement complete */
+#define WLC_E_BSSTRANS_RESP		156 /* BSS Transition Response received */
+#define WLC_E_HE_TWT_SETUP		157	/* HE TWT Setup Complete event */
+#define WLC_E_NAN_DATA_IND		158	/* NAN 2.0 data indication */
+#define WLC_E_NAN_DATA_CONF		159	/* NAN 2.0 data confirmation */
+#define WLC_E_RADAR_DETECTED		160	/* Radar Detected event */
+#define WLC_E_RANGING_EVENT		161	/* Ranging event */
+#define WLC_E_INVALID_IE		162	/* Received invalid IE */
+#define WLC_E_MODE_SWITCH		163	/* Mode switch event */
+#define WLC_E_PKT_FILTER		164	/* Packet filter event */
+#define WLC_E_DMA_TXFLUSH_COMPLETE		165	/* TxFlush done before changing
+											* tx/rxchain
+											*/
+#define WLC_E_LAST			166	/* highest val + 1 for range checking */
+#if (WLC_E_LAST > 166)
+#error "WLC_E_LAST: Invalid value for last event; must be <= 165."
+#endif /* WLC_E_LAST */
+
+/* define an API for getting the string name of an event */
+extern const char *bcmevent_get_name(uint event_type);
+extern void wl_event_to_host_order(wl_event_msg_t * evt);
+extern void wl_event_to_network_order(wl_event_msg_t * evt);
+
+/* validate if the event is proper and if valid copy event header to event */
+extern int is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype,
+	bcm_event_msg_u_t *out_event);
+
+/* conversion between host and network order for events */
+void wl_event_to_host_order(wl_event_msg_t * evt);
+void wl_event_to_network_order(wl_event_msg_t * evt);
+
+
+/* Event status codes */
+#define WLC_E_STATUS_SUCCESS		0	/* operation was successful */
+#define WLC_E_STATUS_FAIL		1	/* operation failed */
+#define WLC_E_STATUS_TIMEOUT		2	/* operation timed out */
+#define WLC_E_STATUS_NO_NETWORKS	3	/* failed due to no matching network found */
+#define WLC_E_STATUS_ABORT		4	/* operation was aborted */
+#define WLC_E_STATUS_NO_ACK		5	/* protocol failure: packet not ack'd */
+#define WLC_E_STATUS_UNSOLICITED	6	/* AUTH or ASSOC packet was unsolicited */
+#define WLC_E_STATUS_ATTEMPT		7	/* attempt to assoc to an auto auth configuration */
+#define WLC_E_STATUS_PARTIAL		8	/* scan results are incomplete */
+#define WLC_E_STATUS_NEWSCAN		9	/* scan aborted by another scan */
+#define WLC_E_STATUS_NEWASSOC		10	/* scan aborted due to assoc in progress */
+#define WLC_E_STATUS_11HQUIET		11	/* 802.11h quiet period started */
+#define WLC_E_STATUS_SUPPRESS		12	/* user disabled scanning (WLC_SET_SCANSUPPRESS) */
+#define WLC_E_STATUS_NOCHANS		13	/* no allowable channels to scan */
+#define WLC_E_STATUS_CS_ABORT		15	/* abort channel select */
+#define WLC_E_STATUS_ERROR		16	/* request failed due to error */
+#define WLC_E_STATUS_INVALID 0xff  /* Invalid status code to init variables. */
+
+/* 4-way handshake event type */
+#define WLC_E_PSK_AUTH_SUB_EAPOL_START		1	/* EAPOL start */
+#define WLC_E_PSK_AUTH_SUB_EAPOL_DONE		2	/* EAPOL end */
+/* GTK event type */
+#define	WLC_E_PSK_AUTH_SUB_GTK_DONE		3	/* GTK end */
+
+/* 4-way handshake event status code */
+#define WLC_E_STATUS_PSK_AUTH_WPA_TIMOUT	1	/* operation timed out */
+#define WLC_E_STATUS_PSK_AUTH_MIC_WPA_ERR		2	/* MIC error */
+#define WLC_E_STATUS_PSK_AUTH_IE_MISMATCH_ERR		3	/* IE Missmatch error */
+#define WLC_E_STATUS_PSK_AUTH_REPLAY_COUNT_ERR		4
+#define WLC_E_STATUS_PSK_AUTH_PEER_BLACKISTED	5	/* Blaclisted peer */
+#define WLC_E_STATUS_PSK_AUTH_GTK_REKEY_FAIL	6	/* GTK event status code */
+
+/* SDB transition status code */
+#define WLC_E_STATUS_SDB_START          1
+#define WLC_E_STATUS_SDB_COMPLETE       2
+
+/* SDB transition reason code */
+#define WLC_E_REASON_HOST_DIRECT	0
+#define WLC_E_REASON_INFRA_ASSOC	1
+#define WLC_E_REASON_INFRA_ROAM		2
+#define WLC_E_REASON_INFRA_DISASSOC	3
+#define WLC_E_REASON_NO_MODE_CHANGE_NEEDED	4
+
+/* WLC_E_SDB_TRANSITION event data */
+#define WL_MAX_BSSCFG     4
+#define WL_EVENT_SDB_TRANSITION_VER     1
+typedef struct wl_event_sdb_data {
+	uint8 wlunit;           /* Core index */
+	uint8 is_iftype;        /* Interface Type(Station, SoftAP, P2P_GO, P2P_GC */
+	uint16 chanspec;        /* Interface Channel/Chanspec */
+	char ssidbuf[(4 * 32) + 1];	/* SSID_FMT_BUF_LEN: ((4 * DOT11_MAX_SSID_LEN) + 1) */
+} wl_event_sdb_data_t;
+
+typedef struct wl_event_sdb_trans {
+	uint8 version;          /* Event Data Version */
+	uint8 rsdb_mode;
+	uint8 enable_bsscfg;
+	uint8 reserved;
+	struct wl_event_sdb_data values[WL_MAX_BSSCFG];
+} wl_event_sdb_trans_t;
+
+/* roam reason codes */
+#define WLC_E_REASON_INITIAL_ASSOC	0	/* initial assoc */
+#define WLC_E_REASON_LOW_RSSI		1	/* roamed due to low RSSI */
+#define WLC_E_REASON_DEAUTH		2	/* roamed due to DEAUTH indication */
+#define WLC_E_REASON_DISASSOC		3	/* roamed due to DISASSOC indication */
+#define WLC_E_REASON_BCNS_LOST		4	/* roamed due to lost beacons */
+
+#define WLC_E_REASON_FAST_ROAM_FAILED	5	/* roamed due to fast roam failure */
+#define WLC_E_REASON_DIRECTED_ROAM	6	/* roamed due to request by AP */
+#define WLC_E_REASON_TSPEC_REJECTED	7	/* roamed due to TSPEC rejection */
+#define WLC_E_REASON_BETTER_AP		8	/* roamed due to finding better AP */
+#define WLC_E_REASON_MINTXRATE		9	/* roamed because at mintxrate for too long */
+#define WLC_E_REASON_TXFAIL		10	/* We can hear AP, but AP can't hear us */
+/* retained for precommit auto-merging errors; remove once all branches are synced */
+#define WLC_E_REASON_REQUESTED_ROAM	11
+#define WLC_E_REASON_BSSTRANS_REQ	11	/* roamed due to BSS Transition request by AP */
+#define WLC_E_REASON_LOW_RSSI_CU		12 /* roamed due to low RSSI and Channel Usage */
+#define WLC_E_REASON_RADAR_DETECTED	13	/* roamed due to radar detection by STA */
+
+/* prune reason codes */
+#define WLC_E_PRUNE_ENCR_MISMATCH	1	/* encryption mismatch */
+#define WLC_E_PRUNE_BCAST_BSSID		2	/* AP uses a broadcast BSSID */
+#define WLC_E_PRUNE_MAC_DENY		3	/* STA's MAC addr is in AP's MAC deny list */
+#define WLC_E_PRUNE_MAC_NA		4	/* STA's MAC addr is not in AP's MAC allow list */
+#define WLC_E_PRUNE_REG_PASSV		5	/* AP not allowed due to regulatory restriction */
+#define WLC_E_PRUNE_SPCT_MGMT		6	/* AP does not support STA locale spectrum mgmt */
+#define WLC_E_PRUNE_RADAR		7	/* AP is on a radar channel of STA locale */
+#define WLC_E_RSN_MISMATCH		8	/* STA does not support AP's RSN */
+#define WLC_E_PRUNE_NO_COMMON_RATES	9	/* No rates in common with AP */
+#define WLC_E_PRUNE_BASIC_RATES		10	/* STA does not support all basic rates of BSS */
+#define WLC_E_PRUNE_CIPHER_NA		12	/* BSS's cipher not supported */
+#define WLC_E_PRUNE_KNOWN_STA		13	/* AP is already known to us as a STA */
+#define WLC_E_PRUNE_WDS_PEER		15	/* AP is already known to us as a WDS peer */
+#define WLC_E_PRUNE_QBSS_LOAD		16	/* QBSS LOAD - AAC is too low */
+#define WLC_E_PRUNE_HOME_AP		17	/* prune home AP */
+#define WLC_E_PRUNE_AUTH_RESP_MAC	20	/* suppress auth resp by MAC filter */
+
+/* WPA failure reason codes carried in the WLC_E_PSK_SUP event */
+#define WLC_E_SUP_OTHER			0	/* Other reason */
+#define WLC_E_SUP_DECRYPT_KEY_DATA	1	/* Decryption of key data failed */
+#define WLC_E_SUP_BAD_UCAST_WEP128	2	/* Illegal use of ucast WEP128 */
+#define WLC_E_SUP_BAD_UCAST_WEP40	3	/* Illegal use of ucast WEP40 */
+#define WLC_E_SUP_UNSUP_KEY_LEN		4	/* Unsupported key length */
+#define WLC_E_SUP_PW_KEY_CIPHER		5	/* Unicast cipher mismatch in pairwise key */
+#define WLC_E_SUP_MSG3_TOO_MANY_IE	6	/* WPA IE contains > 1 RSN IE in key msg 3 */
+#define WLC_E_SUP_MSG3_IE_MISMATCH	7	/* WPA IE mismatch in key message 3 */
+#define WLC_E_SUP_NO_INSTALL_FLAG	8	/* INSTALL flag unset in 4-way msg */
+#define WLC_E_SUP_MSG3_NO_GTK		9	/* encapsulated GTK missing from msg 3 */
+#define WLC_E_SUP_GRP_KEY_CIPHER	10	/* Multicast cipher mismatch in group key */
+#define WLC_E_SUP_GRP_MSG1_NO_GTK	11	/* encapsulated GTK missing from group msg 1 */
+#define WLC_E_SUP_GTK_DECRYPT_FAIL	12	/* GTK decrypt failure */
+#define WLC_E_SUP_SEND_FAIL		13	/* message send failure */
+#define WLC_E_SUP_DEAUTH		14	/* received FC_DEAUTH */
+#define WLC_E_SUP_WPA_PSK_TMO		15	/* WPA PSK 4-way handshake timeout */
+#define WLC_E_SUP_WPA_PSK_M1_TMO	16	/* WPA PSK 4-way handshake M1 timeout */
+#define WLC_E_SUP_WPA_PSK_M3_TMO	17	/* WPA PSK 4-way handshake M3 timeout */
+
+
+/* Ucode reason codes carried in the WLC_E_MACDBG event */
+#define WLC_E_MACDBG_LIST_PSM		0	/* Dump list update for PSM registers */
+#define WLC_E_MACDBG_LIST_PSMX		1	/* Dump list update for PSMx registers */
+#define WLC_E_MACDBG_REGALL		2	/* Dump all registers */
+
+/* reason codes for WLC_E_LINK_QUALITY event */
+#define WLC_E_LINK_QUALITY_NONE			0
+#define WLC_E_LINK_QUALITY_NO_ACK		1
+#define WLC_E_LINK_QUALITY_NO_RESULT	2
+
+/* Event data for events that include frames received over the air */
+/* WLC_E_PROBRESP_MSG
+ * WLC_E_P2P_PROBREQ_MSG
+ * WLC_E_ACTION_FRAME_RX
+ */
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data {
+	uint16	version;
+	uint16	channel;	/* Matches chanspec_t format from bcmwifi_channels.h */
+	int32	rssi;
+	uint32	mactime;
+	uint32	rate;
+} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t;
+
+#define BCM_RX_FRAME_DATA_VERSION 1
+
+/* WLC_E_IF event data */
+typedef struct wl_event_data_if {
+	uint8 ifidx;		/* RTE virtual device index (for dongle) */
+	uint8 opcode;		/* see I/F opcode */
+	uint8 reserved;		/* bit mask (WLC_E_IF_FLAGS_XXX ) */
+	uint8 bssidx;		/* bsscfg index */
+	uint8 role;		/* see I/F role */
+} wl_event_data_if_t;
+
+/* WLC_E_NATOE event data */
+typedef struct wl_event_data_natoe {
+	uint32 natoe_active;
+	uint32 sta_ip;
+	uint16 start_port;
+	uint16 end_port;
+} wl_event_data_natoe_t;
+
+/* opcode in WLC_E_IF event */
+#define WLC_E_IF_ADD		1	/* bsscfg add */
+#define WLC_E_IF_DEL		2	/* bsscfg delete */
+#define WLC_E_IF_CHANGE		3	/* bsscfg role change */
+
+/* I/F role code in WLC_E_IF event */
+#define WLC_E_IF_ROLE_STA		0	/* Infra STA */
+#define WLC_E_IF_ROLE_AP		1	/* Access Point */
+#define WLC_E_IF_ROLE_WDS		2	/* WDS link */
+#define WLC_E_IF_ROLE_P2P_GO		3	/* P2P Group Owner */
+#define WLC_E_IF_ROLE_P2P_CLIENT	4	/* P2P Client */
+#define WLC_E_IF_ROLE_IBSS              8       /* IBSS */
+#define WLC_E_IF_ROLE_NAN              9       /* NAN */
+
+/* WLC_E_RSSI event data */
+typedef struct wl_event_data_rssi {
+	int32 rssi;
+	int32 snr;
+	int32 noise;
+} wl_event_data_rssi_t;
+
+/* WLC_E_IF flag */
+#define WLC_E_IF_FLAGS_BSSCFG_NOIF	0x1	/* no host I/F creation needed */
+
+/* Reason codes for LINK */
+#define WLC_E_LINK_BCN_LOSS     1   /* Link down because of beacon loss */
+#define WLC_E_LINK_DISASSOC     2   /* Link down because of disassoc */
+#define WLC_E_LINK_ASSOC_REC    3   /* Link down because assoc recreate failed */
+#define WLC_E_LINK_BSSCFG_DIS   4   /* Link down due to bsscfg down */
+
+
+/* WLC_E_NDIS_LINK event data */
+typedef BWL_PRE_PACKED_STRUCT struct ndis_link_parms {
+	struct ether_addr peer_mac; /* 6 bytes */
+	uint16 chanspec;            /* 2 bytes */
+	uint32 link_speed;          /* current datarate in units of 500 Kbit/s */
+	uint32 max_link_speed;      /* max possible datarate for link in units of 500 Kbit/s  */
+	int32  rssi;                /* average rssi */
+} BWL_POST_PACKED_STRUCT ndis_link_parms_t;
+
+/* reason codes for WLC_E_OVERLAY_REQ event */
+#define WLC_E_OVL_DOWNLOAD		0	/* overlay download request */
+#define WLC_E_OVL_UPDATE_IND	1	/* device indication of host overlay update */
+
+/* reason codes for WLC_E_TDLS_PEER_EVENT event */
+#define WLC_E_TDLS_PEER_DISCOVERED		0	/* peer is ready to establish TDLS */
+#define WLC_E_TDLS_PEER_CONNECTED		1
+#define WLC_E_TDLS_PEER_DISCONNECTED	2
+
+/* reason codes for WLC_E_RMC_EVENT event */
+#define WLC_E_REASON_RMC_NONE		0
+#define WLC_E_REASON_RMC_AR_LOST		1
+#define WLC_E_REASON_RMC_AR_NO_ACK		2
+
+#ifdef WLTDLS
+/* TDLS Action Category code */
+#define TDLS_AF_CATEGORY		12
+/* Wi-Fi Display (WFD) Vendor Specific Category */
+/* used for WFD Tunneled Probe Request and Response */
+#define TDLS_VENDOR_SPECIFIC		127
+/* TDLS Action Field Values */
+#define TDLS_ACTION_SETUP_REQ		0
+#define TDLS_ACTION_SETUP_RESP		1
+#define TDLS_ACTION_SETUP_CONFIRM	2
+#define TDLS_ACTION_TEARDOWN		3
+#define WLAN_TDLS_SET_PROBE_WFD_IE	11
+#define WLAN_TDLS_SET_SETUP_WFD_IE	12
+#define WLAN_TDLS_SET_WFD_ENABLED	13
+#define WLAN_TDLS_SET_WFD_DISABLED	14
+#endif
+
+/* WLC_E_RANGING_EVENT subtypes */
+#define WLC_E_RANGING_RESULTS	0
+
+
+/* GAS event data */
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_gas {
+	uint16	channel;		/* channel of GAS protocol */
+	uint8	dialog_token;	/* GAS dialog token */
+	uint8	fragment_id;	/* fragment id */
+	uint16	status_code;	/* status code on GAS completion */
+	uint16 	data_len;		/* length of data to follow */
+	uint8	data[1];		/* variable length specified by data_len */
+} BWL_POST_PACKED_STRUCT wl_event_gas_t;
+
+/* service discovery TLV */
+typedef BWL_PRE_PACKED_STRUCT struct wl_sd_tlv {
+	uint16	length;			/* length of response_data */
+	uint8	protocol;		/* service protocol type */
+	uint8	transaction_id;		/* service transaction id */
+	uint8	status_code;		/* status code */
+	uint8	data[1];		/* response data */
+} BWL_POST_PACKED_STRUCT wl_sd_tlv_t;
+
+/* service discovery event data */
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_sd {
+	uint16	channel;		/* channel */
+	uint8	count;			/* number of tlvs */
+	wl_sd_tlv_t	tlv[1];		/* service discovery TLV */
+} BWL_POST_PACKED_STRUCT wl_event_sd_t;
+
+/* WLC_E_PKT_FILTER event sub-classification codes */
+#define WLC_E_PKT_FILTER_TIMEOUT	1 /* Matching packet not received in last timeout seconds */
+
+/* Note: proxd has a new API (ver 3.0) deprecates the following */
+
+/* Reason codes for WLC_E_PROXD */
+#define WLC_E_PROXD_FOUND		1	/* Found a proximity device */
+#define WLC_E_PROXD_GONE		2	/* Lost a proximity device */
+#define WLC_E_PROXD_START		3	/* used by: target  */
+#define WLC_E_PROXD_STOP		4	/* used by: target   */
+#define WLC_E_PROXD_COMPLETED		5	/* used by: initiator completed */
+#define WLC_E_PROXD_ERROR		6	/* used by both initiator and target */
+#define WLC_E_PROXD_COLLECT_START	7	/* used by: target & initiator */
+#define WLC_E_PROXD_COLLECT_STOP	8	/* used by: target */
+#define WLC_E_PROXD_COLLECT_COMPLETED	9	/* used by: initiator completed */
+#define WLC_E_PROXD_COLLECT_ERROR	10	/* used by both initiator and target */
+#define WLC_E_PROXD_NAN_EVENT		11	/* used by both initiator and target */
+#define WLC_E_PROXD_TS_RESULTS          12      /* used by: initiator completed */
+
+/*  proxd_event data */
+typedef struct ftm_sample {
+	uint32 value;	/* RTT in ns */
+	int8 rssi;	/* RSSI */
+} ftm_sample_t;
+
+typedef struct ts_sample {
+	uint32 t1;
+	uint32 t2;
+	uint32 t3;
+	uint32 t4;
+} ts_sample_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct proxd_event_data {
+	uint16 ver;			/* version */
+	uint16 mode;			/* mode: target/initiator */
+	uint16 method;			/* method: rssi/TOF/AOA */
+	uint8  err_code;		/* error classification */
+	uint8  TOF_type;		/* one way or two way TOF */
+	uint8  OFDM_frame_type;		/* legacy or VHT */
+	uint8  bandwidth;		/* Bandwidth is 20, 40,80, MHZ */
+	struct ether_addr peer_mac;	/* (e.g for tgt:initiator's */
+	uint32 distance;		/* dst to tgt, units meter */
+	uint32 meanrtt;			/* mean delta */
+	uint32 modertt;			/* Mode delta */
+	uint32 medianrtt;		/* median RTT */
+	uint32 sdrtt;			/* Standard deviation of RTT */
+	int32  gdcalcresult;		/* Software or Hardware Kind of redundant, but if */
+					/* frame type is VHT, then we should do it by hardware */
+	int16  avg_rssi;		/* avg rssi accroos the ftm frames */
+	int16  validfrmcnt;		/* Firmware's valid frame counts */
+	int32  peer_router_info;	/* Peer router information if available in TLV, */
+					/* We will add this field later  */
+	int32 var1;			/* average of group delay */
+	int32 var2;			/* average of threshold crossing */
+	int32 var3;			/* difference between group delay and threshold crossing */
+					/* raw Fine Time Measurements (ftm) data */
+	uint16 ftm_unit;		/* ftm cnt resolution in picoseconds , 6250ps - default */
+	uint16 ftm_cnt;			/*  num of rtd measurments/length in the ftm buffer  */
+	ftm_sample_t ftm_buff[1];	/* 1 ... ftm_cnt  */
+} BWL_POST_PACKED_STRUCT wl_proxd_event_data_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct proxd_event_ts_results {
+	uint16 ver;                     /* version */
+	uint16 mode;                    /* mode: target/initiator */
+	uint16 method;                  /* method: rssi/TOF/AOA */
+	uint8  err_code;                /* error classification */
+	uint8  TOF_type;                /* one way or two way TOF */
+	uint16  ts_cnt;                 /* number of timestamp measurements */
+	ts_sample_t ts_buff[1];         /* Timestamps */
+} BWL_POST_PACKED_STRUCT wl_proxd_event_ts_results_t;
+
+
+/* Video Traffic Interference Monitor Event */
+#define INTFER_EVENT_VERSION		1
+#define INTFER_STREAM_TYPE_NONTCP	1
+#define INTFER_STREAM_TYPE_TCP		2
+#define WLINTFER_STATS_NSMPLS		4
+typedef struct wl_intfer_event {
+	uint16 version;			/* version */
+	uint16 status;			/* status */
+	uint8 txfail_histo[WLINTFER_STATS_NSMPLS]; /* txfail histo */
+} wl_intfer_event_t;
+
+#define RRM_EVENT_VERSION		0
+typedef struct wl_rrm_event {
+	int16 version;
+	int16 len;
+	int16 cat;		/* Category */
+	int16 subevent;
+	char payload[1]; /* Measurement payload */
+} wl_rrm_event_t;
+
+
+/* WLC_E_PSTA_PRIMARY_INTF_IND event data */
+typedef struct wl_psta_primary_intf_event {
+	struct ether_addr prim_ea;	/* primary intf ether addr */
+} wl_psta_primary_intf_event_t;
+
+/* WLC_E_DPSTA_INTF_IND event data */
+typedef enum {
+	WL_INTF_PSTA = 1,
+	WL_INTF_DWDS = 2
+} wl_dpsta_intf_type;
+
+typedef struct wl_dpsta_intf_event {
+	wl_dpsta_intf_type intf_type;    /* dwds/psta intf register */
+} wl_dpsta_intf_event_t;
+
+/*  **********  NAN protocol events/subevents  ********** */
+#define NAN_EVENT_BUFFER_SIZE 512 /* max size */
+/* NAN Events sent by firmware */
+typedef enum wl_nan_events {
+	WL_NAN_EVENT_START = 1,		/* NAN cluster started */
+	WL_NAN_EVENT_JOIN = 2,		/* Joined to a NAN cluster */
+	WL_NAN_EVENT_ROLE = 3,	/* Role changed */
+	WL_NAN_EVENT_SCAN_COMPLETE = 4,
+	WL_NAN_EVENT_DISCOVERY_RESULT = 5,
+	WL_NAN_EVENT_REPLIED = 6,
+	WL_NAN_EVENT_TERMINATED = 7,	/* the instance ID will be present in the ev data */
+	WL_NAN_EVENT_RECEIVE = 8,
+	WL_NAN_EVENT_STATUS_CHG = 9,	/* generated on any change in nan_mac status */
+	WL_NAN_EVENT_MERGE = 10,	/* Merged to a NAN cluster */
+	WL_NAN_EVENT_STOP = 11,		/* NAN stopped */
+	WL_NAN_EVENT_P2P = 12,		/* NAN P2P EVENT */
+	WL_NAN_EVENT_WINDOW_BEGIN_P2P = 13, /* Event for begin of P2P further availability window */
+	WL_NAN_EVENT_WINDOW_BEGIN_MESH = 14,
+	WL_NAN_EVENT_WINDOW_BEGIN_IBSS = 15,
+	WL_NAN_EVENT_WINDOW_BEGIN_RANGING = 16,
+	WL_NAN_EVENT_POST_DISC = 17,	/* Event for post discovery data */
+	WL_NAN_EVENT_DATA_IF_ADD = 18,	/* Event for Data IF add */
+	WL_NAN_EVENT_DATA_PEER_ADD = 19, /* Event for peer add */
+	/* nan 2.0 */
+	WL_NAN_EVENT_DATA_IND = 20, /* Will be removed after source code is committed. */
+	WL_NAN_EVENT_PEER_DATAPATH_IND = 20, /* Peer's Datapath request Indication to Host */
+	WL_NAN_EVENT_DATA_CONF = 21, /* Will be removed after source code is committed. */
+	WL_NAN_EVENT_DATAPATH_ESTB = 21, /* Datapath Established to Host */
+	WL_NAN_EVENT_SDF_RX = 22,	/* entire service discovery frame */
+	WL_NAN_EVENT_DATA_END = 23,	/* Will be removed after source code is committed. */
+	WL_NAN_EVENT_DATAPATH_END = 23,	/* Data End to Host */
+	WL_NAN_EVENT_BCN_RX = 24,	/* received beacon payload */
+	WL_NAN_EVENT_PEER_DATAPATH_RESP = 25, /* Peer's Data Response indication to Host */
+	WL_NAN_EVENT_PEER_DATAPATH_CONF = 26, /* Peer's Data Confirm indication to Host */
+	WL_NAN_EVENT_RNG_REQ_IND = 27,  /* Range Request Indication to Host */
+	WL_NAN_EVENT_RNG_RPT_IND = 28,  /* Range Report Indication to Host */
+	WL_NAN_EVENT_RNG_TERM_IND = 29,  /* Range Termination Indication to Host */
+	WL_NAN_EVENT_INVALID	/* delimiter for max value */
+} nan_app_events_e;
+
+#define IS_NAN_EVT_ON(var, evt) ((var & (1 << (evt-1))) != 0)
+/*  ******************* end of NAN section *************** */
+
+/* WLC_E_ULP event data */
+#define WL_ULP_EVENT_VERSION		1
+#define WL_ULP_DISABLE_CONSOLE		1	/* Disable console message on ULP entry */
+#define WL_ULP_UCODE_DOWNLOAD		2       /* Download ULP ucode file */
+#define WL_ULP_ENTRY			3       /* inform ulp entry to Host during warmboot */
+
+typedef struct wl_ulp_event {
+	uint16 version;
+	uint16 ulp_dongle_action;
+} wl_ulp_event_t;
+
+/* TCP keepalive event data */
+typedef BWL_PRE_PACKED_STRUCT struct wl_event_tko {
+	uint8 index;		/* TCP connection index, 0 to max-1 */
+	uint8 pad[3];		/* 4-byte struct alignment */
+} BWL_POST_PACKED_STRUCT wl_event_tko_t;
+
+typedef struct {
+	uint8 radar_type;       /* one of RADAR_TYPE_XXX */
+	uint16 min_pw;          /* minimum pulse-width (usec * 20) */
+	uint16 max_pw;          /* maximum pulse-width (usec * 20) */
+	uint16 min_pri;         /* minimum pulse repetition interval (usec) */
+	uint16 max_pri;         /* maximum pulse repetition interval (usec) */
+	uint16 subband;         /* subband/frequency */
+} radar_detected_event_info_t;
+typedef struct wl_event_radar_detect_data {
+
+	uint32 version;
+	uint16 current_chanspec; /* chanspec on which the radar is recieved */
+	uint16 target_chanspec; /*  Target chanspec after detection of radar on current_chanspec */
+	radar_detected_event_info_t radar_info[2];
+} wl_event_radar_detect_data_t;
+
+
+#define WL_EVENT_MODESW_VER_1			1
+#define WL_EVENT_MODESW_VER_CURRENT		WL_EVENT_MODESW_VER_1
+
+#define WL_E_MODESW_FLAG_MASK_DEVICE		0x01u /* mask of device: belongs to local or peer */
+#define WL_E_MODESW_FLAG_MASK_FROM		0x02u /* mask of origin: firmware or user */
+#define WL_E_MODESW_FLAG_MASK_STATE		0x0Cu /* mask of state: modesw progress state */
+
+#define WL_E_MODESW_FLAG_DEVICE_LOCAL		0x00u /* flag - device: info is about self/local */
+#define WL_E_MODESW_FLAG_DEVICE_PEER		0x01u /* flag - device: info is about peer */
+
+#define WL_E_MODESW_FLAG_FROM_FIRMWARE		0x00u /* flag - from: request is from firmware */
+#define WL_E_MODESW_FLAG_FROM_USER		0x02u /* flag - from: request is from user/iov */
+
+#define WL_E_MODESW_FLAG_STATE_REQUESTED	0x00u /* flag - state: mode switch request */
+#define WL_E_MODESW_FLAG_STATE_INITIATED	0x04u /* flag - state: switch initiated */
+#define WL_E_MODESW_FLAG_STATE_COMPLETE		0x08u /* flag - state: switch completed/success */
+#define WL_E_MODESW_FLAG_STATE_FAILURE		0x0Cu /* flag - state: failed to switch */
+
+/* Get sizeof *X including variable data's length where X is pointer to wl_event_mode_switch_t */
+#define WL_E_MODESW_SIZE(X) (sizeof(*(X)) + (X)->length)
+
+/* Get variable data's length where X is pointer to wl_event_mode_switch_t */
+#define WL_E_MODESW_DATA_SIZE(X) (((X)->length > sizeof(*(X))) ? ((X)->length - sizeof(*(X))) : 0)
+
+#define WL_E_MODESW_REASON_UNKNOWN		0u /* reason: UNKNOWN */
+#define WL_E_MODESW_REASON_ACSD			1u /* reason: ACSD (based on events from FW */
+#define WL_E_MODESW_REASON_OBSS_DBS		2u /* reason: OBSS DBS (eg. on interference) */
+#define WL_E_MODESW_REASON_DFS			3u /* reason: DFS (eg. on subband radar) */
+#define WL_E_MODESW_REASON_DYN160		4u /* reason: DYN160 (160/2x2 - 80/4x4) */
+
+/* event structure for WLC_E_MODE_SWITCH */
+typedef struct {
+	uint16 version;
+	uint16 length;	/* size including 'data' field */
+	uint16 opmode_from;
+	uint16 opmode_to;
+	uint32 flags;	/* bit 0: peer(/local==0);
+			 * bit 1: user(/firmware==0);
+			 * bits 3,2: 00==requested, 01==initiated,
+			 *           10==complete, 11==failure;
+			 * rest: reserved
+			 */
+	uint16 reason;	/* value 0: unknown, 1: ACSD, 2: OBSS_DBS,
+			 *       3: DFS, 4: DYN160, rest: reserved
+			 */
+	uint16 data_offset;	/* offset to 'data' from beginning of this struct.
+				 * fields may be added between data_offset and data
+				 */
+	/* ADD NEW FIELDS HERE */
+	uint8 data[];	/* reason specific data; could be empty */
+} wl_event_mode_switch_t;
+
+/* when reason in WLC_E_MODE_SWITCH is DYN160, data will carry the following structure */
+typedef struct {
+	uint16 trigger;		/* value 0: MU to SU, 1: SU to MU, 2: metric_dyn160, 3:re-/assoc,
+				 *       4: disassoc, 5: rssi, 6: traffic, 7: interference,
+				 *       8: chanim_stats
+				 */
+	struct ether_addr sta_addr;	/* causal STA's MAC address when known */
+	uint16 metric_160_80;		/* latest dyn160 metric */
+	uint8 nss;		/* NSS of the STA */
+	uint8 bw;		/* BW of the STA */
+	int8 rssi;		/* RSSI of the STA */
+	uint8 traffic;		/* internal metric of traffic */
+} wl_event_mode_switch_dyn160;
+
+/* TWT Setup Completion is designed to notify the user of TWT Setup process
+ * status. When 'status' field is value of BCME_OK, the user must check the
+ * 'setup_cmd' field value in 'wl_twt_sdesc_t' structure that at the end of
+ * the event data to see the response from the TWT Responding STA; when
+ * 'status' field is value of BCME_ERROR or non BCME_OK, user must not use
+ * anything from 'wl_twt_sdesc_t' structure as it is the TWT Requesting STA's
+ * own TWT parameter.
+ */
+
+#define WL_TWT_SETUP_CPLT_VER	0
+
+/* TWT Setup Completion event data */
+typedef struct wl_twt_setup_cplt {
+	uint16 version;
+	uint16 length;	/* the byte count of fields from 'dialog' onwards */
+	uint8 dialog;	/* the dialog token user supplied to the TWT setup API */
+	uint8 pad[3];
+	int32 status;
+	/* wl_twt_sdesc_t desc; - defined in wlioctl.h */
+} wl_twt_setup_cplt_t;
+
+#define WL_INVALID_IE_EVENT_VERSION	0
+
+/* Invalid IE Event data */
+typedef struct wl_invalid_ie_event {
+	uint16 version;
+	uint16 len;      /* Length of the invalid IE copy */
+	uint16 type;     /* Type/subtype of the frame which contains the invalid IE */
+	uint16 error;    /* error code of the wrong IE, defined in ie_error_code_t */
+	uint8  ie[];     /* Variable length buffer for the invalid IE copy */
+} wl_invalid_ie_event_t;
+
+typedef enum ie_error_code {
+	IE_ERROR_OUT_OF_RANGE = 0x01
+} ie_error_code_t;
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _BCMEVENT_H_ */
diff --git a/wl/components/shared/proto/bcmip.h b/wl/components/shared/proto/bcmip.h
new file mode 100644
index 0000000..fce188f
--- /dev/null
+++ b/wl/components/shared/proto/bcmip.h
@@ -0,0 +1,243 @@
+/*
+ * Fundamental constants relating to IP Protocol
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmip.h 594480 2015-10-22 03:14:33Z $
+ */
+
+#ifndef _bcmip_h_
+#define _bcmip_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+/* IPV4 and IPV6 common */
+#define IP_VER_OFFSET		0x0	/* offset to version field */
+#define IP_VER_MASK		0xf0	/* version mask */
+#define IP_VER_SHIFT		4	/* version shift */
+#define IP_VER_4		4	/* version number for IPV4 */
+#define IP_VER_6		6	/* version number for IPV6 */
+
+#define IP_VER(ip_body) \
+	((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT)
+
+#define IP_PROT_ICMP		0x1	/* ICMP protocol */
+#define IP_PROT_IGMP		0x2	/* IGMP protocol */
+#define IP_PROT_TCP		0x6	/* TCP protocol */
+#define IP_PROT_UDP		0x11	/* UDP protocol type */
+#define IP_PROT_GRE		0x2f	/* GRE protocol type */
+#define IP_PROT_ICMP6           0x3a    /* ICMPv6 protocol type */
+
+/* IPV4 field offsets */
+#define IPV4_VER_HL_OFFSET      0       /* version and ihl byte offset */
+#define IPV4_TOS_OFFSET         1       /* type of service offset */
+#define IPV4_PKTLEN_OFFSET      2       /* packet length offset */
+#define IPV4_PKTFLAG_OFFSET     6       /* more-frag,dont-frag flag offset */
+#define IPV4_PROT_OFFSET        9       /* protocol type offset */
+#define IPV4_CHKSUM_OFFSET      10      /* IP header checksum offset */
+#define IPV4_SRC_IP_OFFSET      12      /* src IP addr offset */
+#define IPV4_DEST_IP_OFFSET     16      /* dest IP addr offset */
+#define IPV4_OPTIONS_OFFSET     20      /* IP options offset */
+#define IPV4_MIN_HEADER_LEN     20      /* Minimum size for an IP header (no options) */
+
+/* IPV4 field decodes */
+#define IPV4_VER_MASK		0xf0	/* IPV4 version mask */
+#define IPV4_VER_SHIFT		4	/* IPV4 version shift */
+
+#define IPV4_HLEN_MASK		0x0f	/* IPV4 header length mask */
+#define IPV4_HLEN(ipv4_body)	(4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK))
+
+#define IPV4_ADDR_LEN		4	/* IPV4 address length */
+
+#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	/* DiffServ codepoint mask */
+#define	IPV4_TOS_DSCP_SHIFT	2	/* DiffServ codepoint shift */
+
+#define	IPV4_TOS(ipv4_body)	(((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET])
+
+#define	IPV4_TOS_PREC_MASK	0xe0	/* Historical precedence mask */
+#define	IPV4_TOS_PREC_SHIFT	5	/* Historical precedence shift */
+
+#define IPV4_TOS_LOWDELAY	0x10	/* Lowest delay requested */
+#define IPV4_TOS_THROUGHPUT	0x8	/* Best throughput requested */
+#define IPV4_TOS_RELIABILITY	0x4	/* Most reliable delivery requested */
+
+#define IPV4_TOS_ROUTINE        0
+#define IPV4_TOS_PRIORITY       1
+#define IPV4_TOS_IMMEDIATE      2
+#define IPV4_TOS_FLASH          3
+#define IPV4_TOS_FLASHOVERRIDE  4
+#define IPV4_TOS_CRITICAL       5
+#define IPV4_TOS_INETWORK_CTRL  6
+#define IPV4_TOS_NETWORK_CTRL   7
+
+#define IPV4_PROT(ipv4_body)	(((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET])
+
+#define IPV4_FRAG_RESV		0x8000	/* Reserved */
+#define IPV4_FRAG_DONT		0x4000	/* Don't fragment */
+#define IPV4_FRAG_MORE		0x2000	/* More fragments */
+#define IPV4_FRAG_OFFSET_MASK	0x1fff	/* Fragment offset */
+
+#define IPV4_ADDR_STR_LEN	16	/* Max IP address length in string format */
+
+/* IPV4 packet formats */
+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;		/* Version and Internet Header Length */
+	uint8	tos;			/* Type Of Service */
+	uint16	tot_len;		/* Number of bytes in packet (max 65535) */
+	uint16	id;
+	uint16	frag;			/* 3 flag bits and fragment offset */
+	uint8	ttl;			/* Time To Live */
+	uint8	prot;			/* Protocol */
+	uint16	hdr_chksum;		/* IP header checksum */
+	uint8	src_ip[IPV4_ADDR_LEN];	/* Source IP Address */
+	uint8	dst_ip[IPV4_ADDR_LEN];	/* Destination IP Address */
+} BWL_POST_PACKED_STRUCT;
+
+/* IPV6 field offsets */
+#define IPV6_PAYLOAD_LEN_OFFSET	4	/* payload length offset */
+#define IPV6_NEXT_HDR_OFFSET	6	/* next header/protocol offset */
+#define IPV6_HOP_LIMIT_OFFSET	7	/* hop limit offset */
+#define IPV6_SRC_IP_OFFSET	8	/* src IP addr offset */
+#define IPV6_DEST_IP_OFFSET	24	/* dst IP addr offset */
+
+/* IPV6 field decodes */
+#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	/* IPV6 address length */
+
+/* IPV4 TOS or IPV6 Traffic Classifier or 0 */
+#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 IP_DSCP46(ip_body) (IP_TOS46(ip_body) >> IPV4_TOS_DSCP_SHIFT);
+
+/* IPV4 or IPV6 Protocol Classifier or 0 */
+#define IP_PROT46(ip_body) \
+	(IP_VER(ip_body) == IP_VER_4 ? IPV4_PROT(ip_body) : \
+	 IP_VER(ip_body) == IP_VER_6 ? IPV6_PROT(ip_body) : 0)
+
+/* IPV6 extension headers (options) */
+#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)
+
+#define IPV4_MCAST_TO_ETHER_MCAST(ipv4, ether) \
+{ \
+	ether[0] = 0x01; \
+	ether[1] = 0x00; \
+	ether[2] = 0x5E; \
+	ether[3] = (ipv4 & 0x7f0000) >> 16; \
+	ether[4] = (ipv4 & 0xff00) >> 8; \
+	ether[5] = (ipv4 & 0xff); \
+}
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#define IPV4_ADDR_STR "%d.%d.%d.%d"
+#define IPV4_ADDR_TO_STR(addr)	((uint32)addr & 0xff000000) >> 24, \
+								((uint32)addr & 0x00ff0000) >> 16, \
+								((uint32)addr & 0x0000ff00) >> 8, \
+								((uint32)addr & 0x000000ff)
+
+#endif	/* _bcmip_h_ */
diff --git a/wl/components/shared/proto/bcmipv6.h b/wl/components/shared/proto/bcmipv6.h
new file mode 100644
index 0000000..27e18d4
--- /dev/null
+++ b/wl/components/shared/proto/bcmipv6.h
@@ -0,0 +1,168 @@
+/*
+ * Fundamental constants relating to Neighbor Discovery Protocol
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmipv6.h 665042 2017-05-15 03:46:00Z $
+ */
+
+#ifndef _bcmipv6_h_
+#define _bcmipv6_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/* Extension headers */
+#define IPV6_EXT_HOP	0
+#define IPV6_EXT_ROUTE	43
+#define IPV6_EXT_FRAG	44
+#define IPV6_EXT_DEST	60
+#define IPV6_EXT_ESEC	50
+#define IPV6_EXT_AUTH	51
+
+/* Minimum size (extension header "word" length) */
+#define IPV6_EXT_WORD	8
+
+/* Offsets for most extension headers */
+#define IPV6_EXT_NEXTHDR	0
+#define IPV6_EXT_HDRLEN		1
+
+/* Constants specific to fragmentation header */
+#define IPV6_FRAG_MORE_MASK	0x0001
+#define IPV6_FRAG_MORE_SHIFT	0
+#define IPV6_FRAG_OFFS_MASK	0xfff8
+#define IPV6_FRAG_OFFS_SHIFT	3
+
+/* For icmpv6 */
+#define ICMPV6_HEADER_TYPE	0x3A
+#define ICMPV6_PKT_TYPE_RA	134
+#define ICMPV6_PKT_TYPE_NS	135
+#define ICMPV6_PKT_TYPE_NA	136
+
+#define ICMPV6_ND_OPT_TYPE_TARGET_MAC	2
+#define ICMPV6_ND_OPT_TYPE_SRC_MAC		1
+
+#define ICMPV6_ND_OPT_LEN_LINKADDR		1
+
+#define ICMPV6_ND_OPT_LEN_LINKADDR		1
+
+#define IPV6_VERSION 	6
+#define IPV6_HOP_LIMIT 	255
+
+#define IPV6_ADDR_NULL(a)	((a[0] | a[1] | a[2] | a[3] | a[4] | \
+							 a[5] | a[6] | a[7] | a[8] | a[9] | \
+							 a[10] | a[11] | a[12] | a[13] | \
+							 a[14] | a[15]) == 0)
+
+#define IPV6_ADDR_LOCAL(a)	(((a[0] == 0xfe) && (a[1] & 0x80))? TRUE: FALSE)
+
+/* IPV6 address */
+BWL_PRE_PACKED_STRUCT struct ipv6_addr {
+		uint8		addr[16];
+} BWL_POST_PACKED_STRUCT;
+
+/* ICMPV6 Header */
+BWL_PRE_PACKED_STRUCT struct icmp6_hdr {
+	uint8	icmp6_type;
+	uint8	icmp6_code;
+	uint16	icmp6_cksum;
+	BWL_PRE_PACKED_STRUCT union {
+		uint32 reserved;
+		BWL_PRE_PACKED_STRUCT struct nd_advt {
+#ifndef IL_BIGENDIAN
+			uint32	reserved1:5,
+				override:1,
+				solicited:1,
+				router:1,
+				reserved2:24;
+#else
+			uint32	router:1,
+				solicited:1,
+				override:1,
+				reserved:29;
+#endif /* IL_BIGENDIAN */
+		} BWL_POST_PACKED_STRUCT nd_advt;
+	} BWL_POST_PACKED_STRUCT opt;
+} BWL_POST_PACKED_STRUCT;
+
+/* Ipv6 Header Format */
+BWL_PRE_PACKED_STRUCT struct ipv6_hdr {
+#ifndef IL_BIGENDIAN
+	uint8	priority:4,
+		version:4;
+#else
+	uint8	version:4,
+		priority:4;
+#endif /* IL_BIGENDIAN */
+	uint8	flow_lbl[3];
+	uint16	payload_len;
+	uint8	nexthdr;
+	uint8 	hop_limit;
+	struct	ipv6_addr	saddr;
+	struct	ipv6_addr	daddr;
+} BWL_POST_PACKED_STRUCT;
+
+/* Neighbor Advertisement/Solicitation Packet Structure */
+BWL_PRE_PACKED_STRUCT struct bcm_nd_msg {
+	struct	icmp6_hdr	icmph;
+	struct	ipv6_addr	target;
+} BWL_POST_PACKED_STRUCT;
+
+
+/* Neighibor Solicitation/Advertisement Optional Structure */
+BWL_PRE_PACKED_STRUCT struct nd_msg_opt {
+	uint8 type;
+	uint8 len;
+	uint8 mac_addr[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+
+/* Ipv6 Fragmentation Header */
+BWL_PRE_PACKED_STRUCT struct ipv6_frag {
+	uint8	nexthdr;
+	uint8	reserved;
+	uint16	frag_offset;
+	uint32	ident;
+} BWL_POST_PACKED_STRUCT;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+static const struct ipv6_addr all_node_ipv6_maddr = {
+									{ 0xff, 0x2, 0, 0,
+									0, 0, 0, 0,
+									0, 0, 0, 0,
+									0, 0, 0, 1
+									}};
+
+#define IPV6_ISMULTI(a) (a[0] == 0xff)
+
+#define IPV6_MCAST_TO_ETHER_MCAST(ipv6, ether) \
+{ \
+	ether[0] = 0x33; \
+	ether[1] = 0x33; \
+	ether[2] = ipv6[12]; \
+	ether[3] = ipv6[13]; \
+	ether[4] = ipv6[14]; \
+	ether[5] = ipv6[15]; \
+}
+
+#endif	/* !defined(_bcmipv6_h_) */
diff --git a/wl/components/shared/proto/bcmtcp.h b/wl/components/shared/proto/bcmtcp.h
new file mode 100644
index 0000000..435e1ae
--- /dev/null
+++ b/wl/components/shared/proto/bcmtcp.h
@@ -0,0 +1,87 @@
+/*
+ * Fundamental constants relating to TCP Protocol
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmtcp.h 518342 2014-12-01 23:21:41Z $
+ */
+
+#ifndef _bcmtcp_h_
+#define _bcmtcp_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+#define TCP_SRC_PORT_OFFSET	0	/* TCP source port offset */
+#define TCP_DEST_PORT_OFFSET	2	/* TCP dest port offset */
+#define TCP_SEQ_NUM_OFFSET	4	/* TCP sequence number offset */
+#define TCP_ACK_NUM_OFFSET	8	/* TCP acknowledgement number offset */
+#define TCP_HLEN_OFFSET		12	/* HLEN and reserved bits offset */
+#define TCP_FLAGS_OFFSET	13	/* FLAGS and reserved bits offset */
+#define TCP_CHKSUM_OFFSET	16	/* TCP body checksum offset */
+
+#define TCP_PORT_LEN		2	/* TCP port field length */
+
+/* 8bit TCP flag field */
+#define TCP_FLAG_URG            0x20
+#define TCP_FLAG_ACK            0x10
+#define TCP_FLAG_PSH            0x08
+#define TCP_FLAG_RST            0x04
+#define TCP_FLAG_SYN            0x02
+#define TCP_FLAG_FIN            0x01
+
+#define TCP_HLEN_MASK           0xf000
+#define TCP_HLEN_SHIFT          12
+
+/* These fields are stored in network order */
+BWL_PRE_PACKED_STRUCT struct bcmtcp_hdr
+{
+	uint16	src_port;	/* Source Port Address */
+	uint16	dst_port;	/* Destination Port Address */
+	uint32	seq_num;	/* TCP Sequence Number */
+	uint32	ack_num;	/* TCP Sequence Number */
+	uint16	hdrlen_rsvd_flags;	/* Header length, reserved bits and flags */
+	uint16	tcpwin;		/* TCP window */
+	uint16	chksum;		/* Segment checksum with pseudoheader */
+	uint16	urg_ptr;	/* Points to seq-num of byte following urg data */
+} BWL_POST_PACKED_STRUCT;
+
+#define TCP_MIN_HEADER_LEN 20
+
+#define TCP_HDRLEN_MASK 0xf0
+#define TCP_HDRLEN_SHIFT 4
+#define TCP_HDRLEN(hdrlen) (((hdrlen) & TCP_HDRLEN_MASK) >> TCP_HDRLEN_SHIFT)
+
+#define TCP_FLAGS_MASK  0x1f
+#define TCP_FLAGS(hdrlen) ((hdrlen) & TCP_FLAGS_MASK)
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+/* To address round up by 32bit. */
+#define IS_TCPSEQ_GE(a, b) ((a - b) < NBITVAL(31))		/* a >= b */
+#define IS_TCPSEQ_LE(a, b) ((b - a) < NBITVAL(31))		/* a =< b */
+#define IS_TCPSEQ_GT(a, b) !IS_TCPSEQ_LE(a, b)		/* a > b */
+#define IS_TCPSEQ_LT(a, b) !IS_TCPSEQ_GE(a, b)		/* a < b */
+
+#endif	/* #ifndef _bcmtcp_h_ */
diff --git a/wl/components/shared/proto/ethernet.h b/wl/components/shared/proto/ethernet.h
new file mode 100644
index 0000000..756eff2
--- /dev/null
+++ b/wl/components/shared/proto/ethernet.h
@@ -0,0 +1,247 @@
+/*
+ * From FreeBSD 2.2.7: Fundamental constants relating to ethernet.
+ *
+ * Copyright (C) 2017, Broadcom. 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: ethernet.h 518342 2014-12-01 23:21:41Z $
+ */
+
+#ifndef _NET_ETHERNET_H_	/* use native BSD ethernet.h when available */
+#define _NET_ETHERNET_H_
+
+#ifndef _TYPEDEFS_H_
+#include "typedefs.h"
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+
+/*
+ * The number of bytes in an ethernet (MAC) address.
+ */
+#define	ETHER_ADDR_LEN		6
+
+/*
+ * The number of bytes in the type field.
+ */
+#define	ETHER_TYPE_LEN		2
+
+/*
+ * The number of bytes in the trailing CRC field.
+ */
+#define	ETHER_CRC_LEN		4
+
+/*
+ * The length of the combined header.
+ */
+#define	ETHER_HDR_LEN		(ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN)
+
+/*
+ * The minimum packet length.
+ */
+#define	ETHER_MIN_LEN		64
+
+/*
+ * The minimum packet user data length.
+ */
+#define	ETHER_MIN_DATA		46
+
+/*
+ * The maximum packet length.
+ */
+#define	ETHER_MAX_LEN		1518
+
+/*
+ * The maximum packet user data length.
+ */
+#define	ETHER_MAX_DATA		1500
+
+/* ether types */
+#define ETHER_TYPE_MIN		0x0600		/* Anything less than MIN is a length */
+#define	ETHER_TYPE_IP		0x0800		/* IP */
+#define ETHER_TYPE_ARP		0x0806		/* ARP */
+#define ETHER_TYPE_8021Q	0x8100		/* 802.1Q */
+#define	ETHER_TYPE_IPV6		0x86dd		/* IPv6 */
+#define	ETHER_TYPE_BRCM		0x886c		/* Broadcom Corp. */
+#define	ETHER_TYPE_802_1X	0x888e		/* 802.1x */
+#define	ETHER_TYPE_802_1X_PREAUTH 0x88c7	/* 802.1x preauthentication */
+#define ETHER_TYPE_WAI		0x88b4		/* WAI */
+#define ETHER_TYPE_89_0D	0x890d		/* 89-0d frame for TDLS */
+#define ETHER_TYPE_RRB		ETHER_TYPE_89_0D  /* RRB 802.11r 2008 */
+
+#define ETHER_TYPE_PPP_SES	0x8864		/* PPPoE Session */
+
+#define ETHER_TYPE_IAPP_L2_UPDATE	0x6	/* IAPP L2 update frame */
+
+/* Broadcom subtype follows ethertype;  First 2 bytes are reserved; Next 2 are subtype; */
+#define	ETHER_BRCM_SUBTYPE_LEN	4	/* Broadcom 4 byte subtype */
+
+/* ether header */
+#define ETHER_DEST_OFFSET	(0 * ETHER_ADDR_LEN)	/* dest address offset */
+#define ETHER_SRC_OFFSET	(1 * ETHER_ADDR_LEN)	/* src address offset */
+#define ETHER_TYPE_OFFSET	(2 * ETHER_ADDR_LEN)	/* ether type offset */
+
+/*
+ * A macro to validate a length with
+ */
+#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 /* Quick and ugly hack for VxWorks */
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+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;
+
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+BWL_PRE_PACKED_STRUCT struct	ether_addr {
+	uint8 octet[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+#elif defined(VX_BSD4_3) && VX_BSD4_3
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+BWL_PRE_PACKED_STRUCT struct	ether_addr {
+	uint8 octet[ETHER_ADDR_LEN];
+} BWL_POST_PACKED_STRUCT;
+#endif	/* !__INCif_etherh Quick and ugly hack for VxWorks */
+
+/*
+ * Takes a pointer, set, test, clear, toggle locally admininistered
+ * address bit in the 48-bit Ethernet address.
+ */
+#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))
+
+/* Takes a pointer, marks unicast address bit in the MAC address */
+#define ETHER_SET_UNICAST(ea)	(((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1))
+
+/*
+ * Takes a pointer, returns true if a 48-bit multicast address
+ * (including broadcast, since it is all ones)
+ */
+#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1)
+
+
+/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */
+#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)
+
+/* copy an ethernet address - assumes the pointers can be referenced as shorts */
+#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)
+
+/* Copy an ethernet address in reverse order */
+#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)
+
+/* Copy 14B ethernet header: 32bit aligned source and destination. */
+#define ehcopy32(s, d) \
+do { \
+	((uint32 *)(d))[0] = ((const uint32 *)(s))[0]; \
+	((uint32 *)(d))[1] = ((const uint32 *)(s))[1]; \
+	((uint32 *)(d))[2] = ((const uint32 *)(s))[2]; \
+	((uint16 *)(d))[6] = ((const uint16 *)(s))[6]; \
+} while (0)
+
+#ifdef DONGLEBUILD
+
+/* Dongles use bcmutils functions instead of macros.
+ * Possibly slower but saves over 800 bytes off THUMB dongle image.
+ */
+
+extern const struct ether_addr ether_bcast;
+extern const struct ether_addr ether_null;
+extern const struct ether_addr ether_ipv6_mcast;
+
+extern int ether_isbcast(const void *ea);
+extern int ether_isnulladdr(const void *ea);
+
+#define ETHER_ISBCAST(ea)	ether_isbcast(ea)
+#define ETHER_ISNULLADDR(ea)	ether_isnulladdr(ea)
+
+#else /* !DONGLEBUILD */
+
+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)
+
+#endif /* !DONGLEBUILD */
+
+#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)
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _NET_ETHERNET_H_ */
diff --git a/wl/components/shared/proto/event_log_payload.h b/wl/components/shared/proto/event_log_payload.h
new file mode 100644
index 0000000..aa1f9e6
--- /dev/null
+++ b/wl/components/shared/proto/event_log_payload.h
@@ -0,0 +1,668 @@
+/*
+ * EVENT_LOG System Definitions
+ *
+ * This file describes the payloads of event log entries that are data buffers
+ * rather than formatted string entries. The contents are generally XTLVs.
+ *
+ * Copyright (C) 2017, Broadcom. 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: event_log_payload.h 658172 2016-09-06 20:47:02Z $
+ */
+
+#ifndef _EVENT_LOG_PAYLOAD_H_
+#define _EVENT_LOG_PAYLOAD_H_
+
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <proto/ethernet.h>
+#include <proto/event_log_tag.h>
+
+#define EVENT_LOG_XTLV_ID_STR                   0  /**< XTLV ID for a string */
+#define EVENT_LOG_XTLV_ID_TXQ_SUM               1  /**< XTLV ID for txq_summary_t */
+#define EVENT_LOG_XTLV_ID_SCBDATA_SUM           2  /**< XTLV ID for cb_subq_summary_t */
+#define EVENT_LOG_XTLV_ID_SCBDATA_AMPDU_TX_SUM  3  /**< XTLV ID for scb_ampdu_tx_summary_t */
+#define EVENT_LOG_XTLV_ID_BSSCFGDATA_SUM        4  /**< XTLV ID for bsscfg_q_summary_t */
+#define EVENT_LOG_XTLV_ID_UCTXSTATUS            5  /**< XTLV ID for ucode TxStatus array */
+#define EVENT_LOG_XTLV_ID_TXQ_SUM_V2            6  /**< XTLV ID for txq_summary_v2_t */
+
+/**
+ * An XTLV holding a string
+ * String is not null terminated, length is the XTLV len.
+ */
+typedef struct xtlv_string {
+	uint16 id;              /* XTLV ID: EVENT_LOG_XTLV_ID_STR */
+	uint16 len;             /* XTLV Len (String length) */
+	char   str[1];          /* var len array characters */
+} xtlv_string_t;
+
+#define XTLV_STRING_FULL_LEN(str_len)     (BCM_XTLV_HDR_SIZE + (str_len) * sizeof(char))
+
+/**
+ * Summary for a single TxQ context
+ * Two of these will be used per TxQ context---one for the high TxQ, and one for
+ * the low txq that contains DMA prepared pkts. The high TxQ is a full multi-precidence
+ * queue and also has a BSSCFG map to identify the BSSCFGS associated with the queue context.
+ * The low txq counterpart does not populate the BSSCFG map.
+ * The excursion queue will have no bsscfgs associated and is the first queue dumped.
+ */
+typedef struct txq_summary {
+	uint16 id;              /* XTLV ID: EVENT_LOG_XTLV_ID_TXQ_SUM */
+	uint16 len;             /* XTLV Len */
+	uint32 bsscfg_map;      /* bitmap of bsscfg indexes associated with this queue */
+	uint32 stopped;         /* flow control bitmap */
+	uint8  prec_count;      /* count of precedences/fifos and len of following array */
+	uint8  pad;
+	uint16 plen[1];         /* var len array of lengths of each prec/fifo in the queue */
+} txq_summary_t;
+
+#define TXQ_SUMMARY_LEN                   (OFFSETOF(txq_summary_t, plen))
+#define TXQ_SUMMARY_FULL_LEN(num_q)       (TXQ_SUMMARY_LEN + (num_q) * sizeof(uint16))
+
+typedef struct txq_summary_v2 {
+	uint16 id;              /* XTLV ID: EVENT_LOG_XTLV_ID_TXQ_SUM_V2 */
+	uint16 len;             /* XTLV Len */
+	uint32 bsscfg_map;      /* bitmap of bsscfg indexes associated with this queue */
+	uint32 stopped;         /* flow control bitmap */
+	uint32 hw_stopped;      /* flow control bitmap */
+	uint8  prec_count;      /* count of precedences/fifos and len of following array */
+	uint8  pad;
+	uint16 plen[1];         /* var len array of lengths of each prec/fifo in the queue */
+} txq_summary_v2_t;
+
+#define TXQ_SUMMARY_V2_LEN                (OFFSETOF(txq_summary_v2_t, plen))
+#define TXQ_SUMMARY_V2_FULL_LEN(num_q)    (TXQ_SUMMARY_V2_LEN + (num_q) * sizeof(uint16))
+
+/**
+ * Summary for tx datapath of an SCB cubby
+ * This is a generic summary structure (one size fits all) with
+ * a cubby ID and sub-ID to differentiate SCB cubby types and possible sub-queues.
+ */
+typedef struct scb_subq_summary {
+	uint16 id;             /* XTLV ID: EVENT_LOG_XTLV_ID_SCBDATA_SUM */
+	uint16 len;            /* XTLV Len */
+	uint32 flags;          /* cubby specficic flags */
+	uint8  cubby_id;       /* ID registered for cubby */
+	uint8  sub_id;         /* sub ID if a cubby has more than one queue */
+	uint8  prec_count;     /* count of precedences/fifos and len of following array */
+	uint8  pad;
+	uint16 plen[1];        /* var len array of lengths of each prec/fifo in the queue */
+} scb_subq_summary_t;
+
+#define SCB_SUBQ_SUMMARY_LEN              (OFFSETOF(scb_subq_summary_t, plen))
+#define SCB_SUBQ_SUMMARY_FULL_LEN(num_q)  (SCB_SUBQ_SUMMARY_LEN + (num_q) * sizeof(uint16))
+
+/* scb_subq_summary_t.flags for APPS */
+#define SCBDATA_APPS_F_PS               0x00000001
+#define SCBDATA_APPS_F_PSPEND           0x00000002
+#define SCBDATA_APPS_F_INPVB            0x00000004
+#define SCBDATA_APPS_F_APSD_USP         0x00000008
+#define SCBDATA_APPS_F_TXBLOCK          0x00000010
+#define SCBDATA_APPS_F_APSD_HPKT_TMR    0x00000020
+#define SCBDATA_APPS_F_APSD_TX_PEND     0x00000040
+#define SCBDATA_APPS_F_INTRANS          0x00000080
+#define SCBDATA_APPS_F_OFF_PEND         0x00000100
+#define SCBDATA_APPS_F_OFF_BLOCKED      0x00000200
+#define SCBDATA_APPS_F_OFF_IN_PROG      0x00000400
+
+
+/**
+ * Summary for tx datapath AMPDU SCB cubby
+ * This is a specific data structure to describe the AMPDU datapath state for an SCB
+ * used instead of scb_subq_summary_t.
+ * Info is for one TID, so one will be dumped per BA TID active for an SCB.
+ */
+typedef struct scb_ampdu_tx_summary {
+	uint16 id;              /* XTLV ID: EVENT_LOG_XTLV_ID_SCBDATA_AMPDU_TX_SUM */
+	uint16 len;             /* XTLV Len */
+	uint32 flags;           /* misc flags */
+	uint8  tid;             /* initiator TID (priority) */
+	uint8  ba_state;        /* internal BA state */
+	uint8  bar_cnt;         /* number of bars sent with no progress */
+	uint8  retry_bar;       /* reason code if bar to be retried at watchdog */
+	uint16 barpending_seq;  /* seqnum for bar */
+	uint16 bar_ackpending_seq; /* seqnum of bar for which ack is pending */
+	uint16 start_seq;       /* seqnum of the first unacknowledged packet */
+	uint16 max_seq;         /* max unacknowledged seqnum sent */
+	uint32 released_bytes_inflight; /* Number of bytes pending in bytes */
+	uint32 released_bytes_target;
+} scb_ampdu_tx_summary_t;
+
+/* scb_ampdu_tx_summary.flags defs */
+#define SCBDATA_AMPDU_TX_F_BAR_ACKPEND          0x00000001 /* bar_ackpending */
+
+/** XTLV stuct to summarize a BSSCFG's packet queue */
+typedef struct bsscfg_q_summary {
+	uint16 id;               /* XTLV ID: EVENT_LOG_XTLV_ID_BSSCFGDATA_SUM */
+	uint16 len;              /* XTLV Len */
+	struct ether_addr BSSID; /* BSSID */
+	uint8  bsscfg_idx;       /* bsscfg index */
+	uint8  type;             /* bsscfg type enumeration: BSSCFG_TYPE_XXX */
+	uint8  subtype;          /* bsscfg subtype enumeration: BSSCFG_SUBTYPE_XXX */
+	uint8  prec_count;       /* count of precedences/fifos and len of following array */
+	uint16 plen[1];          /* var len array of lengths of each prec/fifo in the queue */
+} bsscfg_q_summary_t;
+
+#define BSSCFG_Q_SUMMARY_LEN              (OFFSETOF(bsscfg_q_summary_t, plen))
+#define BSSCFG_Q_SUMMARY_FULL_LEN(num_q)  (BSSCFG_Q_SUMMARY_LEN + (num_q) * sizeof(uint16))
+
+/**
+ * An XTLV holding a TxStats array
+ * TxStatus entries are 8 or 16 bytes, size in words (2 or 4) givent in
+ * entry_size field.
+ * Array is uint32 words
+ */
+typedef struct xtlv_uc_txs {
+	uint16 id;              /* XTLV ID: EVENT_LOG_XTLV_ID_UCTXSTATUS */
+	uint16 len;             /* XTLV Len */
+	uint8  entry_size;      /* num uint32 words per entry */
+	uint8  pad[3];          /* reserved, zero */
+	uint32 w[1];            /* var len array of words */
+} xtlv_uc_txs_t;
+
+#define XTLV_UCTXSTATUS_LEN                (OFFSETOF(xtlv_uc_txs_t, w))
+#define XTLV_UCTXSTATUS_FULL_LEN(words)    (XTLV_UCTXSTATUS_LEN + (words) * sizeof(uint32))
+
+#define SCAN_SUMMARY_VERSION	1
+/* Scan flags */
+#define SCAN_SUM_CHAN_INFO	0x1
+/* Scan_sum flags */
+#define BAND5G_SIB_ENAB	0x2
+#define BAND2G_SIB_ENAB	0x4
+#define PARALLEL_SCAN	0x8
+#define SCAN_ABORT	0x10
+
+/* scan_channel_info flags */
+#define ACTIVE_SCAN_SCN_SUM	0x2
+#define SCAN_SUM_WLC_CORE0	0x4
+#define SCAN_SUM_WLC_CORE1	0x8
+#define HOME_CHAN	0x10
+
+typedef struct wl_scan_ssid_info
+{
+	uint8		ssid_len;	/* the length of SSID */
+	uint8		ssid[32];	/* SSID string */
+} wl_scan_ssid_info_t;
+
+typedef struct wl_scan_channel_info {
+	uint16 chanspec;	/* chanspec scanned */
+	uint16 reserv;
+	uint32 start_time;		/* Scan start time in
+				* milliseconds for the chanspec
+				* or home_dwell time start
+				*/
+	uint32 end_time;		/* Scan end time in
+				* milliseconds for the chanspec
+				* or home_dwell time end
+				*/
+	uint16 probe_count;	/* No of probes sent out. For future use
+				*/
+	uint16 scn_res_count;	/* Count of scan_results found per
+				* channel. For future use
+				*/
+} wl_scan_channel_info_t;
+
+typedef struct wl_scan_summary_info {
+	uint32 total_chan_num;	/* Total number of channels scanned */
+	uint32 scan_start_time;	/* Scan start time in milliseconds */
+	uint32 scan_end_time;	/* Scan end time in milliseconds */
+	wl_scan_ssid_info_t ssid[1];	/* SSID being scanned in current
+				* channel. For future use
+				*/
+} wl_scan_summary_info_t;
+
+struct wl_scan_summary {
+	uint8 version;		/* Version */
+	uint8 reserved;
+	uint16 len;		/* Length of the data buffer including SSID
+				 * list.
+				 */
+	uint16 sync_id;		/* Scan Sync ID */
+	uint16 scan_flags;		/* flags [0] or SCAN_SUM_CHAN_INFO = */
+				/* channel_info, if not set */
+				/* it is scan_summary_info */
+				/* when channel_info is used, */
+				/* the following flag bits are overridden: */
+				/* flags[1] or ACTIVE_SCAN_SCN_SUM = active channel if set */
+				/* passive if not set */
+				/* flags[2] or WLC_CORE0 = if set, represents wlc_core0 */
+				/* flags[3] or WLC_CORE1 = if set, represents wlc_core1 */
+				/* flags[4] or HOME_CHAN = if set, represents home-channel */
+				/* flags[5:15] = reserved */
+				/* when scan_summary_info is used, */
+				/* the following flag bits are used: */
+				/* flags[1] or BAND5G_SIB_ENAB = */
+				/* allowSIBParallelPassiveScan on 5G band */
+				/* flags[2] or BAND2G_SIB_ENAB = */
+				/* allowSIBParallelPassiveScan on 2G band */
+				/* flags[3] or PARALLEL_SCAN = Parallel scan enabled or not */
+				/* flags[4] or SCAN_ABORT = SCAN_ABORTED scenario */
+				/* flags[5:15] = reserved */
+	union {
+		wl_scan_channel_info_t scan_chan_info;	/* scan related information
+							* for each channel scanned
+							*/
+		wl_scan_summary_info_t scan_sum_info;	/* Cumulative scan related
+							* information.
+							*/
+	} u;
+};
+
+/* Channel switch log record structure
+ * Host may map the following structure on channel switch event log record
+ * received from dongle. Note that all payload entries in event log record are
+ * uint32/int32.
+ * THIS IS HTE SAME AS wl_chansw_event_log (as in src/include/wlioctl.h)!!!
+ */
+typedef struct wl_chansw_event_log {
+	uint32 time;			/* Time in us */
+	uint32 old_chanspec;		/* Old channel spec */
+	uint32 new_chanspec;		/* New channel spec */
+	uint32 chansw_reason;		/* Reason for channel change */
+	int32 dwell_time;
+} wl_chansw_event_log_t;
+
+/* Sub-block type for EVENT_LOG_TAG_AMPDU_DUMP */
+#define WL_AMPDU_STATS_CNT_RXMCSx1	0	/* RX MCS rate (Nss = 1) */
+#define WL_AMPDU_STATS_CNT_RXMCSx2	1
+#define WL_AMPDU_STATS_CNT_RXMCSx3	2
+#define WL_AMPDU_STATS_CNT_RXMCSx4	3
+#define WL_AMPDU_STATS_CNT_RXVHTx1	4	/* RX VHT rate (Nss = 1) */
+#define WL_AMPDU_STATS_CNT_RXVHTx2	5
+#define WL_AMPDU_STATS_CNT_RXVHTx3	6
+#define WL_AMPDU_STATS_CNT_RXVHTx4	7
+#define WL_AMPDU_STATS_CNT_TXMCSx1	8	/* TX MCS rate (Nss = 1) */
+#define WL_AMPDU_STATS_CNT_TXMCSx2	9
+#define WL_AMPDU_STATS_CNT_TXMCSx3	10
+#define WL_AMPDU_STATS_CNT_TXMCSx4	11
+#define WL_AMPDU_STATS_CNT_TXVHTx1	12	/* TX VHT rate (Nss = 1) */
+#define WL_AMPDU_STATS_CNT_TXVHTx2	13
+#define WL_AMPDU_STATS_CNT_TXVHTx3	14
+#define WL_AMPDU_STATS_CNT_TXVHTx4	15
+#define WL_AMPDU_STATS_CNT_RXMCSSGI	16	/* RX SGI usage (for all MCS rates) */
+#define WL_AMPDU_STATS_CNT_TXMCSSGI	17	/* TX SGI usage (for all MCS rates) */
+#define WL_AMPDU_STATS_CNT_RXVHTSGI	18	/* RX SGI usage (for all VHT rates) */
+#define WL_AMPDU_STATS_CNT_TXVHTSGI	19	/* TX SGI usage (for all VHT rates) */
+#define WL_AMPDU_STATS_CNT_RXMCSPER	20	/* RX PER (for all MCS rates) */
+#define WL_AMPDU_STATS_CNT_TXMCSPER	21	/* TX PER (for all MCS rates) */
+#define WL_AMPDU_STATS_CNT_RXVHTPER	22	/* RX PER (for all VHT rates) */
+#define WL_AMPDU_STATS_CNT_TXVHTPER	23	/* TX PER (for all VHT rates) */
+#define WL_AMPDU_STATS_CNT_RXDENS	24	/* RX AMPDU density */
+#define WL_AMPDU_STATS_CNT_TXDENS	25	/* TX AMPDU density */
+#define WL_AMPDU_STATS_CNT_RXMCSOK	26	/* RX all MCS rates */
+#define WL_AMPDU_STATS_CNT_RXVHTOK	27	/* RX all VHT rates */
+#define WL_AMPDU_STATS_CNT_TXMCSALL	28	/* TX all MCS rates */
+#define WL_AMPDU_STATS_CNT_TXVHTALL	29	/* TX all VHT rates */
+#define WL_AMPDU_STATS_CNT_TXMCSOK	30	/* TX all MCS rates */
+#define WL_AMPDU_STATS_CNT_TXVHTOK	31	/* TX all VHT rates */
+
+#define WL_AMPDU_STATS_CNT_MAX		64
+
+typedef struct {
+	uint16	type;		/* AMPDU statistics sub-type */
+	uint16	len;		/* Number of 32-bit counters */
+	uint32	counters[WL_AMPDU_STATS_CNT_MAX];
+} wl_ampdu_stats_cnt_generic_t;
+
+typedef struct {
+	uint16	type;		/* AMPDU statistics sub-type */
+	uint16	len;		/* Number of 32-bit counters + 2 */
+	uint32	total_ampdu;
+	uint32	total_mpdu;
+	uint32	aggr_dist[WL_AMPDU_STATS_CNT_MAX + 1];
+} wl_ampdu_stats_cnt_aggrsz_t;
+
+/* Sub-block type for EVENT_LOG_TAG_MSCHPROFILE */
+#define WL_MSCH_PROFILER_START		0	/* start event check */
+#define WL_MSCH_PROFILER_EXIT		1	/* exit event check */
+#define WL_MSCH_PROFILER_REQ		2	/* request event */
+#define WL_MSCH_PROFILER_CALLBACK	3	/* call back event */
+#define WL_MSCH_PROFILER_MESSAGE	4	/* message event */
+#define WL_MSCH_PROFILER_PROFILE_START	5
+#define WL_MSCH_PROFILER_PROFILE_END	6
+#define WL_MSCH_PROFILER_REQ_HANDLE	7
+#define WL_MSCH_PROFILER_REQ_ENTITY	8
+#define WL_MSCH_PROFILER_CHAN_CTXT	9
+#define WL_MSCH_PROFILER_EVENT_LOG	10
+#define WL_MSCH_PROFILER_REQ_TIMING	11
+#define WL_MSCH_PROFILER_TYPE_MASK	0x00ff
+#define WL_MSCH_PROFILER_WLINDEX_SHIFT	8
+#define WL_MSCH_PROFILER_WLINDEX_MASK	0x0f00
+#define WL_MSCH_PROFILER_VER_SHIFT	12
+#define WL_MSCH_PROFILER_VER_MASK	0xf000
+
+/* MSCH Event data current verion */
+#define WL_MSCH_PROFILER_VER		2
+
+/* msch version history */
+#define WL_MSCH_PROFILER_RSDB_VER	1
+#define WL_MSCH_PROFILER_REPORT_VER	2
+
+/* msch collect header size */
+#define WL_MSCH_PROFILE_HEAD_SIZE	OFFSETOF(msch_collect_tlv_t, value)
+
+/* msch event log header size */
+#define WL_MSCH_EVENT_LOG_HEAD_SIZE	OFFSETOF(msch_event_log_profiler_event_data_t, data)
+
+/* MSCH data buffer size */
+#define WL_MSCH_PROFILER_BUFFER_SIZE	512
+
+/* request type used in wlc_msch_req_param_t struct */
+#define WL_MSCH_RT_BOTH_FIXED	0	/* both start and end time is fixed */
+#define WL_MSCH_RT_START_FLEX	1	/* start time is flexible and duration is fixed */
+#define WL_MSCH_RT_DUR_FLEX	2	/* start time is fixed and end time is flexible */
+#define WL_MSCH_RT_BOTH_FLEX	3	/* Both start and duration is flexible */
+
+/* Flags used in wlc_msch_req_param_t struct */
+#define WL_MSCH_REQ_FLAGS_CHAN_CONTIGUOUS  (1 << 0) /* Don't break up channels in chanspec_list */
+#define WL_MSCH_REQ_FLAGS_MERGE_CONT_SLOTS (1 << 1)  /* No slot end if slots are continous */
+#define WL_MSCH_REQ_FLAGS_PREMTABLE        (1 << 2) /* Req can be pre-empted by PREMT_CURTS req */
+#define WL_MSCH_REQ_FLAGS_PREMT_CURTS      (1 << 3) /* Pre-empt request at the end of curts */
+#define WL_MSCH_REQ_FLAGS_PREMT_IMMEDIATE  (1 << 4) /* Pre-empt cur_ts immediately */
+
+/* Requested slot Callback states
+ * req->pend_slot/cur_slot->flags
+ */
+#define WL_MSCH_RC_FLAGS_ONCHAN_FIRE		(1 << 0)
+#define WL_MSCH_RC_FLAGS_START_FIRE_DONE	(1 << 1)
+#define WL_MSCH_RC_FLAGS_END_FIRE_DONE		(1 << 2)
+#define WL_MSCH_RC_FLAGS_ONFIRE_DONE		(1 << 3)
+#define WL_MSCH_RC_FLAGS_SPLIT_SLOT_START	(1 << 4)
+#define WL_MSCH_RC_FLAGS_SPLIT_SLOT_END		(1 << 5)
+#define WL_MSCH_RC_FLAGS_PRE_ONFIRE_DONE	(1 << 6)
+
+/* Request entity flags */
+#define WL_MSCH_ENTITY_FLAG_MULTI_INSTANCE	(1 << 0)
+
+/* Request Handle flags */
+#define WL_MSCH_REQ_HDL_FLAGS_NEW_REQ		(1 << 0) /* req_start callback */
+
+/* MSCH state flags (msch_info->flags) */
+#define	WL_MSCH_STATE_IN_TIEMR_CTXT		0x1
+#define WL_MSCH_STATE_SCHD_PENDING		0x2
+
+/* MSCH callback type */
+#define	WL_MSCH_CT_REQ_START		0x1
+#define	WL_MSCH_CT_ON_CHAN		0x2
+#define	WL_MSCH_CT_SLOT_START		0x4
+#define	WL_MSCH_CT_SLOT_END		0x8
+#define	WL_MSCH_CT_SLOT_SKIP		0x10
+#define	WL_MSCH_CT_OFF_CHAN		0x20
+#define WL_MSCH_CT_OFF_CHAN_DONE	0x40
+#define	WL_MSCH_CT_REQ_END		0x80
+#define	WL_MSCH_CT_PARTIAL		0x100
+#define	WL_MSCH_CT_PRE_ONCHAN		0x200
+#define	WL_MSCH_CT_PRE_REQ_START	0x400
+
+/* MSCH command bits */
+#define WL_MSCH_CMD_ENABLE_BIT		0x01
+#define WL_MSCH_CMD_PROFILE_BIT		0x02
+#define WL_MSCH_CMD_CALLBACK_BIT	0x04
+#define WL_MSCH_CMD_REGISTER_BIT	0x08
+#define WL_MSCH_CMD_ERROR_BIT		0x10
+#define WL_MSCH_CMD_DEBUG_BIT		0x20
+#define WL_MSCH_CMD_INFOM_BIT		0x40
+#define WL_MSCH_CMD_TRACE_BIT		0x80
+#define WL_MSCH_CMD_ALL_BITS		0xfe
+#define WL_MSCH_CMD_SIZE_MASK		0x00ff0000
+#define WL_MSCH_CMD_SIZE_SHIFT		16
+#define WL_MSCH_CMD_VER_MASK		0xff000000
+#define WL_MSCH_CMD_VER_SHIFT		24
+
+/* maximum channels returned by the get valid channels iovar */
+#define WL_MSCH_NUMCHANNELS		64
+
+typedef struct msch_collect_tlv {
+	uint16	type;
+	uint16	size;
+	char	value[1];
+} msch_collect_tlv_t;
+
+typedef struct msch_profiler_event_data {
+	uint32	time_lo;		/* Request time */
+	uint32	time_hi;
+} msch_profiler_event_data_t;
+
+typedef struct msch_start_profiler_event_data {
+	uint32	time_lo;		/* Request time */
+	uint32	time_hi;
+	uint32	status;
+} msch_start_profiler_event_data_t;
+
+typedef struct msch_message_profiler_event_data {
+	uint32	time_lo;		/* Request time */
+	uint32	time_hi;
+	char	message[1];		/* message */
+} msch_message_profiler_event_data_t;
+
+typedef struct msch_event_log_profiler_event_data {
+	uint32	time_lo;		/* Request time */
+	uint32	time_hi;
+	event_log_hdr_t hdr;		/* event log header */
+	uint32	data[9];		/* event data */
+} msch_event_log_profiler_event_data_t;
+
+typedef struct msch_req_param_profiler_event_data {
+	uint16  flags;			/* Describe various request properties */
+	uint8	req_type;		/* Describe start and end time flexiblilty */
+	uint8	priority;		/* Define the request priority */
+	uint32	start_time_l;		/* Requested start time offset in us unit */
+	uint32	start_time_h;
+	uint32	duration;		/* Requested duration in us unit */
+	uint32	interval;		/* Requested periodic interval in us unit,
+					 * 0 means non-periodic
+					 */
+	union {
+		uint32	dur_flex;	/* MSCH_REG_DUR_FLEX, min_dur = duration - dur_flex */
+		struct {
+			uint32 min_dur;	/* min duration for traffic, maps to home_time */
+			uint32 max_away_dur; /* max acceptable away dur, maps to home_away_time */
+			uint32 hi_prio_time_l;
+			uint32 hi_prio_time_h;
+			uint32 hi_prio_interval; /* repeated high priority interval */
+		} bf;
+	} flex;
+} msch_req_param_profiler_event_data_t;
+
+typedef struct msch_req_timing_profiler_event_data {
+	uint32 p_req_timing;
+	uint32 p_prev;
+	uint32 p_next;
+	uint16 flags;
+	uint16 timeslot_ptr;
+	uint32 fire_time_l;
+	uint32 fire_time_h;
+	uint32 pre_start_time_l;
+	uint32 pre_start_time_h;
+	uint32 start_time_l;
+	uint32 start_time_h;
+	uint32 end_time_l;
+	uint32 end_time_h;
+	uint32 p_timeslot;
+} msch_req_timing_profiler_event_data_t;
+
+typedef struct msch_chan_ctxt_profiler_event_data {
+	uint32 p_chan_ctxt;
+	uint32 p_prev;
+	uint32 p_next;
+	uint16 chanspec;
+	uint16 bf_sch_pending;
+	uint32 bf_link_prev;
+	uint32 bf_link_next;
+	uint32 onchan_time_l;
+	uint32 onchan_time_h;
+	uint32 actual_onchan_dur_l;
+	uint32 actual_onchan_dur_h;
+	uint32 pend_onchan_dur_l;
+	uint32 pend_onchan_dur_h;
+	uint16 req_entity_list_cnt;
+	uint16 req_entity_list_ptr;
+	uint16 bf_entity_list_cnt;
+	uint16 bf_entity_list_ptr;
+	uint32 bf_skipped_count;
+} msch_chan_ctxt_profiler_event_data_t;
+
+typedef struct msch_req_entity_profiler_event_data {
+	uint32 p_req_entity;
+	uint32 req_hdl_link_prev;
+	uint32 req_hdl_link_next;
+	uint32 chan_ctxt_link_prev;
+	uint32 chan_ctxt_link_next;
+	uint32 rt_specific_link_prev;
+	uint32 rt_specific_link_next;
+	uint32 start_fixed_link_prev;
+	uint32 start_fixed_link_next;
+	uint32 both_flex_list_prev;
+	uint32 both_flex_list_next;
+	uint16 chanspec;
+	uint16 priority;
+	uint16 cur_slot_ptr;
+	uint16 pend_slot_ptr;
+	uint16 pad;
+	uint16 chan_ctxt_ptr;
+	uint32 p_chan_ctxt;
+	uint32 p_req_hdl;
+	uint32 bf_last_serv_time_l;
+	uint32 bf_last_serv_time_h;
+	uint16 onchan_chn_idx;
+	uint16 cur_chn_idx;
+	uint32 flags;
+	uint32 actual_start_time_l;
+	uint32 actual_start_time_h;
+	uint32 curts_fire_time_l;
+	uint32 curts_fire_time_h;
+} msch_req_entity_profiler_event_data_t;
+
+typedef struct msch_req_handle_profiler_event_data {
+	uint32 p_req_handle;
+	uint32 p_prev;
+	uint32 p_next;
+	uint32 cb_func;
+	uint32 cb_ctxt;
+	uint16 req_param_ptr;
+	uint16 req_entity_list_cnt;
+	uint16 req_entity_list_ptr;
+	uint16 chan_cnt;
+	uint32 flags;
+	uint16 chanspec_list;
+	uint16 chanspec_cnt;
+	uint16 chan_idx;
+	uint16 last_chan_idx;
+	uint32 req_time_l;
+	uint32 req_time_h;
+} msch_req_handle_profiler_event_data_t;
+
+typedef struct msch_profiler_profiler_event_data {
+	uint32 time_lo;			/* Request time */
+	uint32 time_hi;
+	uint32 free_req_hdl_list;
+	uint32 free_req_entity_list;
+	uint32 free_chan_ctxt_list;
+	uint32 free_chanspec_list;
+	uint16 cur_msch_timeslot_ptr;
+	uint16 next_timeslot_ptr;
+	uint32 p_cur_msch_timeslot;
+	uint32 p_next_timeslot;
+	uint32 cur_armed_timeslot;
+	uint32 flags;
+	uint32 ts_id;
+	uint32 service_interval;
+	uint32 max_lo_prio_interval;
+	uint16 flex_list_cnt;
+	uint16 msch_chanspec_alloc_cnt;
+	uint16 msch_req_entity_alloc_cnt;
+	uint16 msch_req_hdl_alloc_cnt;
+	uint16 msch_chan_ctxt_alloc_cnt;
+	uint16 msch_timeslot_alloc_cnt;
+	uint16 msch_req_hdl_list_cnt;
+	uint16 msch_req_hdl_list_ptr;
+	uint16 msch_chan_ctxt_list_cnt;
+	uint16 msch_chan_ctxt_list_ptr;
+	uint16 msch_req_timing_list_cnt;
+	uint16 msch_req_timing_list_ptr;
+	uint16 msch_start_fixed_list_cnt;
+	uint16 msch_start_fixed_list_ptr;
+	uint16 msch_both_flex_req_entity_list_cnt;
+	uint16 msch_both_flex_req_entity_list_ptr;
+	uint16 msch_start_flex_list_cnt;
+	uint16 msch_start_flex_list_ptr;
+	uint16 msch_both_flex_list_cnt;
+	uint16 msch_both_flex_list_ptr;
+	uint32 slotskip_flag;
+} msch_profiler_profiler_event_data_t;
+
+typedef struct msch_req_profiler_event_data {
+	uint32 time_lo;			/* Request time */
+	uint32 time_hi;
+	uint16 chanspec_cnt;
+	uint16 chanspec_ptr;
+	uint16 req_param_ptr;
+	uint16 pad;
+} msch_req_profiler_event_data_t;
+
+typedef struct msch_callback_profiler_event_data {
+	uint32 time_lo;			/* Request time */
+	uint32 time_hi;
+	uint16 type;			/* callback type */
+	uint16 chanspec;		/* actual chanspec, may different with requested one */
+	uint32 start_time_l;		/* time slot start time low 32bit */
+	uint32 start_time_h;		/* time slot start time high 32bit */
+	uint32 end_time_l;		/* time slot end time low 32 bit */
+	uint32 end_time_h;		/* time slot end time high 32 bit */
+	uint32 timeslot_id;		/* unique time slot id */
+	uint32 p_req_hdl;
+	uint32 onchan_idx;		/* Current channel index */
+	uint32 cur_chan_seq_start_time_l; /* start time of current sequence */
+	uint32 cur_chan_seq_start_time_h;
+} msch_callback_profiler_event_data_t;
+
+typedef struct msch_timeslot_profiler_event_data {
+	uint32 p_timeslot;
+	uint32 timeslot_id;
+	uint32 pre_start_time_l;
+	uint32 pre_start_time_h;
+	uint32 end_time_l;
+	uint32 end_time_h;
+	uint32 sch_dur_l;
+	uint32 sch_dur_h;
+	uint32 p_chan_ctxt;
+	uint32 fire_time_l;
+	uint32 fire_time_h;
+	uint32 state;
+} msch_timeslot_profiler_event_data_t;
+
+typedef struct msch_register_params	{
+	uint16 wlc_index;		/* Optional wlc index */
+	uint16 flags;			/* Describe various request properties */
+	uint32 req_type;		/* Describe start and end time flexiblilty */
+	uint16 id;			/* register id */
+	uint16 priority;		/* Define the request priority */
+	uint32 start_time;		/* Requested start time offset in ms unit */
+	uint32 duration;		/* Requested duration in ms unit */
+	uint32 interval;		/* Requested periodic interval in ms unit,
+					 * 0 means non-periodic
+					 */
+	uint32 dur_flex;		/* MSCH_REG_DUR_FLEX, min_dur = duration - dur_flex */
+	uint32 min_dur;			/* min duration for traffic, maps to home_time */
+	uint32 max_away_dur;		/* max acceptable away dur, maps to home_away_time */
+	uint32 hi_prio_time;
+	uint32 hi_prio_interval;	/* repeated high priority interval */
+	uint32 chanspec_cnt;
+	uint16 chanspec_list[WL_MSCH_NUMCHANNELS];
+} msch_register_params_t;
+
+#endif /* _EVENT_LOG_PAYLOAD_H_ */
diff --git a/wl/components/shared/proto/event_log_set.h b/wl/components/shared/proto/event_log_set.h
new file mode 100644
index 0000000..fc9cc0d
--- /dev/null
+++ b/wl/components/shared/proto/event_log_set.h
@@ -0,0 +1,40 @@
+/*
+ * EVENT_LOG system definitions
+ *
+ * Copyright (C) 2017, Broadcom. 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: event_log_set.h 585396 2015-09-10 09:04:56Z $
+ */
+
+#ifndef _EVENT_LOG_SET_H_
+#define _EVENT_LOG_SET_H_
+
+/* Set a maximum number of sets here.  It is not dynamic for
+ *  efficiency of the EVENT_LOG calls.
+ */
+#define NUM_EVENT_LOG_SETS 8
+
+/* Define new event log sets here */
+#define EVENT_LOG_SET_BUS	0
+#define EVENT_LOG_SET_WL	1
+#define EVENT_LOG_SET_PSM	2
+#define EVENT_LOG_SET_ERROR	3
+#define EVENT_LOG_SET_MEM_API	4
+#define EVENT_LOG_SET_ECOUNTERS 5	/* Host to instantiate this for ecounters. */
+
+#endif /* _EVENT_LOG_SET_H_ */
diff --git a/wl/components/shared/proto/event_log_tag.h b/wl/components/shared/proto/event_log_tag.h
new file mode 100644
index 0000000..187d174
--- /dev/null
+++ b/wl/components/shared/proto/event_log_tag.h
@@ -0,0 +1,196 @@
+/*
+ * EVENT_LOG system definitions
+ *
+ * Copyright (C) 2017, Broadcom. 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: event_log_tag.h 660406 2016-09-20 11:21:19Z $
+ */
+
+#ifndef _EVENT_LOG_TAG_H_
+#define _EVENT_LOG_TAG_H_
+
+#include <typedefs.h>
+
+/* Define new event log tags here */
+#define EVENT_LOG_TAG_NULL	0	/* Special null tag */
+#define EVENT_LOG_TAG_TS	1	/* Special timestamp tag */
+#define EVENT_LOG_TAG_BUS_OOB	2
+#define EVENT_LOG_TAG_BUS_STATE	3
+#define EVENT_LOG_TAG_BUS_PROTO	4
+#define EVENT_LOG_TAG_BUS_CTL	5
+#define EVENT_LOG_TAG_BUS_EVENT	6
+#define EVENT_LOG_TAG_BUS_PKT	7
+#define EVENT_LOG_TAG_BUS_FRAME	8
+#define EVENT_LOG_TAG_BUS_DESC	9
+#define EVENT_LOG_TAG_BUS_SETUP	10
+#define EVENT_LOG_TAG_BUS_MISC	11
+#define EVENT_LOG_TAG_SRSCAN		22
+#define EVENT_LOG_TAG_PWRSTATS_INFO	23
+#define EVENT_LOG_TAG_UCODE_WATCHDOG 26
+#define EVENT_LOG_TAG_UCODE_FIFO 27
+#define EVENT_LOG_TAG_SCAN_TRACE_LOW	28
+#define EVENT_LOG_TAG_SCAN_TRACE_HIGH	29
+#define EVENT_LOG_TAG_SCAN_ERROR	30
+#define EVENT_LOG_TAG_SCAN_WARN	31
+#define EVENT_LOG_TAG_MPF_ERR	32
+#define EVENT_LOG_TAG_MPF_WARN	33
+#define EVENT_LOG_TAG_MPF_INFO	34
+#define EVENT_LOG_TAG_MPF_DEBUG	35
+#define EVENT_LOG_TAG_EVENT_INFO	36
+#define EVENT_LOG_TAG_EVENT_ERR	37
+#define EVENT_LOG_TAG_PWRSTATS_ERROR	38
+#define EVENT_LOG_TAG_EXCESS_PM_ERROR	39
+#define EVENT_LOG_TAG_IOCTL_LOG			40
+#define EVENT_LOG_TAG_PFN_ERR	41
+#define EVENT_LOG_TAG_PFN_WARN	42
+#define EVENT_LOG_TAG_PFN_INFO	43
+#define EVENT_LOG_TAG_PFN_DEBUG	44
+#define EVENT_LOG_TAG_BEACON_LOG	45
+#define EVENT_LOG_TAG_WNM_BSSTRANS_INFO 46
+#define EVENT_LOG_TAG_TRACE_CHANSW 47
+#define EVENT_LOG_TAG_PCI_ERROR	48
+#define EVENT_LOG_TAG_PCI_TRACE	49
+#define EVENT_LOG_TAG_PCI_WARN	50
+#define EVENT_LOG_TAG_PCI_INFO	51
+#define EVENT_LOG_TAG_PCI_DBG	52
+#define EVENT_LOG_TAG_PCI_DATA  53
+#define EVENT_LOG_TAG_PCI_RING	54
+/* EVENT_LOG_TAG_AWDL_TRACE_RANGING will be removed after wlc_ranging merge from IGUANA
+ * keeping it here to avoid compilation error on trunk
+ */
+#define EVENT_LOG_TAG_AWDL_TRACE_RANGING	55
+#define EVENT_LOG_TAG_RANGING_TRACE	55
+#define EVENT_LOG_TAG_WL_ERROR		56
+#define EVENT_LOG_TAG_PHY_ERROR		57
+#define EVENT_LOG_TAG_OTP_ERROR		58
+#define EVENT_LOG_TAG_NOTIF_ERROR	59
+#define EVENT_LOG_TAG_MPOOL_ERROR	60
+#define EVENT_LOG_TAG_OBJR_ERROR	61
+#define EVENT_LOG_TAG_DMA_ERROR		62
+#define EVENT_LOG_TAG_PMU_ERROR		63
+#define EVENT_LOG_TAG_BSROM_ERROR	64
+#define EVENT_LOG_TAG_SI_ERROR		65
+#define EVENT_LOG_TAG_ROM_PRINTF	66
+#define EVENT_LOG_TAG_RATE_CNT		67
+#define EVENT_LOG_TAG_CTL_MGT_CNT	68
+#define EVENT_LOG_TAG_AMPDU_DUMP	69
+#define EVENT_LOG_TAG_MEM_ALLOC_SUCC	70
+#define EVENT_LOG_TAG_MEM_ALLOC_FAIL	71
+#define EVENT_LOG_TAG_MEM_FREE		72
+#define EVENT_LOG_TAG_WL_ASSOC_LOG	73
+#define EVENT_LOG_TAG_WL_PS_LOG		74
+#define EVENT_LOG_TAG_WL_ROAM_LOG	75
+#define EVENT_LOG_TAG_WL_MPC_LOG	76
+#define EVENT_LOG_TAG_WL_WSEC_LOG	77
+#define EVENT_LOG_TAG_WL_WSEC_DUMP	78
+#define EVENT_LOG_TAG_WL_MCNX_LOG	79
+#define EVENT_LOG_TAG_HEALTH_CHECK_ERROR 80
+#define EVENT_LOG_TAG_HNDRTE_EVENT_ERROR 81
+#define EVENT_LOG_TAG_ECOUNTERS_ERROR	82
+#define EVENT_LOG_TAG_WL_COUNTERS	83
+#define EVENT_LOG_TAG_ECOUNTERS_IPCSTATS	84
+#define EVENT_LOG_TAG_WL_P2P_LOG            85
+#define EVENT_LOG_TAG_SDIO_ERROR		86
+#define EVENT_LOG_TAG_SDIO_TRACE		87
+#define EVENT_LOG_TAG_SDIO_DBG          88
+#define EVENT_LOG_TAG_SDIO_PRHDRS		89
+#define EVENT_LOG_TAG_SDIO_PRPKT		90
+#define EVENT_LOG_TAG_SDIO_INFORM		91
+#define EVENT_LOG_TAG_MIMO_PS_ERROR	92
+#define EVENT_LOG_TAG_MIMO_PS_TRACE	93
+#define EVENT_LOG_TAG_MIMO_PS_INFO	94
+#define EVENT_LOG_TAG_BTCX_STATS	95
+#define EVENT_LOG_TAG_LEAKY_AP_STATS	96
+#define EVENT_LOG_TAG_AWDL_TRACE_ELECTION	97
+#define EVENT_LOG_TAG_MIMO_PS_STATS	98
+#define EVENT_LOG_TAG_PWRSTATS_PHY	99
+#define EVENT_LOG_TAG_PWRSTATS_SCAN	100
+#define EVENT_LOG_TAG_PWRSTATS_AWDL	101
+#define EVENT_LOG_TAG_PWRSTATS_WAKE_V2	102
+#define EVENT_LOG_TAG_LQM		103
+#define EVENT_LOG_TAG_TRACE_WL_INFO	104
+#define EVENT_LOG_TAG_TRACE_BTCOEX_INFO	105
+#define EVENT_LOG_TAG_ECOUNTERS_TIME_DATA	106
+#define EVENT_LOG_TAG_NAN_ERROR		107
+#define EVENT_LOG_TAG_NAN_INFO		108
+#define EVENT_LOG_TAG_NAN_DBG		109
+#define EVENT_LOG_TAG_STF_ARBITRATOR_ERROR	110
+#define EVENT_LOG_TAG_STF_ARBITRATOR_TRACE	111
+#define EVENT_LOG_TAG_STF_ARBITRATOR_WARN	112
+#define EVENT_LOG_TAG_SCAN_SUMMARY		113
+#define EVENT_LOG_TAG_PROXD_SAMPLE_COLLECT	114
+#define EVENT_LOG_TAG_OCL_INFO			115
+#define EVENT_LOG_TAG_RSDB_PMGR_DEBUG		116
+#define EVENT_LOG_TAG_RSDB_PMGR_ERR		117
+#define EVENT_LOG_TAG_NAT_ERR                   118
+#define EVENT_LOG_TAG_NAT_WARN                  119
+#define EVENT_LOG_TAG_NAT_INFO                  120
+#define EVENT_LOG_TAG_NAT_DEBUG                 121
+#define EVENT_LOG_TAG_STA_INFO			122
+#define EVENT_LOG_TAG_PROXD_ERROR		123
+#define EVENT_LOG_TAG_PROXD_TRACE		124
+#define EVENT_LOG_TAG_PROXD_INFO		125
+#define EVENT_LOG_TAG_IE_ERROR			126
+#define EVENT_LOG_TAG_ASSOC_ERROR		127
+#define EVENT_LOG_TAG_SCAN_ERR			128
+#define EVENT_LOG_TAG_AMSDU_ERROR		129
+#define EVENT_LOG_TAG_AMPDU_ERROR		130
+#define EVENT_LOG_TAG_KM_ERROR			131
+#define EVENT_LOG_TAG_DFS			132
+#define EVENT_LOG_TAG_REGULATORY		133
+#define EVENT_LOG_TAG_CSA			134
+#define EVENT_LOG_TAG_WNM_BSSTRANS_ERR		135
+#define EVENT_LOG_TAG_SUP_INFO			136
+#define EVENT_LOG_TAG_SUP_ERROR			137
+#define EVENT_LOG_TAG_CHANCTXT_TRACE		138
+#define EVENT_LOG_TAG_CHANCTXT_INFO		139
+#define EVENT_LOG_TAG_CHANCTXT_ERROR		140
+#define EVENT_LOG_TAG_CHANCTXT_WARN		141
+#define EVENT_LOG_TAG_MSCHPROFILE		142
+#define EVENT_LOG_TAG_4WAYHANDSHAKE		143
+#define EVENT_LOG_TAG_MSCHPROFILE_TLV		144
+
+/* EVENT_LOG_TAG_MAX	= Set to the same value of last tag, not last tag + 1 */
+#define EVENT_LOG_TAG_MAX			144
+/* Note: New event should be added/reserved in trunk before adding it to branches */
+
+
+#define	SD_PRHDRS(i, s, h, p, n, l)
+#define	SD_PRPKT(m, b, n)
+#define	SD_INFORM(args)
+
+/* Flags for tag control */
+#define EVENT_LOG_TAG_FLAG_NONE		0
+#define EVENT_LOG_TAG_FLAG_LOG		0x80
+#define EVENT_LOG_TAG_FLAG_PRINT	0x40
+#define EVENT_LOG_TAG_FLAG_SET_MASK	0x3f
+
+/* Each event log entry has a type.  The type is the LAST word of the
+ * event log.  The printing code walks the event entries in reverse
+ * order to find the first entry.
+ */
+typedef union event_log_hdr {
+	struct {
+		uint8 tag;		/* Event_log entry tag */
+		uint8 count;		/* Count of 4-byte entries */
+		uint16 fmt_num;		/* Format number */
+	};
+	uint32 t;			/* Type cheat */
+} event_log_hdr_t;
+
+#endif /* _EVENT_LOG_TAG_H_ */
diff --git a/wl/components/shared/proto/mbo.h b/wl/components/shared/proto/mbo.h
new file mode 100644
index 0000000..5fa8e07
--- /dev/null
+++ b/wl/components/shared/proto/mbo.h
@@ -0,0 +1,272 @@
+/*
+ * Fundamental types and constants relating to WFA MBO
+ * (Multiband Operation)
+ * Copyright (C) 2017, Broadcom. 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$
+ */
+
+#ifndef _MBO_H_
+#define _MBO_H_
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/* WiFi MBO OUI values */
+#define MBO_OUI         WFA_OUI      /* WiFi OUI 50:6F:9A */
+/* oui_type field identifying the type and version of the MBO IE. */
+#define MBO_OUI_TYPE    WFA_OUI_TYPE_MBO /* OUI Type/Version */
+/* IEEE 802.11 vendor specific information element. */
+#define MBO_IE_ID          0xdd
+
+/* MBO ATTR related macros */
+#define MBO_ATTR_ID_OFF         0
+#define MBO_ATTR_LEN_OFF        1
+#define MBO_ATTR_DATA_OFF       2
+
+#define MBO_ATTR_ID_LEN          1      /* Attr ID field length */
+#define MBO_ATTR_LEN_LEN         1      /* Attr Length field length */
+#define MBO_ATTR_HDR_LEN         2      /* ID + 1-byte length field */
+
+/* MBO subelemts related */
+#define MBO_SUBELEM_ID          0xdd
+#define MBO_SUBELEM_OUI         WFA_OUI
+
+#define MBO_SUBELEM_ID_LEN          1      /* SubElement ID field length */
+#define MBO_SUBELEM_LEN_LEN         1      /* SubElement length field length */
+#define MBO_SUBELEM_HDR_LEN         6      /* ID + length + OUI + OUY TYPE */
+
+#define MBO_NON_PREF_CHAN_SUBELEM_LEN_LEN(L)  (7 + (L))  /* value of length field */
+#define MBO_NON_PREF_CHAN_SUBELEM_TOT_LEN(L) \
+	(MBO_SUBELEM_ID_LEN + MBO_SUBELEM_LEN_LEN + MBO_NON_PREF_CHAN_SUBELEM_LEN_LEN(L))
+/* MBO attributes as defined in the mbo spec */
+enum {
+	MBO_ATTR_MBO_AP_CAPABILITY = 1,
+	MBO_ATTR_NON_PREF_CHAN_REPORT = 2,
+	MBO_ATTR_CELL_DATA_CAP = 3,
+	MBO_ATTR_ASSOC_DISALLOWED = 4,
+	MBO_ATTR_CELL_DATA_CONN_PREF = 5,
+	MBO_ATTR_TRANS_REASON_CODE = 6,
+	MBO_ATTR_TRANS_REJ_REASON_CODE = 7,
+	MBO_ATTR_ASSOC_RETRY_DELAY = 8
+};
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_mbo_ie_s {
+	uint8 id;      /* IE ID: MBO_IE_ID 0xDD */
+	uint8 len;     /* IE length */
+	uint8 oui[WFA_OUI_LEN]; /* MBO_OUI 50:6F:9A */
+	uint8 oui_type;   /* MBO_OUI_TYPE 0x16 */
+	uint8 attr[1]; /* var len attributes */
+} BWL_POST_PACKED_STRUCT wifi_mbo_ie_t;
+
+#define MBO_IE_HDR_SIZE (OFFSETOF(wifi_mbo_ie_t, attr))
+/* oui:3 bytes + oui type:1 byte */
+#define MBO_IE_NO_ATTR_LEN  4
+
+/* MBO AP Capability Attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_mbo_ap_cap_ind_attr_s {
+	/* Attribute ID - 0x01. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint8 len;
+	/* AP capability bitmap */
+	uint8 cap_ind;
+} BWL_POST_PACKED_STRUCT wifi_mbo_ap_cap_ind_attr_t;
+
+/* MBO AP Capability Indication Field Values */
+#define MBO_AP_CAP_IND_CELLULAR_AWARE  0x40
+
+/* Non-preferred Channel Report Attribute */
+#define MBO_NON_PREF_CHAN_ATTR_OPCALSS_OFF       2
+#define MBO_NON_PREF_CHAN_ATTR_CHANLIST_OFF      3
+#define MBO_NON_PREF_CHAN_ATTR_PREF_OFF(L)      \
+	(MBO_NON_PREF_CHAN_ATTR_CHANLIST_OFF + (L))
+
+#define MBO_NON_PREF_CHAN_ATTR_OPCALSS_LEN       1
+#define MBO_NON_PREF_CHAN_ATTR_PREF_LEN          1
+#define MBO_NON_PREF_CHAN_ATTR_REASON_LEN        1
+
+#define MBO_NON_PREF_CHAN_ATTR_LEN(L)  ((L) + 3)
+#define MBO_NON_PREF_CHAN_ATTR_TOT_LEN(L)  (MBO_ATTR_HDR_LEN + (L) + 3)
+
+/* attribute len - (opclass + Pref + Reason) */
+#define MBO_NON_PREF_CHAN_ATTR_CHANLIST_LEN(L) ((L) - 3)
+
+/* MBO Non-preferred Channel Report: "Preference" field value */
+enum {
+	MBO_STA_NON_OPERABLE_BAND_CHAN = 0,
+	MBO_STA_NON_PREFERRED_BAND_CHAN = 1,
+	MBO_STA_PREFERRED_BAND_CHAN = 255
+};
+
+/* MBO Non-preferred Channel Report: "Reason Code" field value */
+enum {
+	MBO_NON_PREF_CHAN_RC_UNSPECIFIED = 0,
+	MBO_NON_PREF_CHAN_RC_BCN_STRENGTH = 1,
+	MBO_NON_PREF_CHAN_RC_CO_LOC_INTERFERENCE = 2,
+	MBO_NON_PREF_CHAN_RC_IN_DEV_INTERFERENCE = 3
+};
+
+/* Cellular Data Capability Attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_mbo_cell_data_cap_attr_s {
+	/* Attribute ID - 0x03. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint8 len;
+	/* MBO STA's cellular capability */
+	uint8 cell_conn;
+} BWL_POST_PACKED_STRUCT wifi_mbo_cell_data_cap_attr_t;
+
+/* MBO Cellular Data Capability:  "Cellular Connectivity" field value */
+enum {
+	MBO_CELL_DATA_CONN_AVAILABLE = 1,
+	MBO_CELL_DATA_CONN_NOT_AVAILABLE = 2,
+	MBO_CELL_DATA_CONN_NOT_CAPABLE = 3
+};
+
+/* Association Disallowed attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_mbo_assoc_disallowed_attr_s {
+	/* Attribute ID - 0x04. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint8 len;
+	/* Reason of not accepting new association */
+	uint8 reason_code;
+} BWL_POST_PACKED_STRUCT wifi_mbo_assoc_disallowed_attr_t;
+
+/* Association Disallowed attr Reason code field values */
+enum {
+	MBO_ASSOC_DISALLOWED_RC_UNSPECIFIED = 1,
+	MBO_ASSOC_DISALLOWED_RC_MAX_STA_REACHED = 2,
+	MBO_ASSOC_DISALLOWED_RC_AIR_IFACE_OVERLOADED = 3,
+	MBO_ASSOC_DISALLOWED_RC_AUTH_SRVR_OVERLOADED = 4,
+	MBO_ASSOC_DISALLOWED_RC_INSUFFIC_RSSI = 5
+};
+
+/* Cellular Data Conn Pref attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_mbo_cell_data_conn_pref_attr_s {
+	/* Attribute ID - 0x05. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint8 len;
+	/* Preference value of cellular connection */
+	uint8 cell_pref;
+} BWL_POST_PACKED_STRUCT wifi_mbo_cell_data_conn_pref_attr_t;
+
+/* Cellular Data Conn Pref attr: Cellular Pref field values */
+enum {
+	MBO_CELLULAR_DATA_CONN_EXCLUDED = 1,
+	MBO_CELLULAR_DATA_CONN_NOT_PREFERRED = 2,
+	MBO_CELLULAR_DATA_CONN_PREFERRED = 255
+};
+
+/* Transition Reason Code Attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_mbo_trans_reason_code_attr_s {
+	/* Attribute ID - 0x06. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint8 len;
+	/* Reason of transition recommendation */
+	uint8 trans_reason_code;
+} BWL_POST_PACKED_STRUCT wifi_mbo_trans_reason_code_attr_t;
+
+/* Transition Reason Code Attr: trans reason code field values */
+enum {
+	MBO_TRANS_REASON_UNSPECIFIED = 0,
+	MBO_TRANS_REASON_EXCESSV_FRM_LOSS_RATE = 1,
+	MBO_TRANS_REASON_EXCESSV_TRAFFIC_DELAY = 2,
+	MBO_TRANS_REASON_INSUFF_BW = 3,
+	MBO_TRANS_REASON_LOAD_BALANCING = 4,
+	MBO_TRANS_REASON_LOW_RSSI = 5,
+	MBO_TRANS_REASON_EXCESSV_RETRANS_RCVD = 6,
+	MBO_TRANS_REASON_HIGH_INTERFERENCE = 7,
+	MBO_TRANS_REASON_GRAY_ZONE = 8,
+	MBO_TRANS_REASON_PREMIUM_AP_TRANS = 9
+};
+
+/* Transition Rejection Reason Code Attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_mbo_trans_rej_reason_code_attr_s {
+	/* Attribute ID - 0x07. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint8 len;
+	/* Reason of transition rejection */
+	uint8 trans_rej_reason_code;
+} BWL_POST_PACKED_STRUCT wifi_mbo_trans_rej_reason_code_attr_t;
+
+/* Transition Rej Reason Code Attr: trans rej reason code field values */
+enum {
+	MBO_TRANS_REJ_REASON_UNSPECIFIED = 0,
+	MBO_TRANS_REJ_REASON_EXSSIV_FRM_LOSS_RATE = 1,
+	MBO_TRANS_REJ_REASON_EXSSIV_TRAFFIC_DELAY = 2,
+	MBO_TRANS_REJ_REASON_INSUFF_QOS_CAPACITY = 3,
+	MBO_TRANS_REJ_REASON_LOW_RSSI = 4,
+	MBO_TRANS_REJ_REASON_HIGH_INTERFERENCE = 5,
+	MBO_TRANS_REJ_REASON_SERVICE_UNAVAIL = 6
+};
+
+/* Assoc Retry Delay Attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_mbo_assoc_retry_delay_attr_s {
+	/* Attribute ID - 0x08. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint8 len;
+	/* No of Seconds before next assoc attempt */
+	uint16 reassoc_delay;
+} BWL_POST_PACKED_STRUCT wifi_mbo_assoc_retry_delay_attr_t;
+
+#define MBO_ANQP_OUI_TYPE    0x12     /* OUTI Type/Version */
+
+/* MBO ANQP Element */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_mbo_anqp_elem_s {
+	/* ID - 56797 */
+	uint16 info_id;
+	/* Length of the OUI + Vendor Specific content */
+	uint16 len;
+	/* WFA_OUI 50:6F:9A */
+	uint8 oui[WFA_OUI_LEN];
+	/* MBO_ANQP_OUI_TYPE 0x12 */
+	uint8 oui_type;
+	/* MBO ANQP element type */
+	uint8 sub_type;
+	/* variable len payload */
+	uint8 payload[1];
+} BWL_POST_PACKED_STRUCT wifi_mbo_anqp_elem_t;
+
+/* MBO ANQP Subtype Values */
+enum {
+	MBO_ANQP_ELEM_CELL_DATA_CONN_PREF = 1
+};
+
+/* MBO sub-elements */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_mbo_cell_cap_subelem_s {
+	/* 0xDD */
+	uint8 sub_elem_id;
+	/* Length of the following fields in sub-element */
+	uint8 len;
+	/* WFA_OUI 50:6F:9A */
+	uint8 oui[WFA_OUI_LEN];
+	/* OUI_TYPE 0x03 */
+	uint8 oui_type;
+	/* STA cellular capability */
+	uint8 cell_conn;
+} BWL_POST_PACKED_STRUCT wifi_mbo_cell_cap_subelem_t;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* __MBO_H__ */
diff --git a/wl/components/shared/proto/nan.h b/wl/components/shared/proto/nan.h
new file mode 100644
index 0000000..63ca306
--- /dev/null
+++ b/wl/components/shared/proto/nan.h
@@ -0,0 +1,1223 @@
+/*
+ * Fundamental types and constants relating to WFA NAN
+ * (Neighbor Awareness Networking)
+ *
+ * Copyright (C) 2017, Broadcom. 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: nan.h 660905 2016-09-22 10:38:41Z $
+ */
+#ifndef _NAN_H_
+#define _NAN_H_
+
+#include <typedefs.h>
+#include <proto/802.11.h>
+
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/* WiFi NAN OUI values */
+#define NAN_OUI			WFA_OUI     /* WiFi OUI */
+/* For oui_type field identifying the type and version of the NAN IE. */
+#define NAN_OUI_TYPE		0x13        /* Type/Version */
+#define NAN_AF_OUI_TYPE		0x18        /* Type/Version */
+/* IEEE 802.11 vendor specific information element. (Same as P2P_IE_ID.) */
+#define NAN_IE_ID		0xdd
+
+/* Same as P2P_PUB_AF_CATEGORY and DOT11_ACTION_CAT_PUBLIC */
+#define NAN_PUB_AF_CATEGORY	0x04
+/* IEEE 802.11 Public Action Frame Vendor Specific. (Same as P2P_PUB_AF_ACTION.) */
+#define NAN_PUB_AF_ACTION	0x09
+/* Number of octents in hash of service name. (Same as P2P_WFDS_HASH_LEN.) */
+#define NAN_SVC_HASH_LEN	6
+/* Size of fixed length part of nan_pub_act_frame_t before attributes. */
+#define NAN_PUB_ACT_FRAME_FIXED_LEN 6
+/* Number of octents in master rank value. */
+#define NAN_MASTER_RANK_LEN     8
+/* NAN public action frame header size */
+#define NAN_PUB_ACT_FRAME_HDR_SIZE (OFFSETOF(nan_pub_act_frame_t, data))
+/* NAN network ID */
+#define NAN_NETWORK_ID		"\x51\x6F\x9A\x01\x00\x00"
+/* Service Control Type length */
+#define NAN_SVC_CONTROL_TYPE_LEN	2
+/* Binding Bitmap length */
+#define NAN_BINDING_BITMAP_LEN		2
+/* Service Response Filter (SRF) control field masks */
+#define NAN_SRF_BLOOM_MASK		0x01
+#define NAN_SRF_INCLUDE_MASK		0x02
+#define NAN_SRF_INDEX_MASK		0x0C
+/* SRF Bloom Filter index shift */
+#define NAN_SRF_BLOOM_SHIFT	2
+#define NAN_SRF_INCLUDE_SHIFT	1
+/* Mask for CRC32 output, used in hash function for NAN bloom filter */
+#define NAN_BLOOM_CRC32_MASK	0xFFFF
+
+/* Attribute TLV header size */
+#define NAN_ATTR_ID_OFF		0
+#define NAN_ATTR_LEN_OFF	1
+#define NAN_ATTR_DATA_OFF	3
+
+#define NAN_ATTR_ID_LEN		 1	/* ID field length */
+#define NAN_ATTR_LEN_LEN	 2	/* Length field length */
+#define NAN_ATTR_HDR_LEN	 (NAN_ATTR_ID_LEN + NAN_ATTR_LEN_LEN)
+#define NAN_ENTRY_CTRL_LEN       1      /* Entry control field length from FAM attribute */
+#define NAN_MAP_ID_LEN           1	/* MAP ID length to signify band */
+#define NAN_OPERATING_CLASS_LEN  1	/* operating class field length from NAN FAM */
+#define NAN_CHANNEL_NUM_LEN      1	/* channel number field length 1 byte */
+
+#define NAN_MAP_ID_2G   2  /* NAN Further Avail Map ID for band 2.4G */
+#define NAN_MAP_ID_5G   5  /* NAN Further Avail Map ID for band 5G */
+#define NAN_MAP_NUM_IDS 2  /* Max number of NAN Further Avail Map IDs supported */
+
+/* map id is 4 bits */
+#define NAN_CMN_MAP_ID_LEN_BITS	4
+/* siz eof ndc id */
+#define NAN_DATA_NDC_ID_SIZE 6
+
+#define NAN_AVAIL_ENTRY_LEN_RES0 7      /* Avail entry len in FAM attribute for resolution 16TU */
+#define NAN_AVAIL_ENTRY_LEN_RES1 5      /* Avail entry len in FAM attribute for resolution 32TU */
+#define NAN_AVAIL_ENTRY_LEN_RES2 4      /* Avail entry len in FAM attribute for resolution 64TU */
+
+/* Vendor-specific public action frame for NAN */
+typedef BWL_PRE_PACKED_STRUCT struct nan_pub_act_frame_s {
+	/* NAN_PUB_AF_CATEGORY 0x04 */
+	uint8 category_id;
+	/* NAN_PUB_AF_ACTION 0x09 */
+	uint8 action_field;
+	/* NAN_OUI 0x50-6F-9A */
+	uint8 oui[DOT11_OUI_LEN];
+	/* NAN_OUI_TYPE 0x13 */
+	uint8 oui_type;
+	/* One or more NAN Attributes follow */
+	uint8 data[];
+} BWL_POST_PACKED_STRUCT nan_pub_act_frame_t;
+
+/* NAN attributes as defined in the nan spec */
+enum {
+	NAN_ATTR_MASTER_IND	= 0,
+	NAN_ATTR_CLUSTER	= 1,
+	NAN_ATTR_SVC_ID_LIST    = 2,
+	NAN_ATTR_SVC_DESCRIPTOR = 3,
+	NAN_ATTR_CONN_CAP       = 4,
+	NAN_ATTR_INFRA		= 5,
+	NAN_ATTR_P2P		= 6,
+	NAN_ATTR_IBSS		= 7,
+	NAN_ATTR_MESH		= 8,
+	NAN_ATTR_FURTHER_NAN_SD = 9,
+	NAN_ATTR_FURTHER_AVAIL	= 10,
+	NAN_ATTR_COUNTRY_CODE	= 11,
+	NAN_ATTR_RANGING	= 12,
+	NAN_ATTR_CLUSTER_DISC	= 13,
+	/* nan 2.0 */
+	NAN_ATTR_SVC_DESC_EXTENSION = 14,
+	NAN_ATTR_NAN_DEV_CAP = 15,
+	NAN_ATTR_NAN_NDP = 16,
+	NAN_ATTR_NAN_NMSG = 17,
+	NAN_ATTR_NAN_AVAIL = 18,
+	NAN_ATTR_NAN_NDC = 19,
+	NAN_ATTR_NAN_NDL = 20,
+	NAN_ATTR_NAN_NDL_QOS = 21,
+	NAN_ATTR_MCAST_SCHED = 22,
+	NAN_ATTR_UNALIGN_SCHED = 23,
+	NAN_ATTR_PAGING_UCAST = 24,
+	NAN_ATTR_PAGING_MCAST = 25,
+	NAN_ATTR_RANGING_INFO = 26,
+	NAN_ATTR_RANGING_SETUP = 27,
+	NAN_ATTR_FTM_RANGE_REPORT = 28,
+	NAN_ATTR_ELEMENT_CONTAINER = 29,
+	NAN_ATTR_WLAN_INFRA_EXT = 30,
+	NAN_ATTR_EXT_P2P_OPER = 31,
+	NAN_ATTR_EXT_IBSS = 32,
+	NAN_ATTR_EXT_MESH = 33,
+
+	NAN_ATTR_VENDOR_SPECIFIC = 221,
+	NAN_ATTR_NAN_MGMT	= 222	/* NAN Mgmt Attr (TBD; not in spec yet) */
+};
+
+enum wifi_nan_avail_resolution {
+	NAN_AVAIL_RES_16_TU = 0,
+	NAN_AVAIL_RES_32_TU = 1,
+	NAN_AVAIL_RES_64_TU = 2,
+	NAN_AVAIL_RES_INVALID = 255
+};
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ie_s {
+	uint8	id;		/* IE ID: NAN_IE_ID 0xDD */
+	uint8	len;		/* IE length */
+	uint8	oui[DOT11_OUI_LEN]; /* NAN_OUI 50:6F:9A */
+	uint8	oui_type;	/* NAN_OUI_TYPE 0x13 */
+	uint8	attr[];	/* var len attributes */
+} BWL_POST_PACKED_STRUCT wifi_nan_ie_t;
+
+#define NAN_IE_HDR_SIZE	(OFFSETOF(wifi_nan_ie_t, attr))
+
+/* master indication record  */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_master_ind_attr_s {
+	uint8	id;
+	uint16	len;
+	uint8	master_preference;
+	uint8	random_factor;
+} BWL_POST_PACKED_STRUCT wifi_nan_master_ind_attr_t;
+
+/* cluster attr record  */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_cluster_attr_s {
+	uint8	id;
+	uint16	len;
+	uint8   amr[NAN_MASTER_RANK_LEN];
+	uint8   hop_count;
+	/* Anchor Master Beacon Transmission Time */
+	uint32  ambtt;
+} BWL_POST_PACKED_STRUCT wifi_nan_cluster_attr_t;
+
+/*  container for service ID records  */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_svc_id_attr_s {
+	uint8	id;
+	uint16	len;
+	uint8	svcid[0]; /* 6*len of srvc IDs */
+} BWL_POST_PACKED_STRUCT wifi_nan_svc_id_attr_t;
+
+/* service_control bitmap for wifi_nan_svc_descriptor_attr_t below */
+#define NAN_SC_PUBLISH 0x0
+#define NAN_SC_SUBSCRIBE 0x1
+#define NAN_SC_FOLLOWUP 0x2
+/* Set to 1 if a Matching Filter field is included in descriptors. */
+#define NAN_SC_MATCHING_FILTER_PRESENT 0x4
+/* Set to 1 if a Service Response Filter field is included in descriptors. */
+#define NAN_SC_SR_FILTER_PRESENT 0x8
+/* Set to 1 if a Service Info field is included in descriptors. */
+#define NAN_SC_SVC_INFO_PRESENT 0x10
+/* range is close proximity only */
+#define NAN_SC_RANGE_LIMITED 0x20
+/* Set to 1 if binding bitamp is present in descriptors */
+#define NAN_SC_BINDING_BITMAP_PRESENT 0x40
+
+/* Service descriptor */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_svc_descriptor_attr_s {
+	/* Attribute ID - 0x03. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint16 len;
+	/* Hash of the Service Name */
+	uint8 svc_hash[NAN_SVC_HASH_LEN];
+	/* Publish or subscribe instance id */
+	uint8 instance_id;
+	/* Requestor Instance ID */
+	uint8 requestor_id;
+	/* Service Control Bitmask. Also determines what data follows. */
+	uint8 svc_control;
+	/* Optional fields follow */
+} BWL_POST_PACKED_STRUCT wifi_nan_svc_descriptor_attr_t;
+
+/* IBSS attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ibss_attr_s {
+	/* Attribute ID - 0x07. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint16 len;
+	/* BSSID of the ibss */
+	struct ether_addr bssid;
+	/*
+	 map control:, bits:
+	[0-3]: Id for associated further avail map attribute
+	[4-5]: avail interval duration: 0:16ms; 1:32ms; 2:64ms; 3:reserved
+	[6] : repeat : 0 - applies to next DW, 1: 16 intervals max? wtf?
+	[7] : reserved
+	*/
+	uint8 map_ctrl;
+	/* avail. intervals bitmap, var len  */
+	uint8 avail_bmp[1];
+} BWL_POST_PACKED_STRUCT wifi_nan_ibss_attr_t;
+
+/* Further Availability MAP attr  */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_favail_attr_s {
+	/* Attribute ID - 0x0A. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint16 len;
+	/* MAP id: val [0..15], values[16-255] reserved */
+	uint8 map_id;
+	/*  availibility entry, var len */
+	uint8 avil_entry[1];
+} BWL_POST_PACKED_STRUCT wifi_nan_favail_attr_t;
+
+/* Further Availability MAP attr  */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_avail_entry_s {
+	/*
+	 entry control
+	 [0-1]: avail interval duration: 0:16ms; 1:32ms; 2:64ms;
+	 [2:7] reserved
+	*/
+	uint8 entry_ctrl;
+	/* operating class: freq band etc IEEE 802.11 */
+	uint8 opclass;
+	/* channel number */
+	uint8 chan;
+	/*  avail bmp, var len */
+	uint8 avail_bmp[1];
+} BWL_POST_PACKED_STRUCT wifi_nan_avail_entry_t;
+
+/* Map control Field */
+#define NAN_MAPCTRL_IDMASK	0x7
+#define NAN_MAPCTRL_DURSHIFT	4
+#define NAN_MAPCTRL_DURMASK	0x30
+#define NAN_MAPCTRL_REPEAT	0x40
+#define NAN_MAPCTRL_REPEATSHIFT	6
+
+#define NAN_VENDOR_TYPE_RTT	0
+#define NAN_VENDOR_TYPE_P2P	1
+
+/* Vendor Specific Attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_vendor_attr_s {
+	uint8	id;			/* 0xDD */
+	uint16	len;		/* IE length */
+	uint8	oui[DOT11_OUI_LEN]; /* 00-90-4C */
+	uint8	type;		/* attribute type */
+	uint8	attr[1];	/* var len attributes */
+} BWL_POST_PACKED_STRUCT wifi_nan_vendor_attr_t;
+
+#define NAN_VENDOR_HDR_SIZE	(OFFSETOF(wifi_nan_vendor_attr_t, attr))
+
+/* p2p operation attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_p2p_op_attr_s {
+	/* Attribute ID - 0x06. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint16 len;
+	/* P2P device role */
+	uint8 dev_role;
+	/* BSSID of the ibss */
+	struct ether_addr p2p_dev_addr;
+	/*
+	map control:, bits:
+	[0-3]: Id for associated further avail map attribute
+	[4-5]: avail interval duration: 0:16ms; 1:32ms; 2:64ms; 3:reserved
+	[6] : repeat : 0 - applies to next DW, 1: 16 intervals max? wtf?
+	[7] : reserved
+	*/
+	uint8 map_ctrl;
+	/* avail. intervals bitmap */
+	uint8 avail_bmp[1];
+} BWL_POST_PACKED_STRUCT wifi_nan_p2p_op_attr_t;
+
+/* ranging attribute */
+#define NAN_RANGING_MAP_CTRL_ID_SHIFT 0
+#define NAN_RANGING_MAP_CTRL_ID_MASK 0x0F
+#define NAN_RANGING_MAP_CTRL_DUR_SHIFT 4
+#define NAN_RANGING_MAP_CTRL_DUR_MASK 0x30
+#define NAN_RANGING_MAP_CTRL_REPEAT_SHIFT 6
+#define NAN_RANGING_MAP_CTRL_REPEAT_MASK 0x40
+#define NAN_RANGING_MAP_CTRL_REPEAT_DW(_ctrl) (((_ctrl) & \
+	NAN_RANGING_MAP_CTRL_DUR_MASK) ? 16 : 1)
+#define NAN_RANGING_MAP_CTRL(_id, _dur, _repeat) (\
+	(((_id) << NAN_RANGING_MAP_CTRL_ID_SHIFT) & \
+		 NAN_RANGING_MAP_CTRL_ID_MASK) | \
+	(((_dur) << NAN_RANGING_MAP_CTRL_DUR_SHIFT) & \
+		NAN_RANGING_MAP_CTRL_DUR_MASK) | \
+	(((_repeat) << NAN_RANGING_MAP_CTRL_REPEAT_SHIFT) & \
+		 NAN_RANGING_MAP_CTRL_REPEAT_MASK))
+
+enum {
+	NAN_RANGING_PROTO_FTM = 0
+};
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ranging_attr_s {
+	uint8 id;			/* 0x0C */
+	uint16 len;			/* length that follows */
+	struct ether_addr dev_addr;	/* device mac address */
+
+	/*
+	map control:, bits:
+	[0-3]: Id for associated further avail map attribute
+	[4-5]: avail interval duration: 0:16ms; 1:32ms; 2:64ms; 3:reserved
+	[6] : repeat : 0 - applies to next DW, 1: 16 intervals max? wtf?
+	[7] : reserved
+	*/
+	uint8 map_ctrl;
+
+	uint8 protocol;					/* FTM = 0 */
+	uint32 avail_bmp;				/* avail interval bitmap */
+} BWL_POST_PACKED_STRUCT wifi_nan_ranging_attr_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ranging_info_attr_s {
+	uint8 id;			/* 0x1A */
+	uint16 len;			/* length that follows */
+	/*
+	location info availability bit map
+	0: LCI Local Coordinates
+	1: Geospatial LCI WGS84
+	2: Civi Location
+	3: Last Movement Indication
+	[4-7]: reserved
+	*/
+	uint8 lc_info_avail;
+	/*
+	Last movement indication
+	present if bit 3 is set in lc_info_avail
+	cluster TSF[29:14] at the last detected platform movement
+	*/
+	uint16 last_movement;
+
+} BWL_POST_PACKED_STRUCT wifi_nan_ranging_info_attr_t;
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ranging_setup_attr_hdr_s {
+	uint8 id;			/* 0x1B */
+	uint16 len;			/* length that follows */
+	uint8 dialog_token;	/* Identify req and resp */
+	uint8 type_status;	/* bits 0-3 type, 4-7 status */
+	/* reason code
+	i. when frm type = response & status = reject
+	ii. frm type = termination
+	*/
+	uint8 reason;
+} BWL_POST_PACKED_STRUCT wifi_nan_ranging_setup_attr_hdr_t;
+
+/* Common time structure used in NAN Availability, NDC, Immutable schedules */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_time_bitmap_s {
+	uint16 ctrl;		/* Time bitmap control */
+	uint8 len;		/* Time bitmap length */
+	uint8 bitmap[1];	/* Time bitmap */
+} BWL_POST_PACKED_STRUCT wifi_nan_time_bitmap_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ranging_time_bitmap_s {
+	uint8 map_id;			/* Map ID to which this bit map corresponds */
+	wifi_nan_time_bitmap_t time_bmp;
+} BWL_POST_PACKED_STRUCT wifi_nan_ranging_time_bitmap_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ranging_setup_attr_s {
+
+	wifi_nan_ranging_setup_attr_hdr_t setup_attr_hdr;
+	/* Below fields not required when frm type = termination */
+	uint8 ranging_ctrl; /* Bit 0: ranging report required or not */
+	uint8 ftm_params[3];
+	wifi_nan_ranging_time_bitmap_t range_tbm; /* Ranging timebit map info */
+} BWL_POST_PACKED_STRUCT wifi_nan_ranging_setup_attr_t;
+#define NAN_RANGE_SETUP_ATTR_OFFSET_TBM_INFO (OFFSETOF(wifi_nan_ranging_setup_attr_t, range_tbm))
+
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ranging_report_attr_s {
+	uint8 id;			/* 0x1C */
+	uint16 len;			/* length that follows */
+	/* FTM report format in spec.
+	See definition in 9.4.2.22.18 in 802.11mc D5.0
+	*/
+	uint8 entry_count;
+	uint8 data[2]; /* includes pad */
+	/*
+	dot11_ftm_range_entry_t entries[entry_count];
+	uint8 error_count;
+	dot11_ftm_error_entry_t errors[error_count];
+	 */
+} BWL_POST_PACKED_STRUCT wifi_nan_ranging_report_attr_t;
+
+/* Ranging control flags */
+#define NAN_RNG_REPORT_REQUIRED		0x01
+/* Location info flags */
+#define NAN_RNG_LOCATION_FLAGS_LOCAL_CORD		0x1
+#define NAN_RNG_LOCATION_FLAGS_GEO_SPATIAL		0x2
+#define NAN_RNG_LOCATION_FLAGS_CIVIC			0x4
+#define NAN_RNG_LOCATION_FLAGS_LAST_MVMT		0x8
+/* Last movement mask and shift value */
+#define NAN_RNG_LOCATION_MASK_LAST_MVT_TSF	0x3FFFC000
+#define NAN_RNG_LOCATION_SHIFT_LAST_MVT_TSF	14
+
+/* FTM params shift values  */
+#define NAN_RNG_FTM_MAX_BURST_DUR_S	0
+#define NAN_RNG_FTM_MIN_FTM_DELTA_S	4
+#define NAN_RNG_FTM_NUM_FTM_S		10
+#define NAN_RNG_FTM_FORMAT_BW_S		15
+
+/* FTM params mask  */
+#define NAN_RNG_FTM_MAX_BURST_DUR	0x00000F
+#define NAN_RNG_FTM_MIN_FTM_DELTA	0x00003F
+#define NAN_RNG_FTM_NUM_FTM		0x00001F
+#define NAN_RNG_FTM_FORMAT_BW		0x00003F
+
+#define NAN_CONN_CAPABILITY_WFD		0x0001
+#define NAN_CONN_CAPABILITY_WFDS	0x0002
+#define NAN_CONN_CAPABILITY_TDLS	0x0004
+#define NAN_CONN_CAPABILITY_INFRA	0x0008
+#define NAN_CONN_CAPABILITY_IBSS	0x0010
+#define NAN_CONN_CAPABILITY_MESH	0x0020
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_conn_cap_attr_s {
+	/* Attribute ID - 0x04. */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint16	len;
+	uint16	conn_cap_bmp;	/* Connection capability bitmap */
+} BWL_POST_PACKED_STRUCT wifi_nan_conn_cap_attr_t;
+
+#define NAN_SLOT_RES_16TU 16
+#define NAN_SLOT_RES_32TU 32
+#define NAN_SLOT_RES_64TU 64
+#define NAN_SLOT_RES_128TU 128
+
+/* Attribute Control field */
+#define NAN_ATTR_CNTRL_MAP_ID_MASK	0x0F	/* Map Id */
+#define NAN_ATTR_CNTRL_RSVD_MASK	0xF0	/* Reserved */
+#define NAN_ATTR_CNTRL_SEQ_ID_MASK	0xFF	/* Seq Id */
+
+/* NAN Element container Attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_container_attr_s {
+	uint8 id;	/* id - 0x20 */
+	uint16 len;	/* Total length of following IEs */
+	uint8 data[1];	/* Data pointing to one or more IEs */
+} BWL_POST_PACKED_STRUCT wifi_nan_container_attr_t;
+
+/* NAN 2.0 NAN avail attribute */
+
+/* Availability Attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_avail_attr_s {
+	uint8 id;	/* id - 0x12 */
+	uint16 len;	/* total length */
+	uint16 ctrl;	/* attribute control */
+	uint8 entry[1];	/* availability entry list */
+} BWL_POST_PACKED_STRUCT wifi_nan_avail_attr_t;
+
+/* Availability Entry format */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_avail_entry_attr_s {
+	uint16 len;		/* Length */
+	uint16 entry_cntrl;	/* Entry Control */
+	uint8 var[1];		/* Time bitmap fields and channel entry list */
+} BWL_POST_PACKED_STRUCT wifi_nan_avail_entry_attr_t;
+
+/* FAC Channel Entry  (section 10.7.19.1.5) */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_chan_entry_s {
+	uint8 oper_class;		/* Operating Class */
+	uint16 chan_bitmap;		/* Channel Bitmap */
+	uint8 primary_chan_bmp;		/* Primary Channel Bitmap */
+	uint8 aux_chan[0];			/* Auxiliary Channel bitmap */
+} BWL_POST_PACKED_STRUCT wifi_nan_chan_entry_t;
+
+#define NAN_AVAIL_CTRL_SEQ_ID_SHIFT 8
+
+#define NAN_AVAIL_ENTRY_CTRL_AVAIL_TYPE_MASK 0x07
+#define NAN_AVAIL_ENTRY_CTRL_AVAIL_TYPE(_flags) ((_flags) & NAN_AVAIL_ENTRY_CTRL_AVAIL_TYPE_MASK)
+#define NAN_AVAIL_ENTRY_CTRL_USAGE_MASK 0x18
+#define NAN_AVAIL_ENTRY_CTRL_USAGE_SHIFT 3
+#define NAN_AVAIL_ENTRY_CTRL_USAGE(_flags) ((_flags) & NAN_AVAIL_ENTRY_CTRL_USAGE_MASK) \
+	>> NAN_AVAIL_ENTRY_CTRL_USAGE_SHIFT
+#define NAN_AVAIL_ENTRY_CTRL_RX_NSS_MASK 0xF00
+#define NAN_AVAIL_ENTRY_CTRL_RX_NSS_SHIFT 8
+#define NAN_AVAIL_ENTRY_CTRL_RX_NSS(_flags) (((_flags) & NAN_AVAIL_ENTRY_CTRL_RX_NSS_MASK) \
+	>> NAN_AVAIL_ENTRY_CTRL_RX_NSS_SHIFT)
+#define NAN_AVAIL_ENTRY_CTRL_PAGING_MASK 0x1000
+#define NAN_AVAIL_ENTRY_CTRL_PAGING_SHIFT 12
+#define NAN_AVAIL_ENTRY_CTRL_PAGING(_flags) (((_flags) & NAN_AVAIL_ENTRY_CTRL_PAGING_MASK) \
+		>> NAN_AVAIL_ENTRY_CTRL_PAGING_SHIFT)
+#define NAN_AVAIL_ENTRY_CTRL_BITMAP_PRESENT_MASK 0x2000
+#define NAN_AVAIL_ENTRY_CTRL_BITMAP_PRESENT_SHIFT 13
+#define NAN_AVAIL_ENTRY_CTRL_BITMAP_PRESENT(_flags) ((_flags) & \
+	NAN_AVAIL_ENTRY_CTRL_BITMAP_PRESENT_MASK) >> NAN_AVAIL_ENTRY_CTRL_BITMAP_PRESENT_SHIFT
+
+#define NAN_TIME_BMAP_CTRL_BITDUR_MASK 0x07
+#define NAN_TIME_BMAP_CTRL_BITDUR(_flags) ((_flags) & NAN_TIME_BMAP_CTRL_BITDUR_MASK)
+#define NAN_TIME_BMAP_CTRL_PERIOD_MASK 0x38
+#define NAN_TIME_BMAP_CTRL_PERIOD_SHIFT 3
+#define NAN_TIME_BMAP_CTRL_PERIOD(_flags) ((_flags) & NAN_TIME_BMAP_CTRL_PERIOD_MASK) \
+	>> NAN_TIME_BMAP_CTRL_PERIOD_SHIFT
+#define NAN_TIME_BMAP_CTRL_OFFSET_MASK 0x7FC0
+#define NAN_TIME_BMAP_CTRL_OFFSET_SHIFT 6
+#define NAN_TIME_BMAP_CTRL_OFFSET(_flags) ((_flags) & NAN_TIME_BMAP_CTRL_OFFSET_MASK) \
+	>> NAN_TIME_BMAP_CTRL_OFFSET_SHIFT
+#define NAN_TIME_BMAP_LEN(avail_entry)	\
+	(*(uint8 *)(((wifi_nan_avail_entry_attr_t *)avail_entry)->var + 2))
+
+#define NAN_AVAIL_CHAN_LIST_HDR_LEN 1
+#define NAN_AVAIL_CHAN_LIST_TYPE_CHANNEL	0x01
+#define NAN_AVAIL_CHAN_LIST_NON_CONTIG_BW	0x02
+#define NAN_AVAIL_CHAN_LIST_NUM_ENTRIES_MASK	0xF0
+#define NAN_AVAIL_CHAN_LIST_NUM_ENTRIES_SHIFT	4
+#define NAN_AVAIL_CHAN_LIST_NUM_ENTRIES(_ctrl) (((_ctrl) & NAN_AVAIL_CHAN_LIST_NUM_ENTRIES_MASK) \
+	>> NAN_AVAIL_CHAN_LIST_NUM_ENTRIES_SHIFT)
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_channel_entry_list_s {
+	uint8 chan_info;
+	uint8 var[0];
+} BWL_POST_PACKED_STRUCT wifi_nan_channel_entry_list_t;
+
+/* define for chan_info */
+#define NAN_CHAN_OP_CLASS_MASK 0x01
+#define NAN_CHAN_NON_CONT_BW_MASK 0x02
+#define NAN_CHAN_RSVD_MASK 0x03
+#define NAN_CHAN_NUM_ENTRIES_MASK 0xF0
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_band_entry_s {
+	uint8 band[0];
+} BWL_POST_PACKED_STRUCT wifi_nan_band_entry_t;
+
+/* Type of  Availability: committed */
+#define NAN_ENTRY_CNTRL_TYPE_COMM_AVAIL	        0x1
+/* Type of  Availability: potential */
+#define NAN_ENTRY_CNTRL_TYPE_POTEN_AVAIL	0x2
+/* Type of  Availability: conditional */
+#define NAN_ENTRY_CNTRL_TYPE_COND_AVAIL	        0x4
+
+/* Type of  Availability */
+#define NAN_ENTRY_CNTRL_TYPE_OF_AVAIL_MASK	0x07
+#define NAN_ENTRY_CNTRL_TYPE_OF_AVAIL_SHIFT	0
+/* Usage Preference */
+#define NAN_ENTRY_CNTRL_USAGE_PREF_MASK		0x18
+#define NAN_ENTRY_CNTRL_USAGE_PREF_SHIFT	3
+/* Utilization */
+#define NAN_ENTRY_CNTRL_UTIL_MASK		0x1E0
+#define NAN_ENTRY_CNTRL_UTIL_SHIFT		5
+
+/* Time Bitmap Control field (section 5.7.18.2.3) */
+
+/* Reserved */
+#define NAN_TIME_BMP_CNTRL_RSVD_MASK	0x01
+#define NAN_TIME_BMP_CNTRL_RSVD_SHIFT	0
+/* Bitmap Len */
+#define NAN_TIME_BMP_CNTRL_BMP_LEN_MASK	0x7E
+#define NAN_TIME_BMP_CNTRL_BMP_LEN_SHIFT 1
+/* Bit Duration */
+#define NAN_TIME_BMP_CNTRL_BIT_DUR_MASK	0x380
+#define NAN_TIME_BMP_CNTRL_BIT_DUR_SHIFT	7
+/* Bitmap Len */
+#define NAN_TIME_BMP_CNTRL_PERIOD_MASK	0x1C00
+#define NAN_TIME_BMP_CNTRL_PERIOD_SHIFT	10
+/* Start Offset */
+#define NAN_TIME_BMP_CNTRL_START_OFFSET_MASK	0x3FE000
+#define NAN_TIME_BMP_CNTRL_START_OFFSET_SHIFT	13
+/* Reserved */
+#define NAN_TIME_BMP_CNTRL_RESERVED_MASK	0xC00000
+#define NAN_TIME_BMP_CNTRL_RESERVED_SHIFT	22
+
+/* Time Bitmap Control field: Period */
+typedef enum
+{
+	NAN_TIME_BMP_CTRL_PERIOD_128TU = 1,
+	NAN_TIME_BMP_CTRL_PERIOD_256TU = 2,
+	NAN_TIME_BMP_CTRL_PERIOD_512TU = 3,
+	NAN_TIME_BMP_CTRL_PERIOD_1024TU = 4,
+	NAN_TIME_BMP_CTRL_PERIOD_2048U = 5,
+	NAN_TIME_BMP_CTRL_PERIOD_4096U = 6,
+	NAN_TIME_BMP_CTRL_PERIOD_8192U = 7
+} nan_time_bmp_ctrl_repeat_interval_t;
+
+enum
+{
+	NAN_TIME_BMP_BIT_DUR_16TU_IDX = 0,
+	NAN_TIME_BMP_BIT_DUR_32TU_IDX = 1,
+	NAN_TIME_BMP_BIT_DUR_64TU_IDX = 2,
+	NAN_TIME_BMP_BIT_DUR_128TU_IDX = 3
+};
+
+enum
+{
+	NAN_TIME_BMP_BIT_DUR_IDX_0 = 16,
+	NAN_TIME_BMP_BIT_DUR_IDX_1 = 32,
+	NAN_TIME_BMP_BIT_DUR_IDX_2 = 64,
+	NAN_TIME_BMP_BIT_DUR_IDX_3 = 128
+};
+
+enum
+{
+	NAN_TIME_BMP_CTRL_PERIOD_IDX_1 = 128,
+	NAN_TIME_BMP_CTRL_PERIOD_IDX_2 = 256,
+	NAN_TIME_BMP_CTRL_PERIOD_IDX_3 = 512,
+	NAN_TIME_BMP_CTRL_PERIOD_IDX_4 = 1024,
+	NAN_TIME_BMP_CTRL_PERIOD_IDX_5 = 2048,
+	NAN_TIME_BMP_CTRL_PERIOD_IDX_6 = 4096,
+	NAN_TIME_BMP_CTRL_PERIOD_IDX_7 = 8192
+};
+
+/* Channel Entries List field */
+
+/* Type */
+#define NAN_CHAN_ENTRY_TYPE_MASK	0x01
+#define NAN_CHAN_ENTRY_TYPE_SHIFT	0
+/* Channel Entry Length Indication */
+#define NAN_CHAN_ENTRY_LEN_IND_MASK	0x02
+#define NAN_CHAN_ENTRY_LEN_IND_SHIFT	1
+/* Reserved */
+#define NAN_CHAN_ENTRY_RESERVED_MASK	0x0C
+#define NAN_CHAN_ENTRY_RESERVED_SHIFT	2
+/* Number of FAC Band or Channel Entries  */
+#define NAN_CHAN_ENTRY_NO_OF_CHAN_ENTRY_MASK	0xF0
+#define NAN_CHAN_ENTRY_NO_OF_CHAN_ENTRY_SHIFT	4
+
+#define NAN_CHAN_ENTRY_TYPE_BANDS	0
+#define NAN_CHAN_ENTRY_TYPE_OPCLASS_CHANS	1
+
+#define NAN_CHAN_ENTRY_BW_LT_80MHZ	0
+#define NAN_CHAN_ENTRY_BW_EQ_160MHZ	1
+
+/*
+ * NDL Attribute WFA Tech. Spec ver 1.0.r12 (section 10.7.19.2)
+ */
+#define NDL_ATTR_IM_MAP_ID_LEN		1
+#define NDL_ATTR_IM_TIME_BMP_CTRL_LEN	2
+#define NDL_ATTR_IM_TIME_BMP_LEN_LEN	1
+
+/* immutable schedule - as per r21 */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ndl_im_sched_field_s {
+	uint8 no_of_im_entries;
+	uint8 var[];
+} BWL_POST_PACKED_STRUCT wifi_nan_ndl_im_sched_field_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ndl_im_sched_entry_s {
+	uint8 map_id;		/* map id */
+	uint16 tbmp_ctrl;	/* time bitmap control */
+	uint8 tbmp_len;		/* time bitmap len */
+	uint8 tbmp[];		/* time bitmap - Optional */
+} BWL_POST_PACKED_STRUCT wifi_nan_ndl_im_sched_entry_t;
+
+/*
+ * NDL Control field - Table xx
+ */
+#define NDL_ATTR_CTRL_PEER_ID_PRESENT_MASK		0x01
+#define NDL_ATTR_CTRL_PEER_ID_PRESENT_SHIFT		0
+#define NDL_ATTR_CTRL_IM_SCHED_PRESENT_MASK		0x02
+#define NDL_ATTR_CTRL_IM_SCHED_PRESENT_SHIFT	1
+#define NDL_ATTR_CTRL_NDC_ATTR_PRESENT_MASK		0x04
+#define NDL_ATTR_CTRL_NDC_ATTR_PRESENT_SHIFT	2
+#define NDL_ATTR_CTRL_QOS_ATTR_PRESENT_MASK		0x08
+#define NDL_ATTR_CTRL_QOS_ATTR_PRESENT_SHIFT	3
+
+#define NAN_NDL_TYPE_MASK	0x0F
+#define NDL_ATTR_TYPE_STATUS_REQUEST	0x00
+#define NDL_ATTR_TYPE_STATUS_RESPONSE	0x01
+#define NDL_ATTR_TYPE_STATUS_CONFIRM	0x02
+#define NDL_ATTR_TYPE_STATUS_CONTINUED	0x00
+#define NDL_ATTR_TYPE_STATUS_ACCEPTED	0x10
+#define NDL_ATTR_TYPE_STATUS_REJECTED	0x20
+
+#define NAN_NDL_TYPE_CHECK(_ndl, x)	(((_ndl)->type_status & NAN_NDL_TYPE_MASK) == (x))
+#define NAN_NDL_REQUEST(_ndl)		(((_ndl)->type_status & NAN_NDL_TYPE_MASK) == \
+								NDL_ATTR_TYPE_STATUS_REQUEST)
+#define NAN_NDL_RESPONSE(_ndl)		(((_ndl)->type_status & NAN_NDL_TYPE_MASK) == \
+								NDL_ATTR_TYPE_STATUS_RESPONSE)
+#define NAN_NDL_CONFIRM(_ndl)		(((_ndl)->type_status & NAN_NDL_TYPE_MASK) == \
+								NDL_ATTR_TYPE_STATUS_CONFIRM)
+
+#define NAN_NDL_STATUS_SHIFT	4
+#define NAN_NDL_STATUS_MASK	0xF0
+#define NAN_NDL_CONT(_ndl)	(((_ndl)->type_status & NAN_NDL_STATUS_MASK) == \
+								NDL_ATTR_TYPE_STATUS_CONTINUED)
+#define NAN_NDL_ACCEPT(_ndl)	(((_ndl)->type_status & NAN_NDL_STATUS_MASK) == \
+								NDL_ATTR_TYPE_STATUS_ACCEPTED)
+#define NAN_NDL_REJECT(_ndl)	(((_ndl)->type_status & NAN_NDL_STATUS_MASK) == \
+								NDL_ATTR_TYPE_STATUS_REJECTED)
+
+#define NDL_ATTR_CTRL_NONE				0
+#define NDL_ATTR_CTRL_PEER_ID_PRESENT	(1 << NDL_ATTR_CTRL_PEER_ID_PRESENT_SHIFT)
+#define NDL_ATTR_CTRL_IMSCHED_PRESENT	(1 << NDL_ATTR_CTRL_IM_SCHED_PRESENT_SHIFT)
+#define NDL_ATTR_CTRL_NDC_PRESENT		(1 << NDL_ATTR_CTRL_NDC_ATTR_PRESENT_SHIFT)
+#define NDL_ATTR_CTRL_NDL_QOS_PRESENT	(1 << NDL_ATTR_CTRL_QOS_ATTR_PRESENT_SHIFT)
+
+#define NDL_ATTR_PEERID_LEN		1
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ndl_attr_s {
+	uint8 id;		/* NAN_ATTR_NAN_NDL = 0x17 */
+	uint16 len;		/* Length of the fields in the attribute */
+	uint8 dialog_token;	/* Identify req and resp */
+	uint8 type_status;		/* Bits[3-0] type subfield, Bits[7-4] status subfield */
+	uint8 reason;		/* Identifies reject reason */
+	uint8 ndl_ctrl;		/* NDL control field */
+	uint8 var[];		/* Optional fields follow */
+} BWL_POST_PACKED_STRUCT wifi_nan_ndl_attr_t;
+
+/*
+ * NDL QoS Attribute  WFA Tech. Spec ver 1.0.r12 (section 10.7.19.4)
+ */
+#define NDL_QOS_ATTR_MAX_LATENCY_LEN        3
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ndl_qos_attr_s {
+	uint8 id;		/* NAN_ATTR_NAN_NDL_QOS = 24 */
+	uint16 len;		/* Length of the attribute field following */
+	uint8 min_slots;	/* Min. number of FAW slots needed per DW interval */
+	uint8 max_latency[NDL_QOS_ATTR_MAX_LATENCY_LEN];  /* Max interval between non-cont FAW */
+} BWL_POST_PACKED_STRUCT wifi_nan_ndl_qos_attr_t;
+
+/* Device Capability Attribute */
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_dev_cap_s {
+	uint8 id;		/* 0x0F */
+	uint16 len;		/* Length */
+	uint16 commit_dw_info;	/* Committed DW Info */
+	uint8 bands_supported;	/* Supported Bands */
+	uint8 op_mode;		/* Operation Mode */
+	uint8 num_antennas;	/* Bit 0-3 tx, 4-7 rx */
+	uint16 chan_switch_time;	/* Max channel switch time in us */
+} BWL_POST_PACKED_STRUCT wifi_nan_dev_cap_t;
+
+/* Awake DW Info field format */
+
+/* 2.4GHz DW */
+#define NAN_DEV_CAP_AWAKE_DW_2G_MASK	0x07
+/* 5GHz DW */
+#define NAN_DEV_CAP_AWAKE_DW_5G_MASK	0x38
+/* Reserved */
+#define NAN_DEV_CAP_AWAKE_DW_RSVD_MASK	0xC0
+
+/* bit shift for dev cap */
+#define NAN_DEV_CAP_AWAKE_DW_2G_SHIFT	0
+#define NAN_DEV_CAP_AWAKE_DW_5G_SHIFT	3
+
+/* Device Capability Attribute Format */
+
+/* Operation Mode: HT */
+#define NAN_DEV_CAP_HT_OPER_MODE_MASK	0x01
+/* Operation Mode: VHT */
+#define NAN_DEV_CAP_VHT_OPER_MODE_MASK	0x02
+
+/* Committed DW Info field format */
+/* 2.4GHz DW */
+#define NAN_DEV_CAP_COMMIT_DW_2G_MASK	0x07
+#define NAN_DEV_CAP_COMMIT_DW_2G_OVERWRITE_MASK	0x3C0
+/* 5GHz DW */
+#define NAN_DEV_CAP_COMMIT_DW_5G_MASK	0x38
+#define NAN_DEV_CAP_COMMIT_DW_5G_OVERWRITE_MASK 0x3C00
+/* Reserved */
+#define NAN_DEV_CAP_COMMIT_DW_RSVD_MASK	0xC000
+/* Committed DW bit shift for dev cap */
+#define NAN_DEV_CAP_COMMIT_DW_2G_SHIFT	0
+#define NAN_DEV_CAP_COMMIT_DW_5G_SHIFT	3
+#define NAN_DEV_CAP_COMMIT_DW_2G_OVERWRITE_SHIFT	6
+#define NAN_DEV_CAP_COMMIT_DW_5G_OVERWRITE_SHIFT	10
+/* Operation Mode */
+#define NAN_DEV_CAP_OP_PHY_MODE_HT_ONLY		0x00
+#define NAN_DEV_CAP_OP_PHY_MODE_VHT		0x01
+#define NAN_DEV_CAP_OP_PHY_MODE_VHT_8080	0x02
+#define NAN_DEV_CAP_OP_PHY_MODE_VHT_160		0x04
+#define NAN_DEV_CAP_OP_PAGING_NDL		0x08
+
+#define NAN_DEV_CAP_OP_MODE_VHT_MASK		0x01
+#define NAN_DEV_CAP_OP_MODE_VHT8080_MASK	0x03
+#define NAN_DEV_CAP_OP_MODE_VHT160_MASK		0x05
+#define NAN_DEV_CAP_OP_MODE_PAGING_NDL_MASK	0x08
+
+#define NAN_DEV_CAP_RX_ANT_SHIFT		4
+#define NAN_DEV_CAP_TX_ANT_MASK			0x0F
+#define NAN_DEV_CAP_RX_ANT_MASK			0xF0
+
+/* Band IDs */
+enum {
+	NAN_BAND_ID_TVWS		= 0,
+	NAN_BAND_ID_SIG			= 1,
+	NAN_BAND_ID_2G			= 2,
+	NAN_BAND_ID_5G			= 4,
+	NAN_BAND_ID_60G			= 5
+};
+typedef uint8 nan_band_id_t;
+
+/*
+ * Unaligned schedule attribute section 10.7.19.6 spec. ver r15
+ */
+#define NAN_UAW_ATTR_CTRL_SCHED_ID_MASK 0x000F
+#define NAN_UAW_ATTR_CTRL_SCHED_ID_SHIFT 0
+#define NAN_UAW_ATTR_CTRL_SEQ_ID_MASK 0xFF00
+#define NAN_UAW_ATTR_CTRL_SEQ_ID_SHIFT 8
+
+#define NAN_UAW_OVWR_ALL_MASK 0x01
+#define NAN_UAW_OVWR_ALL_SHIFT 0
+#define NAN_UAW_OVWR_MAP_ID_MASK 0x1E
+#define NAN_UAW_OVWR_MAP_ID_SHIFT 1
+
+#define NAN_UAW_CTRL_TYPE_MASK 0x03
+#define NAN_UAW_CTRL_TYPE_SHIFT 0
+#define NAN_UAW_CTRL_CHAN_AVAIL_MASK 0x04
+#define NAN_UAW_CTRL_CHAN_AVAIL_SHIFT 2
+#define NAN_UAW_CTRL_RX_NSS_MASK 0x78
+#define NAN_UAW_CTRL_RX_NSS_SHIFT 3
+
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_uaw_attr_s {
+	uint8 id;
+	uint16 len;
+	uint16 ctrl;
+	uint32 start; /* low 32 bits of tsf */
+	uint32 dur;
+	uint32 period;
+	uint8 count_down;
+	uint8 overwrite;
+	/*
+	 * uaw[0] == optional field UAW control when present.
+	 * band ID or channel follows
+	 */
+	uint8 uaw_entry[];
+} BWL_POST_PACKED_STRUCT wifi_nan_uaw_attr_t;
+
+/* NAN2 Management Frame (section 5.6) */
+
+/* Public action frame for NAN2 */
+typedef BWL_PRE_PACKED_STRUCT struct nan2_pub_act_frame_s {
+	/* NAN_PUB_AF_CATEGORY 0x04 */
+	uint8 category_id;
+	/* NAN_PUB_AF_ACTION 0x09 */
+	uint8 action_field;
+	/* NAN_OUI 0x50-6F-9A */
+	uint8 oui[DOT11_OUI_LEN];
+	/* NAN_OUI_TYPE TBD */
+	uint8 oui_type;
+	/* NAN_OUI_SUB_TYPE TBD */
+	uint8 oui_sub_type;
+	/* One or more NAN Attributes follow */
+	uint8 data[];
+} BWL_POST_PACKED_STRUCT nan2_pub_act_frame_t;
+
+#define NAN2_PUB_ACT_FRM_SIZE	(OFFSETOF(nan2_pub_act_frame_t, data))
+
+/* NAN Action Frame Subtypes */
+/* Subtype-0 is Reserved */
+#define NAN_MGMT_FRM_SUBTYPE_RESERVED		0
+/* NAN Ranging Request */
+#define NAN_MGMT_FRM_SUBTYPE_RANGING_REQ	1
+/* NAN Ranging Response */
+#define NAN_MGMT_FRM_SUBTYPE_RANGING_RESP	2
+/* NAN Ranging Termination */
+#define NAN_MGMT_FRM_SUBTYPE_RANGING_TERM	3
+/* NAN Ranging Report */
+#define NAN_MGMT_FRM_SUBTYPE_RANGING_RPT	4
+/* NDP Request */
+#define NAN_MGMT_FRM_SUBTYPE_NDP_REQ		5
+/* NDP Response */
+#define NAN_MGMT_FRM_SUBTYPE_NDP_RESP		6
+/* NDP Confirm */
+#define NAN_MGMT_FRM_SUBTYPE_NDP_CONFIRM	7
+/* NDP Key Installment */
+#define NAN_MGMT_FRM_SUBTYPE_NDP_KEY_INST	8
+/* NDP Termination */
+#define NAN_MGMT_FRM_SUBTYPE_NDP_END		9
+/* Schedule Request */
+#define NAN_MGMT_FRM_SUBTYPE_SCHED_REQ		10
+/* Schedule Response */
+#define NAN_MGMT_FRM_SUBTYPE_SCHED_RESP		11
+/* Schedule Confirm */
+#define NAN_MGMT_FRM_SUBTYPE_SCHED_CONF		12
+/* Schedule Update */
+#define NAN_MGMT_FRM_SUBTYPE_SCHED_UPD		13
+
+/* Reason code defines */
+#define NAN_REASON_RESERVED			0x0
+#define NAN_REASON_UNSPECIFIED			0x1
+#define NAN_REASON_RESOURCE_LIMIT		0x2
+#define NAN_REASON_INVALID_PARAMS		0x3
+#define NAN_REASON_FTM_PARAM_INCAP		0x4
+#define NAN_REASON_NO_MOVEMENT			0x5
+#define NAN_REASON_INVALID_AVAIL		0x6
+
+/* nan 2.0 qos (not attribute) */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ndp_qos_s {
+	uint8 tid;		/* traffic identifier */
+	uint16 pkt_size;	/* service data pkt size */
+	uint8 data_rate;	/* mean data rate */
+	uint8 svc_interval;	/* max service interval */
+} BWL_POST_PACKED_STRUCT wifi_nan_ndp_qos_t;
+
+/* NDP control bitmap defines */
+#define NAN_NDP_CTRL_CONFIRM_REQUIRED		0x01
+#define NAN_NDP_CTRL_EXPLICIT_CONFIRM		0x02
+#define NAN_NDP_CTRL_SECURTIY_PRESENT		0x04
+#define NAN_NDP_CTRL_PUB_ID_PRESENT		0x08
+#define NAN_NDP_CTRL_RESP_NDI_PRESENT		0x10
+#define NAN_NDP_CTRL_SPEC_INFO_PRESENT		0x20
+#define NAN_NDP_CTRL_RESERVED			0xA0
+
+/* NDP Attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ndp_attr_s {
+	uint8 id;		/* 0x10 */
+	uint16 len;		/* length */
+	uint8 dialog_token;	/* dialog token */
+	uint8 type_status;	/* bits 0-3 type, 4-7 status */
+	uint8 reason;		/* reason code */
+	struct ether_addr init_ndi;	/* ndp initiator's data interface address */
+	uint8 ndp_id;		/* ndp identifier (created by initiator */
+	uint8 control;		/* ndp control field */
+	uint8 var[];		/* Optional fields follow */
+} BWL_POST_PACKED_STRUCT wifi_nan_ndp_attr_t;
+/* NDP attribute type and status macros */
+#define NAN_NDP_TYPE_MASK	0x0F
+#define NAN_NDP_TYPE_REQUEST	0x0
+#define NAN_NDP_TYPE_RESPONSE	0x1
+#define NAN_NDP_TYPE_CONFIRM	0x2
+#define NAN_NDP_TYPE_SECURITY	0x3
+#define NAN_NDP_TYPE_TERMINATE	0x4
+#define NAN_NDP_REQUEST(_ndp)	(((_ndp)->type_status & NAN_NDP_TYPE_MASK) == NAN_NDP_TYPE_REQUEST)
+#define NAN_NDP_RESPONSE(_ndp)	(((_ndp)->type_status & NAN_NDP_TYPE_MASK) == NAN_NDP_TYPE_RESPONSE)
+#define NAN_NDP_CONFIRM(_ndp)	(((_ndp)->type_status & NAN_NDP_TYPE_MASK) == NAN_NDP_TYPE_CONFIRM)
+#define NAN_NDP_SECURITY_INST(_ndp)	(((_ndp)->type_status & NAN_NDP_TYPE_MASK) == \
+									NAN_NDP_TYPE_SECURITY)
+#define NAN_NDP_TERMINATE(_ndp) (((_ndp)->type_status & NAN_NDP_TYPE_MASK) == \
+									NAN_NDP_TYPE_TERMINATE)
+#define NAN_NDP_STATUS_SHIFT	4
+#define NAN_NDP_STATUS_MASK	0xF0
+#define NAN_NDP_STATUS_CONT	(0 << NAN_NDP_STATUS_SHIFT)
+#define NAN_NDP_STATUS_ACCEPT	(1 << NAN_NDP_STATUS_SHIFT)
+#define NAN_NDP_STATUS_REJECT	(2 << NAN_NDP_STATUS_SHIFT)
+#define NAN_NDP_CONT(_ndp)	(((_ndp)->type_status & NAN_NDP_STATUS_MASK) == NAN_NDP_STATUS_CONT)
+#define NAN_NDP_ACCEPT(_ndp)	(((_ndp)->type_status & NAN_NDP_STATUS_MASK) == \
+									NAN_NDP_STATUS_ACCEPT)
+#define NAN_NDP_REJECT(_ndp)	(((_ndp)->type_status & NAN_NDP_STATUS_MASK) == \
+									NAN_NDP_STATUS_REJECT)
+/* NDP Setup Status */
+#define NAN_NDP_SETUP_STATUS_OK		1
+#define NAN_NDP_SETUP_STATUS_FAIL	0
+#define NAN_NDP_SETUP_STATUS_REJECT	2
+
+/* Rng setup attribute type and status macros */
+#define NAN_RNG_TYPE_MASK	0x0F
+#define NAN_RNG_TYPE_REQUEST	0x0
+#define NAN_RNG_TYPE_RESPONSE	0x1
+#define NAN_RNG_TYPE_TERMINATE	0x2
+
+#define NAN_RNG_STATUS_SHIFT	4
+#define NAN_RNG_STATUS_MASK	0xF0
+#define NAN_RNG_STATUS_ACCEPT	(0 << NAN_RNG_STATUS_SHIFT)
+#define NAN_RNG_STATUS_REJECT	(1 << NAN_RNG_STATUS_SHIFT)
+
+#define NAN_RNG_ACCEPT(_rsua)	(((_rsua)->type_status & NAN_RNG_STATUS_MASK) == \
+									NAN_RNG_STATUS_ACCEPT)
+#define NAN_RNG_REJECT(_rsua)	(((_rsua)->type_status & NAN_RNG_STATUS_MASK) == \
+									NAN_RNG_STATUS_REJECT)
+
+/* nan2 ndc ie */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ndc_attr_s {
+	uint8 id;
+	uint16 len;
+	uint8 ndc_id[NAN_DATA_NDC_ID_SIZE];
+	uint8 sched_cntrl;
+	uint8 var[];
+} BWL_POST_PACKED_STRUCT wifi_nan_ndc_attr_t;
+
+/* Schedule Indication */
+#define NAN_NDC_ATTR_SCHED_IND_MASK	0x1E
+#define NAN_NDC_ATTR_SCHED_IND_SHIFT 1
+/* Time Bitmap Present */
+#define NAN_NDC_ATTR_TBMP_PRESENT_MASK	0x20
+#define NAN_NDC_ATTR_TBMP_PRESENT_SHIFT 5
+
+#define NAN_NDC_ATTR_TBMP_CTRL_OFFSET 0
+#define NAN_NDC_ATTR_TBMP_LEN_OFFSET  2
+#define NAN_NDC_ATTR_TBMP_OFFSET      3
+
+/* Proposed NDC */
+#define NAN_NDC_ATTR_PROPOSED_NDC_MASK	0x40
+#define NAN_NDC_ATTR_PROPOSED_NDC_SHIFT 6
+#define NAN_NDC_CTRL_BITMAP_PRESENT(_flags) ((_flags) & \
+	NAN_NDC_ATTR_TBMP_PRESENT_MASK) >> NAN_NDC_ATTR_TBMP_PRESENT_SHIFT
+
+/* Service descriptor extension attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_svc_descriptor_ext_attr_t {
+	/* Attribute ID - 0x11 */
+	uint8 id;
+	/* Length of the following fields in the attribute */
+	uint16 len;
+	/* Instance id of associated service descriptor attribute */
+	uint8 instance_id;
+	/* SDE control field */
+	uint16 control;
+	/* Range limit - ingress */
+	uint16 range_ingress;
+	/* Range limit - egress */
+	uint16 range_egress;
+} BWL_POST_PACKED_STRUCT wifi_nan_svc_descriptor_ext_attr_t;
+#define NAN_SDE_ATTR_LEN (sizeof(wifi_nan_svc_descriptor_ext_attr_t))
+/* SDEA control field bit definitions and access macros */
+#define NAN_SDE_CF_FSD_REQUIRED		(1 << 0)
+#define NAN_SDE_CF_FSD_GAS		(1 << 1)
+#define NAN_SDE_CF_DP_REQUIRED		(1 << 2)
+#define NAN_SDE_CF_DP_TYPE		(1 << 3)
+#define NAN_SDE_CF_MULTICAST_TYPE	(1 << 4)
+#define NAN_SDE_CF_QOS_REQUIRED		(1 << 5)
+#define NAN_SDE_CF_SECURITY_REQUIRED	(1 << 6)
+#define NAN_SDE_CF_RANGING_REQUIRED	(1 << 7)
+#define NAN_SDE_CF_RANGE_PRESENT	(1 << 8)
+#define NAN_SDE_FSD_REQUIRED(_sde)	((_sde)->control & NAN_SDE_CF_FSD_REQUIRED)
+#define NAN_SDE_FSD_GAS(_sde)		((_sde)->control & NAN_SDE_CF_FSD_GAS)
+#define NAN_SDE_DP_REQUIRED(_sde)	((_sde)->control & NAN_SDE_CF_DP_REQUIRED)
+#define NAN_SDE_DP_MULTICAST(_sde)	((_sde)->control & NAN_SDE_CF_DP_TYPE)
+#define NAN_SDE_MULTICAST_M_TO_M(_sde)	((_sde)->control & NAN_SDE_CF_MULTICAST_TYPE)
+#define NAN_SDE_QOS_REQUIRED(_sde)	((_sde)->control & NAN_SDE_CF_QOS_REQUIRED)
+#define NAN_SDE_SECURITY_REQUIRED(_sde)	((_sde)->control & NAN_SDE_CF_SECURITY_REQUIRED)
+#define NAN_SDE_RANGING_REQUIRED(_sde)	((_sde)->control & NAN_SDE_CF_RANGING_REQUIRED)
+#define NAN_SDE_RANGE_PRESENT(_sde)	((_sde)->control & NAN_SDE_CF_RANGE_PRESENT)
+
+/* ********************************************
+* OBSOLETE/DUPLICATES - DO NOT USE BELOW
+**********************************************
+*/
+/* Time Bitmap Control field: Bit Duration - Incorrect. */
+typedef enum
+{
+	NAN_TIME_BMP_CTRL_BIT_DUR_DUR_16TU = 0,
+	NAN_TIME_BMP_CTRL_BIT_DUR_DUR_32TU = 1,
+	NAN_TIME_BMP_CTRL_BIT_DUR_DUR_48TU = 2,
+	NAN_TIME_BMP_CTRL_BIT_DUR_DUR_64TU = 3,
+	NAN_TIME_BMP_CTRL_BIT_DUR_DUR_80TU = 4,
+	NAN_TIME_BMP_CTRL_BIT_DUR_DUR_96TU = 5,
+	NAN_TIME_BMP_CTRL_BIT_DUR_DUR_112TU = 6,
+	NAN_TIME_BMP_CTRL_BIT_DUR_DUR_128TU = 7
+} nan_time_bmp_ctrl_bit_dur_t;
+
+/* FAC Channel Entry  (section 10.7.19.1.5) */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_fac_chan_entry_s {
+	uint8 oper_class;		/* Operating Class */
+	uint16 chan_bitmap;		/* Channel Bitmap */
+	uint8 primary_chan_bmp;		/* Primary Channel Bitmap */
+	uint16 aux_chan;			/* Auxiliary Channel bitmap */
+} BWL_POST_PACKED_STRUCT wifi_nan_fac_chan_entry_t;
+
+/* Channel Entry List Present bit in Entry Control Filed is obsolete (WFA NAN Spec 1.0 r21) */
+#define NAN_AVAIL_ENTRY_CTRL_LIST_PRESENT_MASK 0x4000
+#define NAN_AVAIL_ENTRY_CTRL_LIST_PRESENT_SHIFT 14
+#define NAN_AVAIL_ENTRY_CTRL_LIST_PRESENT(_flags) ((_flags) & \
+	NAN_AVAIL_ENTRY_CTRL_LIST_PRESENT_MASK) >> NAN_AVAIL_ENTRY_CTRL_LIST_PRESENT_SHIFT
+
+/* NDP Information Element (internal) */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ndp_setup_s {
+	uint8 id;		/* 221 */
+	uint8 len;		/* Length */
+	uint8 oui[DOT11_OUI_LEN];	/* "\x00\x10\x18" BRCM OUI */
+	uint8 type;		/* NAN_OUI_TYPE 0x13 */
+	uint8 subtype;		/* NAN_DATA_NDP_SETUP */
+	uint8 msg_type;		/* NDP Req, NDP Resp etc. */
+	uint8 pub_inst_id;	/* publish instance id */
+	struct ether_addr peer_mac_addr; /* publisher mac addr (aka peer mgmt address) */
+	struct ether_addr data_if_addr;	/* local data i/f address */
+	uint8 msg_status;
+	uint8 ndp_ctrl;
+	uint8 security;
+	wifi_nan_ndp_qos_t qos;	/* qos info */
+	uint8 var[1];		/* NDP specific info */
+} BWL_POST_PACKED_STRUCT wifi_nan_ndp_setup_t;
+
+/* NAN mgmt information element */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_mgmt_setup_s {
+	uint8 id;		/* 221 */
+	uint8 len;		/* Length */
+	uint8 oui[DOT11_OUI_LEN];	/* "\x00\x10\x18" BRCM OUI */
+	uint8 type;		/* NAN_OUI_TYPE 0x13 */
+	uint8 subtype;		/* NAN_DATA_MGMT_SETUP */
+	uint8 msg_type;		/* Mgmt Req, Mgmt Resp etc. */
+	uint8 msg_status;
+} BWL_POST_PACKED_STRUCT wifi_nan_mgmt_setup_t;
+
+/* NAN Mgmt Request */
+#define NAN_MGMT_SETUP_MSG_REQ	1	/* don't use 0 */
+/* NAN Mgmt Response */
+#define NAN_MGMT_SETUP_MSG_RESP	2
+
+/* NAN Mgmt Setup Status */
+#define NAN_MGMT_SETUP_STATUS_OK	0
+#define NAN_MGMT_SETUP_STATUS_FAIL	1
+#define NAN_MGMT_SETUP_STATUS_REJECT	2
+
+/* NDL Schedule request */
+#define NAN_MGMT_FRM_SUBTYPE_NDL_UPDATE_REQ	17	/* Not part of spec. ver 1.0.r12 */
+/* NDL Schedule response */
+#define	NAN_MGMT_FRM_SUBTYPE_NDL_UPDATE_RESP	18	/* Not part of spec. ver 1.0.r12 */
+
+/* NAN2 Management */
+/* TODO: Remove this once nan_mgmt module is removed */
+#define NAN_MGMT_FRM_SUBTYPE_MGMT		0
+
+/* NAN 2.0 NDP Setup */
+#define NAN_DATA_NDP_SETUP  0	 /* arbitrary value */
+/* NAN 2.0 Mgmt Setup */
+#define NAN_DATA_MGMT_SETUP 1	 /* arbitrary value */
+/* NAN 2.0 NDL Setup */
+#define NAN_DATA_NDL_SETUP 2	 /* arbitrary value */
+
+/*
+ * Period
+ * Indicate the repeat interval of the following bitmap.
+ * when set to 0, the indicated bitmap is not repeated.
+ * When set to non-zero, the repeat interval is:
+ * 1:128 TU, 2: 256 TU, 3: 512 TU, 4: 1024 TU, 5: 2048 TU, 6: 4096 TU, 7: 8192 TU
+*/
+#define NAN_DATA_MAX_AVAIL_INTRVL	7	/* no. of period intervals supported */
+
+/* no. of peer devices supported TODO make it tunable */
+#define NAN_DATA_PEER_DEV_SUPPORT	8
+/* no. of instaces supported (ndp, mgmt) */
+#define NAN_DATA_NDP_INST_SUPPORT	16
+/* instaces supported (same as ndp) */
+#define NAN_DATA_MGMT_INST_SUPPORT	NAN_DATA_NDP_INST_SUPPORT
+#define NAN_DATA_NDL_INST_SUPPORT	NAN_DATA_PEER_DEV_SUPPORT
+/* ndc base schedule cannot be more than ndl instances */
+#define NAN_DATA_NDC_INST_SUPPORT	NAN_DATA_PEER_DEV_SUPPORT
+
+/* NAN 2.0 (section 5.7.18.2): NAN availability attribute */
+
+/* NAN Availability Attribute */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_availability_attr_s {
+	uint8 id;				/* TBD */
+	uint16 len;				/* length that follows */
+	uint8 attr_cntrl[3];			/* attribute control */
+	uint8 avail_entry_list[1];		/* availability entry list */
+} BWL_POST_PACKED_STRUCT wifi_nan_availability_attr_t;
+
+/* Channel entry */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_channel_entry_s {
+	uint8 opclass;		/* Operating class */
+	uint16 chan_bitmap;	/* Channel bitmap */
+	uint8 prim_bitmap;	/* Primary channel bitmap */
+	uint16 aux_bitmap;	/* Time bitmap length */
+} BWL_POST_PACKED_STRUCT wifi_nan_channel_entry_t;
+
+/* GAS Sechdule Request */
+#define NAN_MGMT_FRM_SUBTYPE_GAS_SCHED_REQ	14	/* Not part of spec. ver 1.0.r12 */
+/* GAS Sechdule Response */
+#define NAN_MGMT_FRM_SUBTYPE_GAS_SCHED_RESP	15	/* Not part of spec. ver 1.0.r12 */
+
+/* DUPLICATES */
+/* Type of  Availability: committed */
+#define NAN_ENTRY_CNTRL_TYPE_COMM_AVAIL_MASK	0x1
+/* Type of  Availability: potential */
+#define NAN_ENTRY_CNTRL_TYPE_POTEN_AVAIL_MASK	0x2
+/* Type of  Availability: conditional */
+#define NAN_ENTRY_CNTRL_TYPE_COND_AVAIL_MASK	0x4
+
+/* Rx Nss */
+#define NAN_ENTRY_CNTRL_RX_NSS_MASK		0x1E00
+#define NAN_ENTRY_CNTRL_RX_NSS_SHIFT		9
+/* Paged Resource block */
+#define NAN_ENTRY_CNTRL_PAGED_RSC_BLK_MASK	0x2000
+#define NAN_ENTRY_CNTRL_PAGED_RSC_BLK_SHIFT	13
+/* Time Bitmap Present */
+#define NAN_ENTRY_CNTRL_TIME_BMP_PRSNT_MASK	0x4000
+#define NAN_ENTRY_CNTRL_TIME_BMP_PRSNT_SHIFT	14
+/* Channel Entry Present */
+#define NAN_ENTRY_CNTRL_CHAN_ENTRY_PRSNT_MASK	0x8000
+#define NAN_ENTRY_CNTRL_CHAN_ENTRY_PRSNT_SHIFT	15
+/* Reserved */
+#define NAN_ENTRY_CNTRL_RESERVED_MASK		0xFF0000
+#define NAN_ENTRY_CNTRL_RESERVED_SHIFT		16
+
+#define NAN_ALL_NAN_MGMT_FRAMES (NAN_FRM_MGMT_AF | \
+	NAN_FRM_NDP_AF | NAN_FRM_NDL_AF | \
+	NAN_FRM_DISC_BCN | NAN_FRM_SYNC_BCN | \
+	NAN_FRM_SVC_DISC)
+
+/* obsoleted by spec r21 */
+typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_ndl_im_sched_ctrl_s {
+	uint8 sched_ctrl;		/* Schedule control */
+	uint16 bitmap_ctrl;		/* Optional field */
+	uint8 time_bitmap_len;		/* Optional field */
+	uint8 time_bitmap[];		/* Optional field */
+} BWL_POST_PACKED_STRUCT wifi_nan_ndl_im_sched_ctrl_t;
+
+#define NDL_ATTR_IM_SCHED_CTRL_LEN		1
+#define NDL_ATTR_IM_SCHED_CTRL_SCHED_IND_MASK 0x1E
+#define NDL_ATTR_IM_SCHED_CTRL_SCHED_IND_SHIFT	1
+#define NDL_ATTR_IM_SCHED_CTRL_TIME_BMP_PRSNT_MASK	0x20
+#define NDL_ATTR_IM_SCHED_CTRL_TIME_BMP_PRSNT_SHIFT	5
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _NAN_H_ */
diff --git a/wl/components/shared/proto/vlan.h b/wl/components/shared/proto/vlan.h
new file mode 100644
index 0000000..eb85151
--- /dev/null
+++ b/wl/components/shared/proto/vlan.h
@@ -0,0 +1,92 @@
+/*
+ * 802.1Q VLAN protocol definitions
+ *
+ * Copyright (C) 2017, Broadcom. 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: vlan.h 518342 2014-12-01 23:21:41Z $
+ */
+
+#ifndef _vlan_h_
+#define _vlan_h_
+
+#ifndef _TYPEDEFS_H_
+#include <typedefs.h>
+#endif
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#ifndef	 VLAN_VID_MASK
+#define VLAN_VID_MASK		0xfff	/* low 12 bits are vlan id */
+#endif
+
+#define	VLAN_CFI_SHIFT		12	/* canonical format indicator bit */
+#define VLAN_PRI_SHIFT		13	/* user priority */
+
+#define VLAN_PRI_MASK		7	/* 3 bits of priority */
+
+#define	VLAN_TPID_OFFSET	12	/* offset of tag protocol id field */
+#define	VLAN_TCI_OFFSET		14	/* offset of tag ctrl info field */
+
+#define	VLAN_TAG_LEN		4
+#define	VLAN_TAG_OFFSET		(2 * ETHER_ADDR_LEN)	/* offset in Ethernet II packet only */
+
+#define VLAN_TPID		0x8100	/* VLAN ethertype/Tag Protocol ID */
+
+struct vlan_header {
+	uint16	vlan_type;		/* 0x8100 */
+	uint16	vlan_tag;		/* priority, cfi and vid */
+};
+
+struct ethervlan_header {
+	uint8	ether_dhost[ETHER_ADDR_LEN];
+	uint8	ether_shost[ETHER_ADDR_LEN];
+	uint16	vlan_type;		/* 0x8100 */
+	uint16	vlan_tag;		/* priority, cfi and vid */
+	uint16	ether_type;
+};
+
+struct dot3_mac_llc_snapvlan_header {
+	uint8	ether_dhost[ETHER_ADDR_LEN];	/* dest mac */
+	uint8	ether_shost[ETHER_ADDR_LEN];	/* src mac */
+	uint16	length;				/* frame length incl header */
+	uint8	dsap;				/* always 0xAA */
+	uint8	ssap;				/* always 0xAA */
+	uint8	ctl;				/* always 0x03 */
+	uint8	oui[3];				/* RFC1042: 0x00 0x00 0x00
+						 * Bridge-Tunnel: 0x00 0x00 0xF8
+						 */
+	uint16	vlan_type;			/* 0x8100 */
+	uint16	vlan_tag;			/* priority, cfi and vid */
+	uint16	ether_type;			/* ethertype */
+};
+
+#define	ETHERVLAN_HDR_LEN	(ETHER_HDR_LEN + VLAN_TAG_LEN)
+
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#define ETHERVLAN_MOVE_HDR(d, s) \
+do { \
+	struct ethervlan_header t; \
+	t = *(struct ethervlan_header *)(s); \
+	*(struct ethervlan_header *)(d) = t; \
+} while (0)
+
+#endif /* _vlan_h_ */
diff --git a/wl/components/shared/proto/wpa.h b/wl/components/shared/proto/wpa.h
new file mode 100644
index 0000000..68ac03c
--- /dev/null
+++ b/wl/components/shared/proto/wpa.h
@@ -0,0 +1,206 @@
+/*
+ * Fundamental types and constants relating to WPA
+ *
+ * Copyright (C) 2017, Broadcom. 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: wpa.h 518342 2014-12-01 23:21:41Z $
+ */
+
+#ifndef _proto_wpa_h_
+#define _proto_wpa_h_
+
+#include <typedefs.h>
+#include <proto/ethernet.h>
+
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+/* Reason Codes */
+
+/* 13 through 23 taken from IEEE Std 802.11i-2004 */
+#define DOT11_RC_INVALID_WPA_IE		13	/* Invalid info. element */
+#define DOT11_RC_MIC_FAILURE		14	/* Michael failure */
+#define DOT11_RC_4WH_TIMEOUT		15	/* 4-way handshake timeout */
+#define DOT11_RC_GTK_UPDATE_TIMEOUT	16	/* Group key update timeout */
+#define DOT11_RC_WPA_IE_MISMATCH	17	/* WPA IE in 4-way handshake differs from
+						 * (re-)assoc. request/probe response
+						 */
+#define DOT11_RC_INVALID_MC_CIPHER	18	/* Invalid multicast cipher */
+#define DOT11_RC_INVALID_UC_CIPHER	19	/* Invalid unicast cipher */
+#define DOT11_RC_INVALID_AKMP		20	/* Invalid authenticated key management protocol */
+#define DOT11_RC_BAD_WPA_VERSION	21	/* Unsupported WPA version */
+#define DOT11_RC_INVALID_WPA_CAP	22	/* Invalid WPA IE capabilities */
+#define DOT11_RC_8021X_AUTH_FAIL	23	/* 802.1X authentication failure */
+
+#define WPA2_PMKID_LEN	16
+
+/* WPA IE fixed portion */
+typedef BWL_PRE_PACKED_STRUCT struct
+{
+	uint8 tag;	/* TAG */
+	uint8 length;	/* TAG length */
+	uint8 oui[3];	/* IE OUI */
+	uint8 oui_type;	/* OUI type */
+	BWL_PRE_PACKED_STRUCT struct {
+		uint8 low;
+		uint8 high;
+	} BWL_POST_PACKED_STRUCT version;	/* IE 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
+
+#define BIP_OUI_TYPE WPA2_OUI "\x06"
+
+typedef BWL_PRE_PACKED_STRUCT struct {
+	uint8 tag;	/* TAG */
+	uint8 length;	/* TAG length */
+	BWL_PRE_PACKED_STRUCT struct {
+		uint8 low;
+		uint8 high;
+	} BWL_POST_PACKED_STRUCT version;	/* IE 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];
+
+#define WFA_OSEN_IE_FIXED_LEN	6
+
+/* WPA suite/multicast suite */
+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
+
+/* WPA unicast suite list/key management suite list */
+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;
+
+/* WPA cipher suites */
+#define WPA_CIPHER_NONE		0	/* None */
+#define WPA_CIPHER_WEP_40	1	/* WEP (40-bit) */
+#define WPA_CIPHER_TKIP		2	/* TKIP: default for WPA */
+#define WPA_CIPHER_AES_OCB	3	/* AES (OCB) */
+#define WPA_CIPHER_AES_CCM	4	/* AES (CCM) */
+#define WPA_CIPHER_WEP_104	5	/* WEP (104-bit) */
+#define WPA_CIPHER_BIP		6	/* WEP (104-bit) */
+#define WPA_CIPHER_TPK		7	/* Group addressed traffic not allowed */
+
+#ifdef BCMWAPI_WAI
+#define WAPI_CIPHER_NONE	WPA_CIPHER_NONE
+#define WAPI_CIPHER_SMS4	11
+
+#define WAPI_CSE_WPI_SMS4	1
+#endif /* BCMWAPI_WAI */
+
+#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)
+
+#ifdef BCMWAPI_WAI
+#define IS_WAPI_CIPHER(cipher)	((cipher) == WAPI_CIPHER_NONE || \
+				 (cipher) == WAPI_CSE_WPI_SMS4)
+
+/* convert WAPI_CSE_WPI_XXX to WAPI_CIPHER_XXX */
+#define WAPI_CSE_WPI_2_CIPHER(cse) ((cse) == WAPI_CSE_WPI_SMS4 ? \
+				WAPI_CIPHER_SMS4 : WAPI_CIPHER_NONE)
+
+#define WAPI_CIPHER_2_CSE_WPI(cipher) ((cipher) == WAPI_CIPHER_SMS4 ? \
+				WAPI_CSE_WPI_SMS4 : WAPI_CIPHER_NONE)
+#endif /* BCMWAPI_WAI */
+
+/* WPA TKIP countermeasures parameters */
+#define WPA_TKIP_CM_DETECT	60	/* multiple MIC failure window (seconds) */
+#define WPA_TKIP_CM_BLOCK	60	/* countermeasures active window (seconds) */
+
+/* RSN IE defines */
+#define RSN_CAP_LEN		2	/* Length of RSN capabilities field (2 octets) */
+
+/* RSN Capabilities defined in 802.11i */
+#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
+
+/* WPA capabilities defined in 802.11i */
+#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
+
+/* WPA capabilities defined in 802.11zD9.0 */
+#define WPA_CAP_PEER_KEY_ENABLE		(0x1 << 1)	/* bit 9 */
+
+/* WPA Specific defines */
+#define WPA_CAP_LEN	RSN_CAP_LEN	/* Length of RSN capabilities in RSN IE (2 octets) */
+#define WPA_PMKID_CNT_LEN	2 	/* Length of RSN PMKID count (2 octests) */
+
+#define	WPA_CAP_WPA2_PREAUTH		RSN_CAP_PREAUTH
+
+#define WPA2_PMKID_COUNT_LEN	2
+
+#ifdef BCMWAPI_WAI
+#define WAPI_CAP_PREAUTH		RSN_CAP_PREAUTH
+
+/* Other WAI definition */
+#define WAPI_WAI_REQUEST		0x00F1
+#define WAPI_UNICAST_REKEY		0x00F2
+#define WAPI_STA_AGING			0x00F3
+#define WAPI_MUTIL_REKEY		0x00F4
+#define WAPI_STA_STATS			0x00F5
+
+#define WAPI_USK_REKEY_COUNT		0x4000000 /* 0xA00000 */
+#define WAPI_MSK_REKEY_COUNT		0x4000000 /* 0xA00000 */
+#endif /* BCMWAPI_WAI */
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+#endif /* _proto_wpa_h_ */
diff --git a/wl/components/shared/proto/wps.h b/wl/components/shared/proto/wps.h
new file mode 100644
index 0000000..4569a84
--- /dev/null
+++ b/wl/components/shared/proto/wps.h
@@ -0,0 +1,383 @@
+/*
+ * WPS IE definitions
+ *
+ * Copyright (C) 2017, Broadcom. 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$
+ */
+
+#ifndef _WPS_
+#define _WPS_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Data Element Definitions */
+#define WPS_ID_AP_CHANNEL         0x1001
+#define WPS_ID_ASSOC_STATE        0x1002
+#define WPS_ID_AUTH_TYPE          0x1003
+#define WPS_ID_AUTH_TYPE_FLAGS    0x1004
+#define WPS_ID_AUTHENTICATOR      0x1005
+#define WPS_ID_CONFIG_METHODS     0x1008
+#define WPS_ID_CONFIG_ERROR       0x1009
+#define WPS_ID_CONF_URL4          0x100A
+#define WPS_ID_CONF_URL6          0x100B
+#define WPS_ID_CONN_TYPE          0x100C
+#define WPS_ID_CONN_TYPE_FLAGS    0x100D
+#define WPS_ID_CREDENTIAL         0x100E
+#define WPS_ID_DEVICE_NAME        0x1011
+#define WPS_ID_DEVICE_PWD_ID      0x1012
+#define WPS_ID_E_HASH1            0x1014
+#define WPS_ID_E_HASH2            0x1015
+#define WPS_ID_E_SNONCE1          0x1016
+#define WPS_ID_E_SNONCE2          0x1017
+#define WPS_ID_ENCR_SETTINGS      0x1018
+#define WPS_ID_ENCR_TYPE          0x100F
+#define WPS_ID_ENCR_TYPE_FLAGS    0x1010
+#define WPS_ID_ENROLLEE_NONCE     0x101A
+#define WPS_ID_FEATURE_ID         0x101B
+#define WPS_ID_IDENTITY           0x101C
+#define WPS_ID_IDENTITY_PROOF     0x101D
+#define WPS_ID_KEY_WRAP_AUTH      0x101E
+#define WPS_ID_KEY_IDENTIFIER     0x101F
+#define WPS_ID_MAC_ADDR           0x1020
+#define WPS_ID_MANUFACTURER       0x1021
+#define WPS_ID_MSG_TYPE           0x1022
+#define WPS_ID_MODEL_NAME         0x1023
+#define WPS_ID_MODEL_NUMBER       0x1024
+#define WPS_ID_NW_INDEX           0x1026
+#define WPS_ID_NW_KEY             0x1027
+#define WPS_ID_NW_KEY_INDEX       0x1028
+#define WPS_ID_NEW_DEVICE_NAME    0x1029
+#define WPS_ID_NEW_PWD            0x102A
+#define WPS_ID_OOB_DEV_PWD        0x102C
+#define WPS_ID_OS_VERSION         0x102D
+#define WPS_ID_POWER_LEVEL        0x102F
+#define WPS_ID_PSK_CURRENT        0x1030
+#define WPS_ID_PSK_MAX            0x1031
+#define WPS_ID_PUBLIC_KEY         0x1032
+#define WPS_ID_RADIO_ENABLED      0x1033
+#define WPS_ID_REBOOT             0x1034
+#define WPS_ID_REGISTRAR_CURRENT  0x1035
+#define WPS_ID_REGISTRAR_ESTBLSHD 0x1036
+#define WPS_ID_REGISTRAR_LIST     0x1037
+#define WPS_ID_REGISTRAR_MAX      0x1038
+#define WPS_ID_REGISTRAR_NONCE    0x1039
+#define WPS_ID_REQ_TYPE           0x103A
+#define WPS_ID_RESP_TYPE          0x103B
+#define WPS_ID_RF_BAND            0x103C
+#define WPS_ID_R_HASH1            0x103D
+#define WPS_ID_R_HASH2            0x103E
+#define WPS_ID_R_SNONCE1          0x103F
+#define WPS_ID_R_SNONCE2          0x1040
+#define WPS_ID_SEL_REGISTRAR      0x1041
+#define WPS_ID_SERIAL_NUM         0x1042
+#define WPS_ID_SC_STATE           0x1044
+#define WPS_ID_SSID               0x1045
+#define WPS_ID_TOT_NETWORKS       0x1046
+#define WPS_ID_UUID_E             0x1047
+#define WPS_ID_UUID_R             0x1048
+#define WPS_ID_VENDOR_EXT         0x1049
+#define WPS_ID_VERSION            0x104A
+#define WPS_ID_X509_CERT_REQ      0x104B
+#define WPS_ID_X509_CERT          0x104C
+#define WPS_ID_EAP_IDENTITY       0x104D
+#define WPS_ID_MSG_COUNTER        0x104E
+#define WPS_ID_PUBKEY_HASH        0x104F
+#define WPS_ID_REKEY_KEY          0x1050
+#define WPS_ID_KEY_LIFETIME       0x1051
+#define WPS_ID_PERM_CFG_METHODS   0x1052
+#define WPS_ID_SEL_REG_CFG_METHODS 0x1053
+#define WPS_ID_PRIM_DEV_TYPE      0x1054
+#define WPS_ID_SEC_DEV_TYPE_LIST  0x1055
+#define WPS_ID_PORTABLE_DEVICE    0x1056
+#define WPS_ID_AP_SETUP_LOCKED    0x1057
+#define WPS_ID_APP_LIST           0x1058
+#define WPS_ID_EAP_TYPE           0x1059
+#define WPS_ID_INIT_VECTOR        0x1060
+#define WPS_ID_KEY_PROVIDED_AUTO  0x1061
+#define WPS_ID_8021X_ENABLED      0x1062
+#define WPS_ID_WEP_TRANSMIT_KEY   0x1064
+#define WPS_ID_REQ_DEV_TYPE       0x106A
+
+/* WSC 2.0, WFA Vendor Extension Subelements */
+#define WFA_VENDOR_EXT_ID                 "\x00\x37\x2A"
+#define WPS_WFA_SUBID_VERSION2            0x00
+#define WPS_WFA_SUBID_AUTHORIZED_MACS     0x01
+#define WPS_WFA_SUBID_NW_KEY_SHAREABLE    0x02
+#define WPS_WFA_SUBID_REQ_TO_ENROLL       0x03
+#define WPS_WFA_SUBID_SETTINGS_DELAY_TIME 0x04
+#define WPS_WFA_SUBID_REG_CFG_METHODS     0x05
+
+
+/* WCN-NET Windows Rally Vertical Pairing Vendor Extensions */
+#define MS_VENDOR_EXT_ID           "\x00\x01\x37"
+#define WPS_MS_ID_VPI               0x1001	/* Vertical Pairing Identifier TLV */
+#define WPS_MS_ID_TRANSPORT_UUID    0x1002      /* Transport UUID TLV */
+
+/* Vertical Pairing Identifier TLV Definitions */
+#define WPS_MS_VPI_TRANSPORT_NONE   0x00        /* None */
+#define WPS_MS_VPI_TRANSPORT_DPWS   0x01        /* Devices Profile for Web Services */
+#define WPS_MS_VPI_TRANSPORT_UPNP   0x02        /* uPnP */
+#define WPS_MS_VPI_TRANSPORT_SDNWS  0x03        /* Secure Devices Profile for Web Services */
+#define WPS_MS_VPI_NO_PROFILE_REQ   0x00        /* Wi-Fi profile not requested.
+						 * Not supported in Windows 7
+						 */
+#define WPS_MS_VPI_PROFILE_REQ      0x01        /* Wi-Fi profile requested.  */
+
+/* sizes of the fixed size elements */
+#define WPS_ID_AP_CHANNEL_S       2
+#define WPS_ID_ASSOC_STATE_S      2
+#define WPS_ID_AUTH_TYPE_S        2
+#define WPS_ID_AUTH_TYPE_FLAGS_S  2
+#define WPS_ID_AUTHENTICATOR_S    8
+#define WPS_ID_CONFIG_METHODS_S   2
+#define WPS_ID_CONFIG_ERROR_S     2
+#define WPS_ID_CONN_TYPE_S          1
+#define WPS_ID_CONN_TYPE_FLAGS_S    1
+#define WPS_ID_DEVICE_PWD_ID_S      2
+#define WPS_ID_ENCR_TYPE_S          2
+#define WPS_ID_ENCR_TYPE_FLAGS_S    2
+#define WPS_ID_FEATURE_ID_S         4
+#define WPS_ID_MAC_ADDR_S           6
+#define WPS_ID_MSG_TYPE_S           1
+#define WPS_ID_SC_STATE_S           1
+#define WPS_ID_RF_BAND_S            1
+#define WPS_ID_OS_VERSION_S         4
+#define WPS_ID_VERSION_S            1
+#define WPS_ID_SEL_REGISTRAR_S      1
+#define WPS_ID_SEL_REG_CFG_METHODS_S 2
+#define WPS_ID_REQ_TYPE_S           1
+#define WPS_ID_RESP_TYPE_S          1
+#define WPS_ID_AP_SETUP_LOCKED_S    1
+
+/* WSC 2.0, WFA Vendor Extension Subelements */
+#define WPS_WFA_SUBID_VERSION2_S            1
+#define WPS_WFA_SUBID_NW_KEY_SHAREABLE_S    1
+#define WPS_WFA_SUBID_REQ_TO_ENROLL_S       1
+#define WPS_WFA_SUBID_SETTINGS_DELAY_TIME_S 1
+#define WPS_WFA_SUBID_REG_CFG_METHODS_S     2
+
+/* Association states */
+#define WPS_ASSOC_NOT_ASSOCIATED  0
+#define WPS_ASSOC_CONN_SUCCESS    1
+#define WPS_ASSOC_CONFIG_FAIL     2
+#define WPS_ASSOC_ASSOC_FAIL      3
+#define WPS_ASSOC_IP_FAIL         4
+
+/* Authentication types */
+#define WPS_AUTHTYPE_OPEN        0x0001
+#define WPS_AUTHTYPE_WPAPSK      0x0002	/* Deprecated in WSC 2.0 */
+#define WPS_AUTHTYPE_SHARED      0x0004	/* Deprecated in WSC 2.0 */
+#define WPS_AUTHTYPE_WPA         0x0008	/* Deprecated in WSC 2.0 */
+#define WPS_AUTHTYPE_WPA2        0x0010
+#define WPS_AUTHTYPE_WPA2PSK     0x0020
+
+/* Config methods */
+#define WPS_CONFMET_USBA            0x0001	/* Deprecated in WSC 2.0 */
+#define WPS_CONFMET_ETHERNET        0x0002	/* Deprecated in WSC 2.0 */
+#define WPS_CONFMET_LABEL           0x0004
+#define WPS_CONFMET_DISPLAY         0x0008
+#define WPS_CONFMET_EXT_NFC_TOK     0x0010
+#define WPS_CONFMET_INT_NFC_TOK     0x0020
+#define WPS_CONFMET_NFC_INTF        0x0040
+#define WPS_CONFMET_PBC             0x0080
+#define WPS_CONFMET_KEYPAD          0x0100
+/* WSC 2.0 */
+#define WPS_CONFMET_VIRT_PBC        0x0280
+#define WPS_CONFMET_PHY_PBC         0x0480
+#define WPS_CONFMET_VIRT_DISPLAY    0x2008
+#define WPS_CONFMET_PHY_DISPLAY     0x4008
+
+/* WPS error messages */
+#define WPS_ERROR_NO_ERROR                0
+#define WPS_ERROR_OOB_INT_READ_ERR        1
+#define WPS_ERROR_DECRYPT_CRC_FAIL        2
+#define WPS_ERROR_CHAN24_NOT_SUPP         3
+#define WPS_ERROR_CHAN50_NOT_SUPP         4
+#define WPS_ERROR_SIGNAL_WEAK             5	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_NW_AUTH_FAIL            6	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_NW_ASSOC_FAIL           7	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_NO_DHCP_RESP            8	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_FAILED_DHCP_CONF        9	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_IP_ADDR_CONFLICT        10	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_FAIL_CONN_REGISTRAR     11
+#define WPS_ERROR_MULTI_PBC_DETECTED      12
+#define WPS_ERROR_ROGUE_SUSPECTED         13
+#define WPS_ERROR_DEVICE_BUSY             14
+#define WPS_ERROR_SETUP_LOCKED            15
+#define WPS_ERROR_MSG_TIMEOUT             16	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_REG_SESSION_TIMEOUT     17	/* Deprecated in WSC 2.0 */
+#define WPS_ERROR_DEV_PWD_AUTH_FAIL       18
+#define WPS_ERROR_60GHZ_NOT_SUPPORT       19
+#define WPS_ERROR_PKH_MISMATCH            20	/* Public Key Hash Mismatch */
+
+/* Connection types */
+#define WPS_CONNTYPE_ESS    0x01
+#define WPS_CONNTYPE_IBSS   0x02
+
+/* Device password ID */
+#define WPS_DEVICEPWDID_DEFAULT          0x0000
+#define WPS_DEVICEPWDID_USER_SPEC        0x0001
+#define WPS_DEVICEPWDID_MACHINE_SPEC     0x0002
+#define WPS_DEVICEPWDID_REKEY            0x0003
+#define WPS_DEVICEPWDID_PUSH_BTN         0x0004
+#define WPS_DEVICEPWDID_REG_SPEC         0x0005
+#define WPS_DEVICEPWDID_IBSS             0x0006
+#define WPS_DEVICEPWDID_NFC_CHO          0x0007	/* NFC-Connection-Handover */
+#define WPS_DEVICEPWDID_WFDS             0x0008	/* Wi-Fi Direct Services Specification */
+
+/* Encryption type */
+#define WPS_ENCRTYPE_NONE    0x0001
+#define WPS_ENCRTYPE_WEP     0x0002	/* Deprecated in WSC 2.0 */
+#define WPS_ENCRTYPE_TKIP    0x0004	/* Deprecated in version 2.0. TKIP can only
+					  * be advertised on the AP when Mixed Mode
+					  * is enabled (Encryption Type is 0x000c).
+					  */
+#define WPS_ENCRTYPE_AES     0x0008
+
+
+/* WPS Message Types */
+#define WPS_ID_BEACON            0x01
+#define WPS_ID_PROBE_REQ         0x02
+#define WPS_ID_PROBE_RESP        0x03
+#define WPS_ID_MESSAGE_M1        0x04
+#define WPS_ID_MESSAGE_M2        0x05
+#define WPS_ID_MESSAGE_M2D       0x06
+#define WPS_ID_MESSAGE_M3        0x07
+#define WPS_ID_MESSAGE_M4        0x08
+#define WPS_ID_MESSAGE_M5        0x09
+#define WPS_ID_MESSAGE_M6        0x0A
+#define WPS_ID_MESSAGE_M7        0x0B
+#define WPS_ID_MESSAGE_M8        0x0C
+#define WPS_ID_MESSAGE_ACK       0x0D
+#define WPS_ID_MESSAGE_NACK      0x0E
+#define WPS_ID_MESSAGE_DONE      0x0F
+
+/* WSP private ID for local use */
+#define WPS_PRIVATE_ID_IDENTITY		(WPS_ID_MESSAGE_DONE + 1)
+#define WPS_PRIVATE_ID_WPS_START	(WPS_ID_MESSAGE_DONE + 2)
+#define WPS_PRIVATE_ID_FAILURE		(WPS_ID_MESSAGE_DONE + 3)
+#define WPS_PRIVATE_ID_FRAG		(WPS_ID_MESSAGE_DONE + 4)
+#define WPS_PRIVATE_ID_FRAG_ACK		(WPS_ID_MESSAGE_DONE + 5)
+#define WPS_PRIVATE_ID_EAPOL_START	(WPS_ID_MESSAGE_DONE + 6)
+
+
+/* Device Type categories for primary and secondary device types */
+#define WPS_DEVICE_TYPE_CAT_COMPUTER        1
+#define WPS_DEVICE_TYPE_CAT_INPUT_DEVICE    2
+#define WPS_DEVICE_TYPE_CAT_PRINTER         3
+#define WPS_DEVICE_TYPE_CAT_CAMERA          4
+#define WPS_DEVICE_TYPE_CAT_STORAGE         5
+#define WPS_DEVICE_TYPE_CAT_NW_INFRA        6
+#define WPS_DEVICE_TYPE_CAT_DISPLAYS        7
+#define WPS_DEVICE_TYPE_CAT_MM_DEVICES      8
+#define WPS_DEVICE_TYPE_CAT_GAME_DEVICES    9
+#define WPS_DEVICE_TYPE_CAT_TELEPHONE       10
+#define WPS_DEVICE_TYPE_CAT_AUDIO_DEVICES   11	/* WSC 2.0 */
+
+/* Device Type sub categories for primary and secondary device types */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_PC         1
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_SERVER     2
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_MEDIA_CTR  3
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_UM_PC      4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_NOTEBOOK   5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_DESKTOP    6	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_MID        7	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_COMP_NETBOOK    8	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_Keyboard    1	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_MOUSE       2	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_JOYSTICK    3	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_TRACKBALL   4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_GAM_CTRL    5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_REMOTE      6	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_TOUCHSCREEN 7	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_BIO_READER  8	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_INP_BAR_READER  9	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_PRINTER    1
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_SCANNER    2
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_FAX        3	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_COPIER     4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PRTR_ALLINONE   5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_DGTL_STILL  1
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_VIDEO_CAM   2	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_WEB_CAM     3	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_CAM_SECU_CAM    4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_STOR_NAS        1
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_AP           1
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_ROUTER       2
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_SWITCH       3
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_GATEWAY      4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_NW_BRIDGE       5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_TV         1
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_PIC_FRAME  2
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_PROJECTOR  3
+#define WPS_DEVICE_TYPE_SUB_CAT_DISP_MONITOR    4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_DAR          1
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_PVR          2
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_MCX          3
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_STB          4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_MS_ME        5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_MM_PVP          6	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_XBOX        1
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_XBOX_360    2
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_PS          3
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_GC          4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_GAM_PGD         5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_WM        1
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_PSM       2	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_PDM       3	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_SSM       4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_PHONE_SDM       5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_TUNER     1	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_SPEAKERS  2	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_PMP       3	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HEADSET   4	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HPHONE    5	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_MPHONE    6	/* WSC 2.0 */
+#define WPS_DEVICE_TYPE_SUB_CAT_AUDIO_HTS       7	/* WSC 2.0 */
+
+
+/* Device request/response type */
+#define WPS_MSGTYPE_ENROLLEE_INFO_ONLY    0x00
+#define WPS_MSGTYPE_ENROLLEE_OPEN_8021X   0x01
+#define WPS_MSGTYPE_REGISTRAR             0x02
+#define WPS_MSGTYPE_AP_WLAN_MGR           0x03
+
+/* RF Band */
+#define WPS_RFBAND_24GHZ    0x01
+#define WPS_RFBAND_50GHZ    0x02
+
+/* Simple Config state */
+#define WPS_SCSTATE_UNCONFIGURED    0x01
+#define WPS_SCSTATE_CONFIGURED      0x02
+#define WPS_SCSTATE_OFF 11
+
+/* WPS Vendor extension key */
+#define WPS_OUI_HEADER_LEN 2
+#define WPS_OUI_HEADER_SIZE 4
+#define WPS_OUI_FIXED_HEADER_OFF 16
+#define WPS_WFA_SUBID_V2_OFF 3
+#define WPS_WFA_V2_OFF 5
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WPS_ */
diff --git a/wl/src/Makerules b/wl/src/Makerules
new file mode 100644
index 0000000..e576370
--- /dev/null
+++ b/wl/src/Makerules
@@ -0,0 +1,639 @@
+
+
+#
+#  Top level Makerules
+#  it uses Makerules.env for build env vars and optional branding.inc
+#
+#  Copyright (C) 2017, Broadcom. 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: Makerules 646625 2016-06-30 02:57:52Z $
+
+# This is the TOP level makefile rules, which is used by many makefiles.
+# Please be cautious on changes, especially compatibilities.
+#   e.g. new gcc compile option should be protected with version check 
+#        or "check_gcc" trick
+
+# first rule (default)
+all:
+
+APPLY_PREFIX ?= true
+
+WLAN_ComponentsInUse ?= bcmwifi
+include $(dir $(lastword $(MAKEFILE_LIST)))makefiles/WLAN_Common.mk
+
+# Set up the build environment variables
+include ${SRCBASE}/Makerules.env
+
+ifeq ($(HOSTOS), Windows_NT)
+
+# force use of bash, otherwise you will get the broken sh.exe.
+SHELL=bash
+
+endif
+
+#
+# Setup make variables depending on target
+#
+
+ifeq ($(TARGETOS), unix)
+
+	# The environment for native unix builds
+
+	EXEEXT	= 
+	OBJEXT	= .o
+	GCINCS	= $(strip -I$(SRCBASE)/include $(WLAN_ComponentIncPath)) $(WLAN_StdIncPathA)
+	GCDEFS	= -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) -DTARGETARCH_$(TARGETARCH)
+
+	ifeq ($(TARGETARCH), x86_mmx)
+		GCDEFS	:= $(GCDEFS) -D_X86_ -D_MMX_
+	endif
+	ifeq ($(TARGETARCH), x86)
+		GCDEFS	:= $(GCDEFS) -D_X86_
+	endif
+	ifeq ($(TARGETARCH), x86_android_ndk_r6b)
+		GCDEFS	:= $(GCDEFS) -D_X86_
+	endif
+	ifeq ($(TARGETARCH), mips)
+		GCDEFS	:= $(GCDEFS) -D_MIPS_
+	endif
+	ifeq ($(TARGETARCH), mips_be)
+		GCDEFS	:= $(GCDEFS) -D_MIPS_ -DIL_BIGENDIAN
+	endif
+	ifeq ($(TARGETARCH), arm)
+		GCDEFS	:= $(GCDEFS) -D_ARM_ -DIL_BIGENDIAN
+	endif
+	ifeq ($(TARGETARCH), arm_le)
+		GCDEFS	:= $(GCDEFS) -D_ARM_
+	endif
+	ifeq ($(TARGETARCH), arm_android)
+		GCDEFS	:= $(GCDEFS) -D_ARM_
+	endif
+	ifeq ($(TARGETARCH), arm64_android)
+		GCDEFS	:= $(GCDEFS) -D_ARM_
+	endif
+	ifeq ($(TARGETARCH), arm_android_ndk_r6b)
+		GCDEFS	:= $(GCDEFS) -D_ARM_
+	endif
+
+#	ifeq ($(TARGETENV), freebsd)
+#		ifeq ($(HOSTENV), freebsd)
+#			GCINCS	:= $(GCINCS) -I/usr/include
+#		endif
+#	endif
+	ifeq ($(TARGETENV), sun4)
+		GCDEFS	:= $(GCDEFS) -D_SPARC_
+	endif
+	ifeq ($(TARGETENV), macos)
+		MACOS_VER := $(shell sw_vers -productVersion)
+
+		# Default dev dir
+		dev_dir := /Applications/Xcode.app/Contents/Developer
+
+		# SDKs dir in the default Developer dir
+		sdk_dir := $(dev_dir)/Platforms/MacOSX.platform/Developer/SDKs
+
+		# Set default SDKROOT based on the host machine MacOS version
+		# If command line SDKROOT is provided, it will take precedence
+
+		ifneq (,$(findstring 10.11,$(MACOS_VER)))
+			export SDKROOT := $(sdk_dir)/MacOSX10.11.sdk
+
+		else ifneq (,$(findstring 10.10,$(MACOS_VER)))
+			export SDKROOT := $(sdk_dir)/MacOSX10.10.sdk
+
+		else ifneq (,$(findstring 10.9,$(MACOS_VER)))
+			export SDKROOT := $(sdk_dir)/MacOSX10.9.sdk
+
+		else ifneq (,$(findstring 10.8,$(MACOS_VER)))
+			export SDKROOT := $(sdk_dir)/MacOSX10.8.sdk
+
+		else ifneq (,$(findstring 10.7,$(MACOS_VER)))
+			SDK=/Developer/SDKs/MacOSX10.7.sdk
+			GCDEFS	+= -isysroot $(SDK)
+
+		else ifneq (,$(findstring 10.6,$(MACOS_VER)))
+			SDK=/Developer/SDKs/MacOSX10.6.sdk
+			GCDEFS	+= -isysroot $(SDK)
+		endif
+
+		GCDEFS	:= $(GCDEFS) -DMACOSX
+
+		ifeq ($(TARGETARCH), PPC)
+			GCDEFS	:= $(GCDEFS) -arch ppc -mtune=G4
+			GLDFLAGS = -arch ppc -Wl,-syslibroot,$(SDK)
+		endif
+		ifeq ($(TARGETARCH), x86)
+			GCDEFS	:= $(GCDEFS) -arch x86_64
+			GLDFLAGS = -arch x86_64
+		endif
+	endif
+
+	GCOPTS	=
+	GCFLAGS	= -g -Wall
+
+	CC_TARGET	=-o $@
+	LINK_TARGET	=-o $@
+
+	ifeq ($(TARGETENV), linuxmips)
+		TARGET_PREFIX = mipsel-linux-
+	else
+	ifeq ($(TARGETENV), linuxmips_be)
+		TARGET_PREFIX = mips-linux-
+	else
+	ifeq ($(TARGETENV), linuxarm)
+		TARGET_PREFIX = armeb-linux-
+	else
+	ifeq ($(TARGETENV), linuxarm_le)
+		TARGET_PREFIX ?= arm-linux-
+		ifneq ($(LINUXDIR),)
+		GCFLAGS += -I$(LINUXDIR)/include
+		endif
+	else
+	ifeq ($(TARGETENV), android)
+		TARGET_PREFIX ?= arm-eabi-
+		GCFLAGS += -Dlinux -DTARGETENV_android
+	else
+	ifeq ($(TARGETENV), android_ndk_r6b)
+		#TARGET_PREFIX = arm-linux-androideabi-
+
+		ifeq ($(TARGET_PREFIX),)
+$(warning : TARGET_PREFIX is not set!)
+		endif
+		ifeq ($(TARGET_NDK),)
+$(warning : TARGET_NDK is not set!)
+		endif
+		ifeq ($(LINUXDIR),)
+$(warning : LINUXDIR is not set!)
+		endif
+		GCDEFS	:= $(GCDEFS) -fno-short-enums
+
+		GCFLAGS += -Dlinux -DTARGETENV_android
+		ifeq ($(TARGETARCH), arm_android_ndk_r6b)
+			GCFLAGS += -DTARGETARCH_arm_android
+			GCFLAGS += -I$(TARGET_NDK)/platforms/android-9/arch-arm/usr/include/
+			GCFLAGS += -march=armv5te -mtune=xscale -msoft-float
+			GCFLAGS += -mthumb-interwork
+		else
+		ifeq ($(TARGETARCH), x86_android_ndk_r6b)
+			GCFLAGS += -DTARGETARCH_x86_android
+			GCFLAGS += -I$(TARGET_NDK)/platforms/android-9/arch-x86/usr/include/
+			GCFLAGS += -march=i686
+		endif
+		endif
+		GCFLAGS += -fpic -fno-exceptions
+		GCFLAGS += -ffunction-sections -funwind-tables
+		GCFLAGS += -fstack-protector -fmessage-length=0
+		GCFLAGS += -I$(LINUXDIR)/include/uapi/
+		GCFLAGS += -I$(LINUXDIR)/include/
+	else
+		TARGET_PREFIX =
+	endif
+	endif
+	endif
+	endif
+	endif
+	endif
+
+	ifeq ($(APPLY_PREFIX),true)
+		CC = $(TARGET_PREFIX)gcc
+		AS = $(TARGET_PREFIX)as
+		LD = $(TARGET_PREFIX)ld
+		AR = $(TARGET_PREFIX)ar
+	endif
+
+	INSTALL = install -c
+
+	TCFLAGS =
+
+	ifeq ($(TARGETENV), freebsd)
+		GLDFLAGS = -static
+	endif
+	ifeq ($(TARGETENV), freebsd_be)
+		GLDFLAGS = -static
+	endif
+	ifeq ($(TARGETENV), linuxarm)
+		GLDFLAGS = -static
+	endif
+	ifeq ($(TARGETENV), linuxarm_le)
+		GLDFLAGS ?= -static
+	endif
+	ifeq ($(TARGETENV), android)
+		GLDFLAGS = -static
+	endif
+	ifeq ($(TARGETENV), android_ndk_r6b)
+		GLDFLAGS = -Bdynamic -Wl,-dynamic-linker,/system/bin/linker
+		GLDFLAGS += -lm -lc -ldl
+		GLDFLAGS += -nostdlib
+		GLDFLAGS += -Wl,--gc-sections -Wl,-z,nocopyreloc
+		GLDFLAGS += -Wl,--no-undefined
+		ifeq ($(TARGETARCH), arm_android_ndk_r6b)
+			GLDFLAGS += -ldl
+			GLDFLAGS += -Wl,-T,$(TARGET_NDK)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/arm-linux-androideabi/lib/ldscripts/armelf_linux_eabi.x
+			GLDFLAGS += -Wl,-rpath-link=$(TARGET_NDK)/platforms/android-9/arch-arm
+			GLDFLAGS += -L$(TARGET_NDK)/platforms/android-9/arch-arm/usr/lib
+			GLDFLAGS += $(TARGET_NDK)/platforms/android-9/arch-arm/usr/lib/crtend_android.o
+			GLDFLAGS += $(TARGET_NDK)/platforms/android-9/arch-arm/usr/lib/crtbegin_dynamic.o
+			GLDFLAGS += $(TARGET_NDK)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.4.3/libgcc.a
+		else
+		ifeq ($(TARGETARCH), x86_android_ndk_r6b)
+			GLDFLAGS += -m32 -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now
+			GLDFLAGS += -Wl,-z,relro,-z,now -fPIE -pie
+			GLDFLAGS += -L$(TARGET_NDK)/platforms/android-9/arch-x86/usr/lib
+			GLDFLAGS += -Wl,-rpath-link=$(TARGET_NDK)/platforms/android-9/arch-x86
+			GLDFLAGS += -lstdc++
+			GLDFLAGS += $(TARGET_NDK)/platforms/android-9/arch-x86/usr/lib/crtbegin_dynamic.o
+			GLDFLAGS += -Wl,--whole-archive -Wl,--no-whole-archive
+			GLDFLAGS += $(TARGET_NDK)/toolchains/x86-4.4.3/prebuilt/linux-x86/lib/gcc/i686-android-linux/4.4.3/libgcc.a
+			GLDFLAGS += $(TARGET_NDK)/platforms/android-9/arch-x86/usr/lib/crtend_android.o
+		endif
+		endif
+	endif
+
+	GLDLIBS = -lgcc
+
+endif	# $(TARGETOS) == unix
+
+ifeq ($(TARGETOS), Windows_NT)
+
+	# The environment for windows builds
+
+	EXEEXT = .exe
+
+	ifeq ($(TARGETENV), win32)
+		# standard win32 using MS compiler
+		OBJEXT	= .obj
+		GCINCS	= $(strip /I$(SRCBASE)/include $(patsubst -I%,/I%,$(WLAN_StdIncPathA)) $(patsubst -I%,/I%,$(WLAN_ComponentIncPath)))
+		GCDEFS	= /DTARGETENV_$(TARGETENV) /DTARGETOS_$(TARGETOS) \
+			/DTARGETARCH_$(TARGETARCH) /D_X86_
+		ifeq ($(TARGETARCH), x86_mmx)
+			GCDEFS += /D_MMX_
+		endif
+		GCOPTS	= /nologo
+		GCFLAGS	= /GM /W3 /Z7
+
+		CC_TARGET	=-Fo$@
+		LINK_TARGET	=-out:$@
+
+		CC = cl
+		AS = cl
+		LD = cl
+
+		TCFLAGS =
+		GLDFLAGS = /nologo /link /nologo /INCREMENTAL:NO
+
+		GLDLIBS =
+	else
+		# cygwin32 based environment
+		OBJEXT	= .o
+		GCINCS	= $(strip -I$(SRCBASE)/include $(WLAN_StdIncPathA) $(WLAN_ComponentIncPath))
+		GCDEFS	= -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) \
+			-DTARGETARCH_$(TARGETARCH) -D_X86_
+		ifeq ($(TARGETARCH), x86_mmx)
+			GCDEFS += -D_MMX_
+		endif
+		GCOPTS	=
+		GCFLAGS	= -g -Wall
+
+		CC_TARGET	=-o $@
+		LINK_TARGET	=-o $@
+
+		CC = gcc
+		AS = gcc
+		LD = gcc
+		INSTALL = install -c
+
+		TCFLAGS =
+		GLDFLAGS =
+
+		GLDLIBS = -liberty -lgcc
+	endif
+
+	# Tools common to cygwin/win32
+
+	INSTALL = install -c
+	BUILD = build -ceZ
+
+	# RELEASE_TARGET is a the directory under RELEASE_DIR where
+	# target dependant files go. It is composed of the OS and
+	# the CPU, some examples are: winnt40/i386, win98 ...
+	#
+	# NEEDSWORK: For now only NT 4.0 stuff uses it.
+	ifneq ($(findstring $(TARGETPLATFORM), "Wdm wdm"), )
+		RELEASE_TARGET = wdm/i386
+	else
+		RELEASE_TARGET = winnt40/i386
+	endif
+
+	# RELEASE_TOOLS_DIR is a the directory under RELEASE_DIR where
+	# common tools go.
+	# For compatability with previous installs &test scripts, old
+	# tools still go in "yosemite".
+	RELEASE_YOS_DIR = yosemite
+	RELEASE_TOOLS_DIR = tools
+
+endif	# $(TARGETOS) == Windows_NT
+
+ifeq ($(TARGETOS), vxWorks)
+	WIND_REGISTRY = sol
+	ifndef WIND_BASE
+		ifeq ($(HOSTOS), unix)
+			WIND_BASE = /dfs/tools/vxWorks
+		else
+			WIND_BASE = $(WLAN_WINPFX)/tools/vxWorks
+		endif
+	endif
+	include $(WIND_BASE)/target/h/make/defs.default
+
+	ifeq ($(HOSTENV), Windows_NT)
+		WIND_HOST_TYPE = x86-win32
+	else
+		ifeq ($(HOSTENV), sun4)
+			WIND_HOST_TYPE = sun4-solaris2
+		else
+			WIND_HOST_TYPE = i386-freebsd
+		endif
+	endif
+
+	ifeq ($(TARGETENV), vxsim)
+		CPU = SIMSPARCSOLARIS
+	else
+		ifeq ($(TARGETENV), vx386)
+			CPU = i386
+		else
+			CPU = R4650
+			VXFLAGS  = -DCPU_VAR=$(CPU)
+		endif
+	endif
+
+	include $(WIND_BASE)/target/h/make/make.$(CPU)$(TOOL)
+	include $(WIND_BASE)/target/h/make/defs.$(WIND_HOST_TYPE)
+
+	GCINCS	= -I$(WIND_BASE)/target/h -I$(SRCBASE)/include $(WLAN_StdIncPathA)
+	GCDEFS	= $(DEFINE_CC) -DCPU=$(CPU) -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) -DTARGETARCH_$(TARGETARCH)
+	GCOPTS	= -g -O2
+	GCFLAGS	= -Wall $(CC_ARCH_SPEC)
+	LDFLAGS	= $(GLDFLAGS) $(LLDFLAGS)
+	GLDLIBS	= $(LIBS)
+
+	WIND_BIN = $(WIND_BASE)/host/$(WIND_HOST_TYPE)/bin
+
+	AR	:= $(WIND_BIN)/$(AR)
+	AS	:= $(WIND_BIN)/$(AS)
+	BINHEX	:= $(WIND_BIN)/$(BINHEX)
+	CC	:= $(WIND_BIN)/$(CC)
+	CF	:= $(WIND_BIN)/$(CF)
+	LD	:= $(CC)
+	NM	:= $(WIND_BIN)/$(NM)
+	RANLIB	:= $(WIND_BIN)/$(RANLIB)
+	BINXSYM_NAME := $(WIND_BIN)/$(BINXSYM)
+
+endif	# $(TARGETOS) == vxWorks
+
+ifeq ($(TARGETENV), nucleusarm)
+
+	# The environment for nucleus builds
+	ifeq ($(BSP_BASE_DIR),)
+		BSP_BASE_DIR := $(SRCBASE)/../bsp
+	endif
+   
+	ifeq ($(NUCLEUS_INC_DIR),)
+		NUCLEUS_INC_DIR := $(BSP_BASE_DIR)/rtos/nucleus/inc
+	endif
+
+	EXEEXT	:= 
+	OBJEXT	:= .o
+	GCINCS	:= $(strip -I$(SRCBASE)/include $(WLAN_StdIncPathA) -I$(NUCLEUS_INC_DIR) $(WLAN_ComponentIncPath))
+	GCDEFS	:= -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) -DTARGETARCH_$(TARGETARCH)
+	GCOPTS	:=
+   
+	ifeq ($(OBJDIR),)
+		OBJDIR	:= $(TARGETENV)/
+	endif
+   
+	# --md:  This option compiles the source and writes make file dependency lines 
+	#        to a file. The output file is suitable for use by a make utility.
+	# -c:    Compiles but does not perform the link phase.
+	# -O2:   High optimization.
+	# ---memaccess -UL41: This option tells the compiler that the memory in the 
+	#        target system has slightly restricted or expanded capabilities.
+	#        Disables unaligned mode for code that uses pre-ARMv6 unaligned 
+	#        access behavior.
+	# "/adsabi" is added to "--apcs /interwork/$(SWST)" so that objects created
+	#	under ADS 1.2 can be linked with objects compiled under RVCT 2.2.
+	# --diag_suppress 2084,1658 = blocks the diagnostic warning "Warning: C2084W: support for --apcs /adsabi is deprecated"
+	#                 1293: Suppress "assignment in condition" warning.
+	#                  550: Suppress "variable set but never used" warning.
+	GCFLAGS	:= --md \
+			-c \
+			-O2 \
+			--memaccess -UL41 \
+			--apcs /adsabi/interwork/NOSWST \
+			--diag_suppress 2084,1658,1293,550 \
+			--li
+
+	# --cpu 'name': This option generates code for a specific ARM processor or architecture.
+	ifeq ($(TARGETCPU),2153)
+		GCFLAGS += --cpu ARM1136J-S
+	else
+      $(error "Unknown target CPU type!")
+	endif
+
+	#CPPFLAGS	:= -embeddedcplusplus
+
+	CC_TARGET	=-o $@
+	CPP_TARGET	=-o $@
+	LINK_TARGET	=-o $@
+
+	CC := tcc
+	CPP := tcpp
+	AS := armasm
+	LD := armlink
+	AR := armar -c -r --create
+
+	INSTALL := install -c
+
+	TCFLAGS :=
+
+	GLDFLAGS := 
+	GLDLIBS := --ELF --symbols --debug --map --info sizes,totals --errors link.err --list link.map --verbose
+
+	# Convert windows style directories to cygwin style.
+	# It should be used in situations where the host environment is cygwin, and
+	# the host compiler is a native Win32 app (non-cygwin). It will convert the 
+	# Windows style directories in the dependencies list to cygwin style. This is
+	# necessary for the dependency files to be included by cygwin make.
+	ifeq ($(HOSTOS),Windows_NT)
+		FILTER_DEPENDS_IN_C_TO_OBJ_RULE := 1
+	endif
+
+endif	# $(TARGETENV) == nucleusarm
+
+ifeq	($(TARGETENV), bcmmips)
+
+	OBJEXT	= .o
+	GCINCS	= $(strip -I$(SRCBASE)/include $(WLAN_StdIncPathA) $(WLAN_ComponentIncPath))
+	GCDEFS	= -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) \
+		-DTARGETARCH_$(TARGETARCH) -D__mips__
+	GCOPTS	= -g -O2
+	GCFLAGS	= -Wall 
+	GLDFLAGS = -Wl,-tidt.dld
+
+	AS		= bcmas
+	CC		= bcmgcc
+	LD		= $(CC)
+	NM		= bcmnm
+	RANLIB		= bcmranlib
+
+endif	# $(TARGETENV) == bcmmips
+
+ifeq	($(TARGETENV), klsi)
+
+	OBJEXT	= .obj
+	GCINCS	= $(strip -I$(SRCBASE)/include $(WLAN_StdIncPathA) $(WLAN_ComponentIncPath))
+	GCDEFS	= -DTARGETENV_$(TARGETENV) -DTARGETOS_$(TARGETOS) \
+		-DTARGETARCH_$(TARGETARCH) -D__klsi__
+
+	AS		= qtasm
+	GASFLAGS	= -m20
+	CC		= qtcc
+	TCFLAGS		= -w asm=$(GASFLAGS) +c -Vcdv -w cc=+reginfo
+
+endif	# $(TARGETENV) == klsi
+
+CFLAGS = $(LCINCS) $(GCINCS) $(GCDEFS) $(GCOPTS) $(GCFLAGS) $(TCFLAGS) $(HCFLAGS) \
+$(LCDEFS) $(LCOPTS) $(LCFLAGS) $(CENV)
+
+ASFLAGS	= $(GASFLAGS) $(LASFLAGS) $(ASENV)
+LDFLAGS	= $(GLDFLAGS) $(LLDFLAGS) $(LDENV)
+LDLIBS	= $(LLDLIBS) $(GLDLIBS)
+
+# dependency files including the .d file itself.
+# note the example in GNU documentation seems to have a bug:
+# two backslashes where one is correct.
+%.d: %.c
+ifeq ($(findstring s, $(MAKEFLAGS) ),)
+	@ echo making $@
+endif
+	@ $(SHELL) -ec '$(CC) -MM $(CFLAGS) $(CPPFLAGS) $< \
+	| sed '\''s/$*\.o[ :]*/$@ &/g'\'' >$@'
+
+ifeq ($(TARGETENV), win32)
+
+# win32 needs different command line args 
+
+%.s: %.c
+	$(CC) /FAs $(CFLAGS) $(CPPFLAGS) /Fa$@ /c $<
+
+%.i: %.c
+	$(CC) /E $(CFLAGS) $(CPPFLAGS) $< > $@
+
+else # !win32
+
+%.s: %.c
+	$(CC) -S $(CFLAGS) $(CPPFLAGS) -o $@ $<
+
+%.i: %.c
+	$(CC) -o $@ -E -dD $(CFLAGS) $(CPPFLAGS) $<
+
+endif # win32
+
+ifeq	($(TARGETENV), klsi)
+
+%$(OBJEXT): %.c
+	$(CC) $(CFLAGS) $*.c
+
+%$(OBJEXT): %.asm
+	$(AS) $(ASFLAGS) $*.asm
+
+%.asm: %.c
+	$(CC) $(CFLAGS) -asm $*.c
+
+%.i: %.c
+	$(CC) $(CFLAGS) -cc -peep -asm $*.c
+	mv $*.pp $*.i
+
+else
+
+
+# This command sequence will:
+#  - Convert back-slashes to foward-slashes
+#  - Convert long filenames to 8.3 format (e.g. Program Files --> PROGRA~1)
+#  - Convert windows-style drive letters to cygwin style.
+#
+# It should be used in situations where the host environment is cygwin, and
+# the host compiler is a native Win32 app (non-cygwin). It will convert the 
+# Windows style directories in the dependencies list to cygwin style. This is
+# necessary for the dependency files to be included by cygwin make.
+define FILTER_DEPENDS
+	sed -e 's/\\/\//g'		\
+		-e 's/Program Files/PROGRA~1/g'	\
+		-e 's/\([A-Za-z]\):\//\/cygdrive\/\1\//' < $(notdir $(@:.o=.d)) > $(@:.o=.d) && \
+	rm -f $(notdir $(@:.o=.d))
+endef
+
+
+$(OBJDIR)%$(OBJEXT): %.c
+	$(CC) -c $(CFLAGS) $(CPPFLAGS) $(CC_TARGET) $<
+ifeq ($(FILTER_DEPENDS_IN_C_TO_OBJ_RULE),1)
+	${FILTER_DEPENDS}
+endif   
+
+$(OBJDIR)%$(OBJEXT): %.cpp
+	$(CPP) -c $(CFLAGS) $(CPPFLAGS) $(CPP_TARGET) $<
+ifeq ($(FILTER_DEPENDS_IN_C_TO_OBJ_RULE),1)
+	${FILTER_DEPENDS}
+endif   
+
+
+endif # klsi
+
+%.h: %.x
+	rpcgen -C -h $< > $@
+
+%_xdr.c: %.x
+	@ (if [ ! -f `basename $<` ] ; then ln -s $< . ; fi; true)
+	rpcgen -C -c -i 0 `basename $<` > $@
+
+# Makefile debugging rule
+env:
+	printenv
+
+# if the user mistakenly specified RELEASE_DIR in unix-style notation,
+# convert it to Win32 notation for them.
+#
+# RELEASE_DIR is assumed to be in windows-style notation if it has both 
+# backslashes ('\') and colons (':').
+#
+
+ifneq  ("$(subst \,,$(RELEASE_DIR))", "$(RELEASE_DIR)")
+ifneq  ("$(subst :,,$(RELEASE_DIR))", "$(RELEASE_DIR)")
+RELEASE_DIR := $(subst :,,$(RELEASE_DIR))
+RELEASE_DIR := $(subst \,/,$(RELEASE_DIR))
+RELEASE_DIR := //$(RELEASE_DIR)
+endif
+endif
+
+# all release rules depend on a valid RELEASE_DIR
+release: check_release_dir
+check_release_dir:
+	@if [ "x$(RELEASE_DIR)" = "x" ]; then \
+		echo "RELEASE_DIR is not set!"; \
+		exit 1; \
+	fi;
+
+include ${SRCBASE}/branding.inc
diff --git a/wl/src/Makerules.env b/wl/src/Makerules.env
new file mode 100644
index 0000000..22f9888
--- /dev/null
+++ b/wl/src/Makerules.env
@@ -0,0 +1,151 @@
+#*******************************************************************************
+#
+# Broadcom Proprietary and Confidential. Copyright (C) 2017,
+# All Rights Reserved.
+# 
+# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+# the contents of this file may not be disclosed to third parties, copied
+# or duplicated in any form, in whole or in part, without the prior
+# written permission of Broadcom.
+#
+#
+# <<Broadcom-WL-IPTag/Proprietary:>>
+#
+# $Id: Makerules.env 514727 2014-11-12 03:02:48Z $
+# Top-level Makerules for defining environment variables
+# can be included by anyone doing software at Epigram
+#*******************************************************************************
+
+# HOSTOS is either unix or Windows_NT.
+# HOSTENV differentiates HOSTOS and is either freebsd, sun4, or Windows_NT.
+# This refers to the *BUILD* environment. All environments use "GNU C" 
+# except Windows_NT which may use "GNU C" or "Microsoft C".
+
+ifndef	HOSTENV
+    # Figure what type of host we are in. 
+    UNAME = $(shell uname)
+
+    ifneq ($(findstring "$(UNAME)", "FreeBSD" "NetBSD"), )
+	HOSTENV = freebsd
+	HOSTOS = unix
+    else
+	ifneq ($(findstring "$(UNAME)", "sun4" "SunOS"), )
+	    HOSTENV = sun4
+	    HOSTOS = unix
+	else
+	    ifeq ($(UNAME), Linux)
+		HOSTENV = linux
+		HOSTOS = unix
+	    else
+		ifneq ($(findstring CYGWIN,$(UNAME)),)
+		    HOSTENV = Windows_NT
+		    HOSTOS = Windows_NT
+		else
+		    ifeq ($(UNAME), Darwin)
+			HOSTENV = macos
+			HOSTOS = unix
+		    else	
+		    	HOSTENV = unknown
+		    	HOSTOS = unknown
+		    endif
+		endif
+	    endif
+	endif
+    endif
+endif
+# In case we just defined them, make sure they are known
+export HOSTENV
+export HOSTOS
+	
+# TARGETENV is one of freebsd, sun4, linux, linuxarm, android, android_ndk_r6b, linuxmips, linuxmips_be, cygwin32, win32, or macos
+# TARGETENV defaults to HOSTENV unless HOSTENV is Windows_NT, in
+# which case it defaults to win32.
+
+ifndef	TARGETENV
+    ifeq ($(HOSTENV), Windows_NT)
+	TARGETENV = win32
+    else
+        TARGETENV = $(HOSTENV)
+    endif
+endif
+export TARGETENV
+
+# TARGETOS defaults to HOSTOS in most cases
+ifneq ($(findstring "$(TARGETENV)", "freebsd" "freebsd_be" "linux" "linuxarm" "linuxarm_le" "android" "android_ndk_r6b" "linuxmips" "linuxmips_be" "sun4" "cygwin32" "win32" "macos"), )
+    TARGETOS = $(HOSTOS)
+endif
+ifeq	($(TARGETENV), bcmmips)
+    TARGETOS = bcmmips
+endif
+ifeq	($(TARGETENV), klsi)
+    TARGETOS = klsi
+endif
+ifeq	($(TARGETENV), nucleusarm)
+    TARGETOS = nucleus
+endif
+ifndef TARGETOS
+    TARGETOS = unknown
+endif
+export TARGETOS
+
+# TARGETARCH is the target processor architecture
+# Currently valid values are: x86, x86_mmx, sparc, unknown, or a list of any
+# of the valid values.
+# For the x86* family, a generic x86 is assuemd if not otherwise specified
+# Order is important since "linux" matches both linuxmips and linux.
+ifndef TARGETARCH
+    ifneq ($(findstring "$(TARGETENV)", "android"), )
+	TARGETARCH = arm_android
+    endif
+
+    ifneq ($(findstring "$(TARGETENV)", "android_ndk_r6b"), )
+	TARGETARCH = arm_android_ndk_r6b
+    endif
+
+    ifneq ($(findstring "$(TARGETENV)", "linuxarm_le"), )
+	TARGETARCH = arm_le
+    endif
+    ifneq ($(findstring "$(TARGETENV)", "linuxarm nucleusarm"), )
+	TARGETARCH = arm
+    endif
+    ifneq ($(findstring "$(TARGETENV)", "bcmmips" "linuxmips" "linuxmips_be"), )
+	TARGETARCH = mips
+    endif
+    ifneq ($(findstring "$(TARGETENV)", "sun4"), )
+	TARGETARCH = sparc
+    endif
+    ifneq ($(findstring "$(TARGETENV)", "freebsd" "linux" "cygwin32" "win32"), )
+	TARGETCPU = $(shell uname -m)
+	ifneq ($(findstring "$(TARGETCPU)", "sparc" "sparc64"), )
+		TARGETARCH = $(TARGETCPU)
+	else
+		TARGETARCH = x86_mmx
+	endif
+    endif
+    ifeq	($(TARGETENV), macos)
+	TARGETCPU = $(shell uname -p)
+	ifneq ($(findstring "$(TARGETCPU)", "powerpc"), )
+		TARGETARCH = PPC
+	else
+		TARGETARCH = x86
+	endif
+    endif
+    ifeq	($(TARGETENV), klsi)
+	TARGETARCH = klsi
+    endif
+    ifndef TARGETARCH
+	TARGETARCH = unknown
+    endif
+endif
+export TARGETARCH
+
+# TARGET_TYPE is either "all" or one or more of: float64, float32, int16
+# default is int16.  "all" will get expanded into a list of all possible types
+ifndef  TARGET_TYPE
+	TARGET_TYPE = int16
+endif
+        
+ifeq ($(TARGET_TYPE), all)
+	TARGET_TYPE = int16 float32 float64
+endif
+export TARGET_TYPE
diff --git a/wl/src/bcmcrypto/sha256.c b/wl/src/bcmcrypto/sha256.c
new file mode 100644
index 0000000..c8024f5
--- /dev/null
+++ b/wl/src/bcmcrypto/sha256.c
@@ -0,0 +1,450 @@
+/* crypto/sha/sha256.c
+ * Code copied from openssl distribution and
+ * Modified just enough so that compiles and runs standalone
+ *
+ * Copyright (C) 2017, Broadcom. 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: sha256.c 523198 2014-12-29 04:39:42Z $
+ */
+/* ====================================================================
+ * Copyright (c) 2004 The OpenSSL Project.  All rights reserved
+ * according to the OpenSSL license [found in ../../LICENSE].
+ * ====================================================================
+ */
+#ifndef BCMDRIVER
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include <typedefs.h>
+#ifdef BCMDRIVER
+#include <osl.h>
+#else
+#include <string.h>
+#endif	/* BCMDRIVER */
+
+#include <bcmcrypto/sha256.h>
+
+const char *SHA256_version = "SHA-256";
+
+int SHA224_Init(SHA256_CTX *c)
+{
+	c->h[0] = 0xc1059ed8UL;	c->h[1] = 0x367cd507UL;
+	c->h[2] = 0x3070dd17UL;	c->h[3] = 0xf70e5939UL;
+	c->h[4] = 0xffc00b31UL;	c->h[5] = 0x68581511UL;
+	c->h[6] = 0x64f98fa7UL;	c->h[7] = 0xbefa4fa4UL;
+	c->Nl = 0;
+	c->Nh = 0;
+	c->num = 0;
+	c->md_len = SHA224_DIGEST_LENGTH;
+	return 1;
+}
+
+int
+SHA256_Init(SHA256_CTX *c)
+{
+	c->h[0] = 0x6a09e667UL;	c->h[1] = 0xbb67ae85UL;
+	c->h[2] = 0x3c6ef372UL;	c->h[3] = 0xa54ff53aUL;
+	c->h[4] = 0x510e527fUL;	c->h[5] = 0x9b05688cUL;
+	c->h[6] = 0x1f83d9abUL;	c->h[7] = 0x5be0cd19UL;
+	c->Nl = 0;
+	c->Nh = 0;
+	c->num = 0;
+	c->md_len = SHA256_DIGEST_LENGTH;
+	return 1;
+}
+
+unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md)
+{
+	SHA256_CTX c;
+	static unsigned char m[SHA224_DIGEST_LENGTH];
+
+	if (md == NULL)
+		md = m;
+
+	SHA224_Init(&c);
+	SHA256_Update(&c, d, n);
+	SHA256_Final(md, &c);
+
+	return (md);
+}
+
+unsigned char *SHA256(const unsigned char *key, size_t n, unsigned char *md)
+{
+	SHA256_CTX c;
+	static unsigned char m[SHA256_DIGEST_LENGTH];
+
+	if (md == NULL)
+		md = m;
+
+	SHA256_Init(&c);
+	SHA256_Update(&c, key, n);
+	SHA256_Final(md, &c);
+
+	return (md);
+}
+
+#ifndef	SHA_LONG_LOG2
+#define	SHA_LONG_LOG2	2	/* default to 32 bits */
+#endif
+
+#define	DATA_ORDER_IS_BIG_ENDIAN
+
+#define	HASH_LONG		SHA_LONG
+#define	HASH_LONG_LOG2		SHA_LONG_LOG2
+#define	HASH_CTX		SHA256_CTX
+#define	HASH_CBLOCK		SHA_CBLOCK
+#define	HASH_LBLOCK		SHA_LBLOCK
+
+/*
+ * Note that FIPS180-2 discusses "Truncation of the Hash Function Output."
+ * default: case below covers for it. It's not clear however if it's
+ * permitted to truncate to amount of bytes not divisible by 4. I bet not,
+ * but if it is, then default: case shall be extended. For reference.
+ * Idea behind separate cases for pre-defined lenghts is to let the
+ * compiler decide if it's appropriate to unroll small loops.
+ */
+#define	HASH_MAKE_STRING(c, s)	do {	\
+	unsigned long ll;		\
+	unsigned int  n;		\
+	switch ((c)->md_len)		\
+	{   case SHA224_DIGEST_LENGTH:	\
+		for (n = 0; n < SHA224_DIGEST_LENGTH/4; n++)	\
+		{   ll = (c)->h[n]; HOST_l2c(ll, (s));   }	\
+		break;			\
+	    case SHA256_DIGEST_LENGTH:	\
+		for (n = 0; n < SHA256_DIGEST_LENGTH/4; n++)	\
+		{   ll = (c)->h[n]; HOST_l2c(ll, (s));   }	\
+		break;			\
+	    default:			\
+		if ((c)->md_len > SHA256_DIGEST_LENGTH)	\
+		    return 0;				\
+		for (n = 0; n < (c)->md_len/4; n++)		\
+		{   ll = (c)->h[n]; HOST_l2c(ll, (s));   }	\
+		break;			\
+	}				\
+	} while (0)
+
+#define	HASH_UPDATE		SHA256_Update
+#define	HASH_TRANSFORM		SHA256_Transform
+#define	HASH_FINAL		SHA256_Final
+#define	HASH_BLOCK_HOST_ORDER	sha256_block_host_order
+#define	HASH_BLOCK_DATA_ORDER	sha256_block_data_order
+
+void sha256_block_host_order(SHA256_CTX *ctx, const void *in, size_t num);
+void sha256_block_data_order(SHA256_CTX *ctx, const void *in, size_t num);
+
+#include <bcmcrypto/md32_common.h>
+
+#ifdef SHA256_ASM
+void sha256_block(SHA256_CTX *ctx, const void *in, size_t num, int host);
+#else
+static const SHA_LONG K256[64] = {
+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL };
+
+/*
+ * FIPS specification refers to right rotations, while our ROTATE macro
+ * is left one. This is why you might notice that rotation coefficients
+ * differ from those observed in FIPS document by 32-N...
+ */
+#define Sigma0(x)	(ROTATE((x), 30) ^ ROTATE((x), 19) ^ ROTATE((x), 10))
+#define Sigma1(x)	(ROTATE((x), 26) ^ ROTATE((x), 21) ^ ROTATE((x), 7))
+#define sigma0(x)	(ROTATE((x), 25) ^ ROTATE((x), 14) ^ ((x)>>3))
+#define sigma1(x)	(ROTATE((x), 15) ^ ROTATE((x), 13) ^ ((x)>>10))
+
+#define Ch(x, y, z)	(((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x, y, z)	(((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+#ifdef OPENSSL_SMALL_FOOTPRINT
+
+static void
+sha256_block(SHA256_CTX *ctx, const void *in, size_t num, int host)
+{
+	unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1, T2;
+	SHA_LONG	X[16];
+	int i;
+	const unsigned char *data = in;
+
+	while (num--) {
+
+		a = ctx->h[0];	b = ctx->h[1];	c = ctx->h[2];	d = ctx->h[3];
+		e = ctx->h[4];	f = ctx->h[5];	g = ctx->h[6];	h = ctx->h[7];
+
+		if (host) {
+			const SHA_LONG *W = (const SHA_LONG *)data;
+
+			for (i = 0; i < 16; i++)
+			{
+				T1 = X[i] = W[i];
+				T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i];
+				T2 = Sigma0(a) + Maj(a, b, c);
+				h = g;	g = f;	f = e;	e = d + T1;
+				d = c;	c = b;	b = a;	a = T1 + T2;
+			}
+
+			data += SHA256_CBLOCK;
+		} else {
+			SHA_LONG l;
+
+			for (i = 0; i < 16; i++) {
+				HOST_c2l(data, l); T1 = X[i] = l;
+				T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i];
+				T2 = Sigma0(a) + Maj(a, b, c);
+				h = g;	g = f;	f = e;	e = d + T1;
+				d = c;	c = b;	b = a;	a = T1 + T2;
+			}
+		}
+
+		for (; i < 64; i++) {
+			s0 = X[(i+1)&0x0f];	s0 = sigma0(s0);
+			s1 = X[(i+14)&0x0f];	s1 = sigma1(s1);
+
+			T1 = X[i&0xf] += s0 + s1 + X[(i+9)&0xf];
+			T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i];
+			T2 = Sigma0(a) + Maj(a, b, c);
+			h = g;	g = f;	f = e;	e = d + T1;
+			d = c;	c = b;	b = a;	a = T1 + T2;
+		}
+
+		ctx->h[0] += a;	ctx->h[1] += b;	ctx->h[2] += c;	ctx->h[3] += d;
+		ctx->h[4] += e;	ctx->h[5] += f;	ctx->h[6] += g;	ctx->h[7] += h;
+
+	}
+}
+
+#else
+
+#define	ROUND_00_15(i, a, b, c, d, e, f, g, h)		do {	\
+	T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i];	\
+	h = Sigma0(a) + Maj(a, b, c);			\
+	d += T1;	h += T1;		} while (0)
+
+#define	ROUND_16_63(i, a, b, c, d, e, f, g, h, X)	do {	\
+	s0 = X[(i+1)&0x0f];	s0 = sigma0(s0);	\
+	s1 = X[(i+14)&0x0f];	s1 = sigma1(s1);	\
+	T1 = X[(i)&0x0f] += s0 + s1 + X[(i+9)&0x0f];	\
+	ROUND_00_15(i, a, b, c, d, e, f, g, h);		} while (0)
+
+static void
+sha256_block(SHA256_CTX *ctx, const void *in, size_t num, int host)
+{
+	unsigned MD32_REG_T a, b, c, d, e, f, g, h, s0, s1, T1;
+	SHA_LONG	X[16];
+	int i;
+	const unsigned char *data = in;
+
+	while (num--) {
+
+		a = ctx->h[0];	b = ctx->h[1];	c = ctx->h[2];	d = ctx->h[3];
+		e = ctx->h[4];	f = ctx->h[5];	g = ctx->h[6];	h = ctx->h[7];
+
+		if (host) {
+			const SHA_LONG *W = (const SHA_LONG *)data;
+
+			T1 = X[0] = W[0];	ROUND_00_15(0, a, b, c, d, e, f, g, h);
+			T1 = X[1] = W[1];	ROUND_00_15(1, h, a, b, c, d, e, f, g);
+			T1 = X[2] = W[2];	ROUND_00_15(2, g, h, a, b, c, d, e, f);
+			T1 = X[3] = W[3];	ROUND_00_15(3, f, g, h, a, b, c, d, e);
+			T1 = X[4] = W[4];	ROUND_00_15(4, e, f, g, h, a, b, c, d);
+			T1 = X[5] = W[5];	ROUND_00_15(5, d, e, f, g, h, a, b, c);
+			T1 = X[6] = W[6];	ROUND_00_15(6, c, d, e, f, g, h, a, b);
+			T1 = X[7] = W[7];	ROUND_00_15(7, b, c, d, e, f, g, h, a);
+			T1 = X[8] = W[8];	ROUND_00_15(8, a, b, c, d, e, f, g, h);
+			T1 = X[9] = W[9];	ROUND_00_15(9, h, a, b, c, d, e, f, g);
+			T1 = X[10] = W[10];	ROUND_00_15(10, g, h, a, b, c, d, e, f);
+			T1 = X[11] = W[11];	ROUND_00_15(11, f, g, h, a, b, c, d, e);
+			T1 = X[12] = W[12];	ROUND_00_15(12, e, f, g, h, a, b, c, d);
+			T1 = X[13] = W[13];	ROUND_00_15(13, d, e, f, g, h, a, b, c);
+			T1 = X[14] = W[14];	ROUND_00_15(14, c, d, e, f, g, h, a, b);
+			T1 = X[15] = W[15];	ROUND_00_15(15, b, c, d, e, f, g, h, a);
+
+			data += SHA256_CBLOCK;
+		} else {
+			SHA_LONG l;
+
+			HOST_c2l(data, l); T1 = X[0] = l;  ROUND_00_15(0, a, b, c, d, e, f, g, h);
+			HOST_c2l(data, l); T1 = X[1] = l;  ROUND_00_15(1, h, a, b, c, d, e, f, g);
+			HOST_c2l(data, l); T1 = X[2] = l;  ROUND_00_15(2, g, h, a, b, c, d, e, f);
+			HOST_c2l(data, l); T1 = X[3] = l;  ROUND_00_15(3, f, g, h, a, b, c, d, e);
+			HOST_c2l(data, l); T1 = X[4] = l;  ROUND_00_15(4, e, f, g, h, a, b, c, d);
+			HOST_c2l(data, l); T1 = X[5] = l;  ROUND_00_15(5, d, e, f, g, h, a, b, c);
+			HOST_c2l(data, l); T1 = X[6] = l;  ROUND_00_15(6, c, d, e, f, g, h, a, b);
+			HOST_c2l(data, l); T1 = X[7] = l;  ROUND_00_15(7, b, c, d, e, f, g, h, a);
+			HOST_c2l(data, l); T1 = X[8] = l;  ROUND_00_15(8, a, b, c, d, e, f, g, h);
+			HOST_c2l(data, l); T1 = X[9] = l;  ROUND_00_15(9, h, a, b, c, d, e, f, g);
+			HOST_c2l(data, l); T1 = X[10] = l; ROUND_00_15(10, g, h, a, b, c, d, e, f);
+			HOST_c2l(data, l); T1 = X[11] = l; ROUND_00_15(11, f, g, h, a, b, c, d, e);
+			HOST_c2l(data, l); T1 = X[12] = l; ROUND_00_15(12, e, f, g, h, a, b, c, d);
+			HOST_c2l(data, l); T1 = X[13] = l; ROUND_00_15(13, d, e, f, g, h, a, b, c);
+			HOST_c2l(data, l); T1 = X[14] = l; ROUND_00_15(14, c, d, e, f, g, h, a, b);
+			HOST_c2l(data, l); T1 = X[15] = l; ROUND_00_15(15, b, c, d, e, f, g, h, a);
+		}
+
+		for (i = 16; i < 64; i += 8) {
+			ROUND_16_63(i+0, a, b, c, d, e, f, g, h, X);
+			ROUND_16_63(i+1, h, a, b, c, d, e, f, g, X);
+			ROUND_16_63(i+2, g, h, a, b, c, d, e, f, X);
+			ROUND_16_63(i+3, f, g, h, a, b, c, d, e, X);
+			ROUND_16_63(i+4, e, f, g, h, a, b, c, d, X);
+			ROUND_16_63(i+5, d, e, f, g, h, a, b, c, X);
+			ROUND_16_63(i+6, c, d, e, f, g, h, a, b, X);
+			ROUND_16_63(i+7, b, c, d, e, f, g, h, a, X);
+		}
+
+		ctx->h[0] += a;	ctx->h[1] += b;	ctx->h[2] += c;	ctx->h[3] += d;
+		ctx->h[4] += e;	ctx->h[5] += f;	ctx->h[6] += g;	ctx->h[7] += h;
+	}
+}
+
+#endif /* OPENSSL_SMALL_FOOTPRINT */
+#endif /* SHA256_ASM */
+
+/*
+ * Idea is to trade couple of cycles for some space. On IA-32 we save
+ * about 4K in "big footprint" case. In "small footprint" case any gain
+ * is appreciated:-)
+ */
+void
+HASH_BLOCK_HOST_ORDER(SHA256_CTX *ctx, const void *in, size_t num)
+{
+	sha256_block(ctx, in, num, 1);
+}
+
+void
+HASH_BLOCK_DATA_ORDER(SHA256_CTX *ctx, const void *in, size_t num)
+{
+	sha256_block(ctx, in, num, 0);
+}
+
+
+#ifdef BCMSHA256_TEST
+/*
+ *  sha1test.c
+ *
+ *  Description:
+ *      This file will exercise the SHA-256 code performing the three
+ *      tests documented in FIPS PUB 180-2 plus one which calls
+ *      SHA1Input with an exact multiple of 512 bits, plus a few
+ *      error test checks.
+ *
+ *  Portability Issues:
+ *      None.
+ *
+ */
+
+#include <stdio.h>
+
+/*
+ *  Define patterns for testing
+ */
+#define TEST1   "abc"
+#define TEST2a  "abcdbcdecdefdefgefghfghighijhi"
+#define TEST2b  "jkijkljklmklmnlmnomnopnopq"
+#define TEST2   TEST2a TEST2b
+#define TEST3   "a"
+
+char *testarray[3] = {
+	TEST1,
+	TEST2,
+	TEST3
+};
+
+
+int repeatcount[3] = { 1, 1, 1000000};
+unsigned char resultarray[3][32] =
+{
+	{0xba, 0x78, 0x16, 0xbf,  0x8f, 0x01, 0xcf, 0xea,
+	 0x41, 0x41, 0x40, 0xde,  0x5d, 0xae, 0x22, 0x23,
+	 0xb0, 0x03, 0x61, 0xa3,  0x96, 0x17, 0x7a, 0x9c,
+	 0xb4, 0x10, 0xff, 0x61,  0xf2, 0x00, 0x15, 0xad},
+
+	{0x24, 0x8d, 0x6a, 0x61,  0xd2, 0x06, 0x38, 0xb8,
+	 0xe5, 0xc0, 0x26, 0x93,  0x0c, 0x3e, 0x60, 0x39,
+	 0xa3, 0x3c, 0xe4, 0x59,  0x64, 0xff, 0x21, 0x67,
+	 0xf6, 0xec, 0xed, 0xd4,  0x19, 0xdb, 0x06, 0xc1},
+
+	{0xcd, 0xc7, 0x6e, 0x5c,  0x99, 0x14, 0xfb, 0x92,
+	 0x81, 0xa1, 0xc7, 0xe2,  0x84, 0xd7, 0x3e, 0x67,
+	 0xf1, 0x80, 0x9a, 0x48,  0xa4, 0x97, 0x20, 0x0e,
+	 0x04, 0x6d, 0x39, 0xcc,  0xc7, 0x11, 0x2c, 0xd0}
+};
+
+int
+main()
+{
+	SHA256_CTX sha;
+	int i, j, err, fail = 0;
+	unsigned char Message_Digest[32];
+
+	/*
+	 *  Perform SHA-1 tests
+	 */
+	for (j = 0; j < 3; ++j) {
+		printf("\nTest %d: %d, '%s'\n", j + 1, repeatcount[j], testarray[j]);
+
+		err = SHA256_Init(&sha);
+
+		for (i = 0; i < repeatcount[j]; ++i) {
+			err = SHA256_Update(&sha,
+			                    (const unsigned char *) testarray[j],
+			                    strlen(testarray[j]));
+		}
+
+		err = SHA256_Final(Message_Digest, &sha);
+		printf("\t");
+		for (i = 0; i < 32; ++i) {
+			printf("%02X ", Message_Digest[i]);
+		}
+		printf("\n");
+		printf("Should match:\n");
+		printf("\t");
+		for (i = 0; i < 32; ++i) {
+			printf("%02X ", resultarray[j][i]);
+		}
+		printf("\n");
+		if (memcmp(Message_Digest, resultarray[j], 32)) fail++;
+	}
+#ifdef EXTRA_SHA256_TEST
+	/* Test some error returns */
+	err = SHA1Input(&sha, (const unsigned char *) testarray[1], 1);
+	printf("\nError %d. Should be %d.\n", err, shaStateError);
+	if (err != shaStateError) fail++;
+
+	err = SHA1Reset(0);
+	printf("\nError %d. Should be %d.\n", err, shaNull);
+	if (err != shaNull) fail++;
+#endif
+	printf("SHA1 test %s\n", fail? "FAILED" : "PASSED");
+	return fail;
+}
+#endif /* BCMSHA1_TEST */
diff --git a/wl/src/branding.inc b/wl/src/branding.inc
new file mode 100644
index 0000000..021c204
--- /dev/null
+++ b/wl/src/branding.inc
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2017, Broadcom. 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:>>
+#  
+BRAND=
+
+export RELAY_FILE_BASE=bcm42rly
diff --git a/wl/src/include/bcm_cfg.h b/wl/src/include/bcm_cfg.h
new file mode 100644
index 0000000..8969980
--- /dev/null
+++ b/wl/src/include/bcm_cfg.h
@@ -0,0 +1,26 @@
+/*
+ * BCM common config options
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcm_cfg.h 514727 2014-11-12 03:02:48Z $
+ */
+
+#ifndef _bcm_cfg_h_
+#define _bcm_cfg_h_
+#endif /* _bcm_cfg_h_ */
diff --git a/wl/src/include/bcm_mpool_pub.h b/wl/src/include/bcm_mpool_pub.h
new file mode 100644
index 0000000..76f087b
--- /dev/null
+++ b/wl/src/include/bcm_mpool_pub.h
@@ -0,0 +1,358 @@
+/*
+ * Memory pools library, Public interface
+ *
+ * API Overview
+ *
+ * This package provides a memory allocation subsystem based on pools of
+ * homogenous objects.
+ *
+ * Instrumentation is available for reporting memory utilization both
+ * on a per-data-structure basis and system wide.
+ *
+ * There are two main types defined in this API.
+ *
+ *    pool manager: A singleton object that acts as a factory for
+ *                  pool allocators. It also is used for global
+ *                  instrumentation, such as reporting all blocks
+ *                  in use across all data structures. The pool manager
+ *                  creates and provides individual memory pools
+ *                  upon request to application code.
+ *
+ *    memory pool:  An object for allocating homogenous memory blocks.
+ *
+ * Global identifiers in this module use the following prefixes:
+ *    bcm_mpm_*     Memory pool manager
+ *    bcm_mp_*      Memory pool
+ *
+ * There are two main types of memory pools:
+ *
+ *    prealloc: The contiguous memory block of objects can either be supplied
+ *              by the client or malloc'ed by the memory manager. The objects are
+ *              allocated out of a block of memory and freed back to the block.
+ *
+ *    heap:     The memory pool allocator uses the heap (malloc/free) for memory.
+ *              In this case, the pool allocator is just providing statistics
+ *              and instrumentation on top of the heap, without modifying the heap
+ *              allocation implementation.
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcm_mpool_pub.h 535090 2015-02-17 04:49:01Z $
+ */
+
+#ifndef _BCM_MPOOL_PUB_H
+#define _BCM_MPOOL_PUB_H 1
+
+#include <typedefs.h> /* needed for uint16 */
+
+
+/*
+**************************************************************************
+*
+* Type definitions, handles
+*
+**************************************************************************
+*/
+
+/* Forward declaration of OSL handle. */
+struct osl_info;
+
+/* Forward declaration of string buffer. */
+struct bcmstrbuf;
+
+/*
+ * Opaque type definition for the pool manager handle. This object is used for global
+ * memory pool operations such as obtaining a new pool, deleting a pool, iterating and
+ * instrumentation/debugging.
+ */
+struct bcm_mpm_mgr;
+typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h;
+
+/*
+ * Opaque type definition for an instance of a pool. This handle is used for allocating
+ * and freeing memory through the pool, as well as management/instrumentation on this
+ * specific pool.
+ */
+struct bcm_mp_pool;
+typedef struct bcm_mp_pool *bcm_mp_pool_h;
+
+
+/*
+ * To make instrumentation more readable, every memory
+ * pool must have a readable name. Pool names are up to
+ * 8 bytes including '\0' termination. (7 printable characters.)
+ */
+#define BCM_MP_NAMELEN 8
+
+
+/*
+ * Type definition for pool statistics.
+ */
+typedef struct bcm_mp_stats {
+	char name[BCM_MP_NAMELEN];  /* Name of this pool. */
+	unsigned int objsz;         /* Object size allocated in this pool */
+	uint16 nobj;                /* Total number of objects in this pool */
+	uint16 num_alloc;           /* Number of objects currently allocated */
+	uint16 high_water;          /* Max number of allocated objects. */
+	uint16 failed_alloc;        /* Failed allocations. */
+} bcm_mp_stats_t;
+
+
+/*
+**************************************************************************
+*
+* API Routines on the pool manager.
+*
+**************************************************************************
+*/
+
+/*
+ * bcm_mpm_init() - initialize the whole memory pool system.
+ *
+ * Parameters:
+ *    osh:       INPUT  Operating system handle. Needed for heap memory allocation.
+ *    max_pools: INPUT Maximum number of mempools supported.
+ *    mgr:       OUTPUT The handle is written with the new pools manager object/handle.
+ *
+ * Returns:
+ *    BCME_OK     Object initialized successfully. May be used.
+ *    BCME_NOMEM  Initialization failed due to no memory. Object must not be used.
+ */
+int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp);
+
+
+/*
+ * bcm_mpm_deinit() - de-initialize the whole memory pool system.
+ *
+ * Parameters:
+ *    mgr:     INPUT  Pointer to pool manager handle.
+ *
+ * Returns:
+ *    BCME_OK  Memory pool manager successfully de-initialized.
+ *    other    Indicated error occured during de-initialization.
+ */
+int bcm_mpm_deinit(bcm_mpm_mgr_h *mgrp);
+
+/*
+ * bcm_mpm_create_prealloc_pool() - Create a new pool for fixed size objects. The
+ *                                  pool uses a contiguous block of pre-alloced
+ *                                  memory. The memory block may either be provided
+ *                                  by the client or dynamically allocated by the
+ *                                  pool manager.
+ *
+ * Parameters:
+ *    mgr:      INPUT  The handle to the pool manager
+ *    obj_sz:   INPUT  Size of objects that will be allocated by the new pool
+ *                     Must be >= sizeof(void *).
+ *    nobj:     INPUT  Maximum number of concurrently existing objects to support
+ *    memstart  INPUT  Pointer to the memory to use, or NULL to malloc()
+ *    memsize   INPUT  Number of bytes referenced from memstart (for error checking).
+ *                     Must be 0 if 'memstart' is NULL.
+ *    poolname  INPUT  For instrumentation, the name of the pool
+ *    newp:     OUTPUT The handle for the new pool, if creation is successful
+ *
+ * Returns:
+ *    BCME_OK   Pool created ok.
+ *    other     Pool not created due to indicated error. newpoolp set to NULL.
+ *
+ *
+ */
+int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr,
+                                 unsigned int obj_sz,
+                                 int nobj,
+                                 void *memstart,
+                                 unsigned int memsize,
+                                 const char poolname[BCM_MP_NAMELEN],
+                                 bcm_mp_pool_h *newp);
+
+
+/*
+ * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after
+ *                                  all memory objects have been freed back to the pool.
+ *
+ * Parameters:
+ *    mgr:     INPUT The handle to the pools manager
+ *    pool:    INPUT The handle of the  pool to delete
+ *
+ * Returns:
+ *    BCME_OK   Pool deleted ok.
+ *    other     Pool not deleted due to indicated error.
+ *
+ */
+int bcm_mpm_delete_prealloc_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp);
+
+/*
+ * bcm_mpm_create_heap_pool() - Create a new pool for fixed size objects. The memory
+ *                              pool allocator uses the heap (malloc/free) for memory.
+ *                              In this case, the pool allocator is just providing
+ *                              statistics and instrumentation on top of the heap,
+ *                              without modifying the heap allocation implementation.
+ *
+ * Parameters:
+ *    mgr:      INPUT  The handle to the pool manager
+ *    obj_sz:   INPUT  Size of objects that will be allocated by the new pool
+ *    poolname  INPUT  For instrumentation, the name of the pool
+ *    newp:     OUTPUT The handle for the new pool, if creation is successful
+ *
+ * Returns:
+ *    BCME_OK   Pool created ok.
+ *    other     Pool not created due to indicated error. newpoolp set to NULL.
+ *
+ *
+ */
+int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz,
+                             const char poolname[BCM_MP_NAMELEN],
+                             bcm_mp_pool_h *newp);
+
+
+/*
+ * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after
+ *                              all memory objects have been freed back to the pool.
+ *
+ * Parameters:
+ *    mgr:     INPUT The handle to the pools manager
+ *    pool:    INPUT The handle of the  pool to delete
+ *
+ * Returns:
+ *    BCME_OK   Pool deleted ok.
+ *    other     Pool not deleted due to indicated error.
+ *
+ */
+int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp);
+
+
+/*
+ * bcm_mpm_stats() - Return stats for all pools
+ *
+ * Parameters:
+ *    mgr:         INPUT   The handle to the pools manager
+ *    stats:       OUTPUT  Array of pool statistics.
+ *    nentries:    MOD     Max elements in 'stats' array on INPUT. Actual number
+ *                         of array elements copied to 'stats' on OUTPUT.
+ *
+ * Returns:
+ *    BCME_OK   Ok
+ *    other     Error getting stats.
+ *
+ */
+int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries);
+
+
+/*
+ * bcm_mpm_dump() - Display statistics on all pools
+ *
+ * Parameters:
+ *    mgr:     INPUT  The handle to the pools manager
+ *    b:       OUTPUT Output buffer.
+ *
+ * Returns:
+ *    BCME_OK   Ok
+ *    other     Error during dump.
+ *
+ */
+int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b);
+
+
+/*
+ * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to
+ *                          compensate for alignment requirements of the objects.
+ *                          This function provides the padded object size. If clients
+ *                          pre-allocate a memory slab for a memory pool, the
+ *                          padded object size should be used by the client to allocate
+ *                          the memory slab (in order to provide sufficent space for
+ *                          the maximum number of objects).
+ *
+ * Parameters:
+ *    mgr:            INPUT   The handle to the pools manager.
+ *    obj_sz:         INPUT   Input object size.
+ *    padded_obj_sz:  OUTPUT  Padded object size.
+ *
+ * Returns:
+ *    BCME_OK      Ok
+ *    BCME_BADARG  Bad arguments.
+ *
+ */
+int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz);
+
+
+/*
+***************************************************************************
+*
+* API Routines on a specific pool.
+*
+***************************************************************************
+*/
+
+
+/*
+ * bcm_mp_alloc() - Allocate a memory pool object.
+ *
+ * Parameters:
+ *    pool:    INPUT    The handle to the pool.
+ *
+ * Returns:
+ *    A pointer to the new object. NULL on error.
+ *
+ */
+void* bcm_mp_alloc(bcm_mp_pool_h pool);
+
+/*
+ * bcm_mp_free() - Free a memory pool object.
+ *
+ * Parameters:
+ *    pool:  INPUT   The handle to the pool.
+ *    objp:  INPUT   A pointer to the object to free.
+ *
+ * Returns:
+ *    BCME_OK   Ok
+ *    other     Error during free.
+ *
+ */
+int bcm_mp_free(bcm_mp_pool_h pool, void *objp);
+
+/*
+ * bcm_mp_stats() - Return stats for this pool
+ *
+ * Parameters:
+ *    pool:     INPUT    The handle to the pool
+ *    stats:    OUTPUT   Pool statistics
+ *
+ * Returns:
+ *    BCME_OK   Ok
+ *    other     Error getting statistics.
+ *
+ */
+void bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats);
+
+
+/*
+ * bcm_mp_dump() - Dump a pool
+ *
+ * Parameters:
+ *    pool:    INPUT    The handle to the pool
+ *    b        OUTPUT   Output buffer
+ *
+ * Returns:
+ *    BCME_OK   Ok
+ *    other     Error during dump.
+ *
+ */
+int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b);
+
+
+#endif /* _BCM_MPOOL_PUB_H */
diff --git a/wl/src/include/bcmbloom.h b/wl/src/include/bcmbloom.h
new file mode 100644
index 0000000..59c6273
--- /dev/null
+++ b/wl/src/include/bcmbloom.h
@@ -0,0 +1,66 @@
+/*
+ * Bloom filter support
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: bcmbloom.h 525587 2015-01-10 05:24:58Z $
+ */
+
+#ifndef _bcmbloom_h_
+#define _bcmbloom_h_
+
+#include <typedefs.h>
+#ifdef BCMDRIVER
+#include <osl.h>
+#else
+#include <stddef.h>  /* For size_t */
+#endif
+
+struct bcm_bloom_filter;
+typedef struct bcm_bloom_filter bcm_bloom_filter_t;
+
+typedef void* (*bcm_bloom_alloc_t)(void *ctx, uint size);
+typedef void (*bcm_bloom_free_t)(void *ctx, void *buf, uint size);
+typedef uint (*bcm_bloom_hash_t)(void* ctx, uint idx, const uint8 *tag, uint len);
+
+/* create/allocate a bloom filter. filter size can be 0 for validate only filters */
+int bcm_bloom_create(bcm_bloom_alloc_t alloc_cb,
+	bcm_bloom_free_t free_cb, void *callback_ctx, uint max_hash,
+	uint filter_size /* bytes */, bcm_bloom_filter_t **bloom);
+
+/* destroy bloom filter */
+int bcm_bloom_destroy(bcm_bloom_filter_t **bloom, bcm_bloom_free_t free_cb);
+
+/* add a hash function to filter, return an index */
+int bcm_bloom_add_hash(bcm_bloom_filter_t *filter, bcm_bloom_hash_t hash, uint *idx);
+
+/* remove the hash function at index from filter */
+int bcm_bloom_remove_hash(bcm_bloom_filter_t *filter, uint idx);
+
+/* check if given tag is member of the filter. If buf is NULL and/or buf_len is 0
+ * then use the internal state. BCME_OK if member, BCME_NOTFOUND if not,
+ * or other error (e.g. BADARG)
+ */
+bool bcm_bloom_is_member(bcm_bloom_filter_t *filter,
+	const uint8 *tag, uint tag_len, const uint8 *buf, uint buf_len);
+
+/* add a member to the filter. invalid for validate_only filters */
+int bcm_bloom_add_member(bcm_bloom_filter_t *filter, const uint8 *tag, uint tag_len);
+
+/* no support for remove member */
+
+/* get the filter data from state. BCME_BUFTOOSHORT w/ required length in buf_len
+ * if supplied size is insufficient
+ */
+int bcm_bloom_get_filter_data(bcm_bloom_filter_t *filter,
+	uint buf_size, uint8 *buf, uint *buf_len);
+
+#endif /* _bcmbloom_h_ */
diff --git a/wl/src/include/bcmcdc.h b/wl/src/include/bcmcdc.h
new file mode 100644
index 0000000..7343726
--- /dev/null
+++ b/wl/src/include/bcmcdc.h
@@ -0,0 +1,130 @@
+/*
+ * CDC network driver ioctl/indication encoding
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmcdc.h 633551 2016-04-22 22:51:06Z $
+ */
+#ifndef _bcmcdc_h_
+#define	_bcmcdc_h_
+#include <proto/ethernet.h>
+
+typedef struct cdc_ioctl {
+	uint32 cmd;      /* ioctl command value */
+	uint32 len;      /* lower 16: output buflen; upper 16: input buflen (excludes header) */
+	uint32 flags;    /* flag defns given below */
+	uint32 status;   /* status code returned from the device */
+} cdc_ioctl_t;
+
+/* Max valid buffer size that can be sent to the dongle */
+#define CDC_MAX_MSG_SIZE   ETHER_MAX_LEN
+
+/* len field is divided into input and output buffer lengths */
+#define CDCL_IOC_OUTLEN_MASK   0x0000FFFF  /* maximum or expected response length, */
+					   /* excluding IOCTL header */
+#define CDCL_IOC_OUTLEN_SHIFT  0
+#define CDCL_IOC_INLEN_MASK    0xFFFF0000   /* input buffer length, excluding IOCTL header */
+#define CDCL_IOC_INLEN_SHIFT   16
+
+/* CDC flag definitions */
+#define CDCF_IOC_ERROR		0x01	/* 0=success, 1=ioctl cmd failed */
+#define CDCF_IOC_SET		0x02	/* 0=get, 1=set cmd */
+#define CDCF_IOC_OVL_IDX_MASK	0x3c	/* overlay region index mask */
+#define CDCF_IOC_OVL_RSV	0x40	/* 1=reserve this overlay region */
+#define CDCF_IOC_OVL		0x80	/* 1=this ioctl corresponds to an overlay */
+#define CDCF_IOC_ACTION_MASK	0xfe	/* SET/GET, OVL_IDX, OVL_RSV, OVL mask */
+#define CDCF_IOC_ACTION_SHIFT	1	/* SET/GET, OVL_IDX, OVL_RSV, OVL shift */
+#define CDCF_IOC_IF_MASK	0xF000	/* I/F index */
+#define CDCF_IOC_IF_SHIFT	12
+#define CDCF_IOC_ID_MASK	0xFFFF0000	/* used to uniquely id an ioctl req/resp pairing */
+#define CDCF_IOC_ID_SHIFT	16		/* # of bits of shift for ID Mask */
+
+#define CDC_IOC_IF_IDX(flags)	(((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
+#define CDC_IOC_ID(flags)	(((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
+
+#define CDC_GET_IF_IDX(hdr) \
+	((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT))
+#define CDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT)))
+
+/*
+ * BDC header
+ *
+ *   The BDC header is used on data packets to convey priority across USB.
+ */
+
+struct bdc_header {
+	uint8	flags;			/* Flags */
+	uint8	priority;		/* 802.1d Priority 0:2 bits, 4:7 USB flow control info */
+	uint8	flags2;
+	uint8	dataOffset;		/* Offset from end of BDC header to packet data, in
+					 * 4-byte words.  Leaves room for optional headers.
+					 */
+};
+
+#define	BDC_HEADER_LEN		4
+
+/* flags field bitmap */
+#define BDC_FLAG_EXEMPT		0x03	/* EXT_STA: encryption exemption (host -> dongle?) */
+#define BDC_FLAG_80211_PKT	0x01	/* Packet is in 802.11 format (dongle -> host) */
+#define BDC_FLAG_SUM_GOOD	0x04	/* Dongle has verified good RX checksums */
+#define BDC_FLAG_SUM_NEEDED	0x08	/* Dongle needs to do TX checksums: host->device */
+#define BDC_FLAG_EVENT_MSG	0x08	/* Payload contains an event msg: device->host */
+#define BDC_FLAG_VER_MASK	0xf0	/* Protocol version mask */
+#define BDC_FLAG_VER_SHIFT	4	/* Protocol version shift */
+
+/* priority field bitmap */
+#define BDC_PRIORITY_MASK	0x07
+#define BDC_PRIORITY_FC_MASK	0xf0	/* flow control info mask */
+#define BDC_PRIORITY_FC_SHIFT	4	/* flow control info shift */
+
+/* flags2 field bitmap */
+#define BDC_FLAG2_IF_MASK	0x0f	/* interface index (host <-> dongle) */
+#define BDC_FLAG2_IF_SHIFT	0
+#define BDC_FLAG2_FC_FLAG	0x10	/* flag to indicate if pkt contains */
+					/* FLOW CONTROL info only */
+
+/* version numbers */
+#define BDC_PROTO_VER_1		1	/* Old Protocol version */
+#define BDC_PROTO_VER		2	/* Protocol version */
+
+/* flags2.if field access macros */
+#define BDC_GET_IF_IDX(hdr) \
+	((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
+#define BDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT)))
+
+#define BDC_FLAG2_PAD_MASK		0xf0
+#define BDC_FLAG_PAD_MASK		0x03
+#define BDC_FLAG2_PAD_SHIFT		2
+#define BDC_FLAG_PAD_SHIFT		0
+#define BDC_FLAG2_PAD_IDX		0x3c
+#define BDC_FLAG_PAD_IDX		0x03
+#define BDC_GET_PAD_LEN(hdr) \
+	((int)(((((hdr)->flags2) & BDC_FLAG2_PAD_MASK) >> BDC_FLAG2_PAD_SHIFT) | \
+	((((hdr)->flags) & BDC_FLAG_PAD_MASK) >> BDC_FLAG_PAD_SHIFT)))
+#define BDC_SET_PAD_LEN(hdr, idx) \
+	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_PAD_MASK) | \
+	(((idx) & BDC_FLAG2_PAD_IDX) << BDC_FLAG2_PAD_SHIFT))); \
+	((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \
+	(((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT)))
+
+#endif /* _bcmcdc_h_ */
diff --git a/wl/src/include/bcmcrypto/md32_common.h b/wl/src/include/bcmcrypto/md32_common.h
new file mode 100644
index 0000000..d31aae8
--- /dev/null
+++ b/wl/src/include/bcmcrypto/md32_common.h
@@ -0,0 +1,527 @@
+/* crypto/md32_common.h */
+/* ====================================================================
+ * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ *
+ * <<Broadcom-WL-IPTag/Open:>>
+ */
+
+/*
+ * This is a generic 32 bit "collector" for message digest algorithms.
+ * Whenever needed it collects input character stream into chunks of
+ * 32 bit values and invokes a block function that performs actual hash
+ * calculations.
+ *
+ * Porting guide.
+ *
+ * Obligatory macros:
+ *
+ * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
+ *	this macro defines byte order of input stream.
+ * HASH_CBLOCK
+ *	size of a unit chunk HASH_BLOCK operates on.
+ * HASH_LONG
+ *	has to be at lest 32 bit wide, if it's wider, then
+ *	HASH_LONG_LOG2 *has to* be defined along
+ * HASH_CTX
+ *	context structure that at least contains following
+ *	members:
+ *		typedef struct {
+ *			...
+ *			HASH_LONG	Nl,Nh;
+ *			HASH_LONG	data[HASH_LBLOCK];
+ *			unsigned int	num;
+ *			...
+ *			} HASH_CTX;
+ * HASH_UPDATE
+ *	name of "Update" function, implemented here.
+ * HASH_TRANSFORM
+ *	name of "Transform" function, implemented here.
+ * HASH_FINAL
+ *	name of "Final" function, implemented here.
+ * HASH_BLOCK_HOST_ORDER
+ *	name of "block" function treating *aligned* input message
+ *	in host byte order, implemented externally.
+ * HASH_BLOCK_DATA_ORDER
+ *	name of "block" function treating *unaligned* input message
+ *	in original (data) byte order, implemented externally (it
+ *	actually is optional if data and host are of the same
+ *	"endianess").
+ * HASH_MAKE_STRING
+ *	macro convering context variables to an ASCII hash string.
+ *
+ * Optional macros:
+ *
+ * B_ENDIAN or L_ENDIAN
+ *	defines host byte-order.
+ * HASH_LONG_LOG2
+ *	defaults to 2 if not states otherwise.
+ * HASH_LBLOCK
+ *	assumed to be HASH_CBLOCK/4 if not stated otherwise.
+ * HASH_BLOCK_DATA_ORDER_ALIGNED
+ *	alternative "block" function capable of treating
+ *	aligned input message in original (data) order,
+ *	implemented externally.
+ *
+ * MD5 example:
+ *
+ *	#define DATA_ORDER_IS_LITTLE_ENDIAN
+ *
+ *	#define HASH_LONG		MD5_LONG
+ *	#define HASH_LONG_LOG2		MD5_LONG_LOG2
+ *	#define HASH_CTX		MD5_CTX
+ *	#define HASH_CBLOCK		MD5_CBLOCK
+ *	#define HASH_LBLOCK		MD5_LBLOCK
+ *	#define HASH_UPDATE		MD5_Update
+ *	#define HASH_TRANSFORM		MD5_Transform
+ *	#define HASH_FINAL		MD5_Final
+ *	#define HASH_BLOCK_HOST_ORDER	md5_block_host_order
+ *	#define HASH_BLOCK_DATA_ORDER	md5_block_data_order
+ *
+ *					<appro@fy.chalmers.se>
+ */
+
+/* FILE-CSTYLED */
+
+#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#error "DATA_ORDER must be defined!"
+#endif
+
+#ifndef HASH_CBLOCK
+#error "HASH_CBLOCK must be defined!"
+#endif
+#ifndef HASH_LONG
+#error "HASH_LONG must be defined!"
+#endif
+#ifndef HASH_CTX
+#error "HASH_CTX must be defined!"
+#endif
+
+#ifndef HASH_UPDATE
+#error "HASH_UPDATE must be defined!"
+#endif
+#ifndef HASH_TRANSFORM
+#error "HASH_TRANSFORM must be defined!"
+#endif
+#ifndef HASH_FINAL
+#error "HASH_FINAL must be defined!"
+#endif
+
+#ifndef HASH_BLOCK_HOST_ORDER
+#error "HASH_BLOCK_HOST_ORDER must be defined!"
+#endif
+
+
+#ifndef HASH_LBLOCK
+#define HASH_LBLOCK	(HASH_CBLOCK/4)
+#endif
+
+#ifndef HASH_LONG_LOG2
+#define HASH_LONG_LOG2	2
+#endif
+
+#ifndef ROTATE
+#define ROTATE(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
+#endif
+
+/*
+ * Make some obvious choices. E.g., HASH_BLOCK_DATA_ORDER_ALIGNED
+ * and HASH_BLOCK_HOST_ORDER ought to be the same if input data
+ * and host are of the same "endianess". It's possible to mask
+ * this with blank #define HASH_BLOCK_DATA_ORDER though...
+ *
+ *				<appro@fy.chalmers.se>
+ */
+#if defined(B_ENDIAN)
+#  if defined(DATA_ORDER_IS_BIG_ENDIAN)
+#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
+#      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER
+#    endif
+#  endif
+#elif defined(L_ENDIAN)
+#  if defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#    if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED) && HASH_LONG_LOG2==2
+#      define HASH_BLOCK_DATA_ORDER_ALIGNED	HASH_BLOCK_HOST_ORDER
+#    endif
+#  endif
+#endif
+
+#if !defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+#ifndef HASH_BLOCK_DATA_ORDER
+#error "HASH_BLOCK_DATA_ORDER must be defined!"
+#endif
+#endif
+
+#if defined(DATA_ORDER_IS_BIG_ENDIAN)
+
+#ifndef PEDANTIC
+# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && \
+	!defined(OPENSSL_NO_INLINE_ASM)
+#  if ((defined(__i386) || defined(__i386__)) && !defined(I386_ONLY)) || \
+	(defined(__x86_64) || defined(__x86_64__))
+    /*
+     * This gives ~30-40% performance improvement in SHA-256 compiled
+     * with gcc [on P4]. Well, first macro to be frank. We can pull
+     * this trick on x86* platforms only, because these CPUs can fetch
+     * unaligned data without raising an exception.
+     */
+#   define HOST_c2l(c,l)	({ unsigned int r=*((const unsigned int *)(c));	\
+				   asm ("bswapl %0":"=r"(r):"0"(r));	\
+				   (c)+=4; (l)=r;			})
+#   define HOST_l2c(l,c)	({ unsigned int r=(l);			\
+				   asm ("bswapl %0":"=r"(r):"0"(r));	\
+				   *((unsigned int *)(c))=r; (c)+=4; r;	})
+#  endif
+# endif
+#endif
+
+#ifndef HOST_c2l
+#define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))<<24),		\
+			 l|=(((unsigned long)(*((c)++)))<<16),		\
+			 l|=(((unsigned long)(*((c)++)))<< 8),		\
+			 l|=(((unsigned long)(*((c)++)))    ),		\
+			 l)
+#endif
+#define HOST_p_c2l(c,l,n)	{					\
+			switch (n) {					\
+			case 0: l =((unsigned long)(*((c)++)))<<24;	\
+			case 1: l|=((unsigned long)(*((c)++)))<<16;	\
+			case 2: l|=((unsigned long)(*((c)++)))<< 8;	\
+			case 3: l|=((unsigned long)(*((c)++)));		\
+				} }
+#define HOST_p_c2l_p(c,l,sc,len) {					\
+			switch (sc) {					\
+			case 0: l =((unsigned long)(*((c)++)))<<24;	\
+				if (--len == 0) break;			\
+			case 1: l|=((unsigned long)(*((c)++)))<<16;	\
+				if (--len == 0) break;			\
+			case 2: l|=((unsigned long)(*((c)++)))<< 8;	\
+				} }
+/* NOTE the pointer is not incremented at the end of this */
+#define HOST_c2l_p(c,l,n)	{					\
+			l=0; (c)+=n;					\
+			switch (n) {					\
+			case 3: l =((unsigned long)(*(--(c))))<< 8;	\
+			case 2: l|=((unsigned long)(*(--(c))))<<16;	\
+			case 1: l|=((unsigned long)(*(--(c))))<<24;	\
+				} }
+#ifndef HOST_l2c
+#define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)>>24)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)    )&0xff),	\
+			 l)
+#endif
+
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+
+#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
+# ifndef B_ENDIAN
+   /* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
+#  define HOST_c2l(c,l)	((l)=*((const unsigned int *)(c)), (c)+=4, l)
+#  define HOST_l2c(l,c)	(*((unsigned int *)(c))=(l), (c)+=4, l)
+# endif
+#endif
+
+#ifndef HOST_c2l
+#define HOST_c2l(c,l)	(l =(((unsigned long)(*((c)++)))    ),		\
+			 l|=(((unsigned long)(*((c)++)))<< 8),		\
+			 l|=(((unsigned long)(*((c)++)))<<16),		\
+			 l|=(((unsigned long)(*((c)++)))<<24),		\
+			 l)
+#endif
+#define HOST_p_c2l(c,l,n)	{					\
+			switch (n) {					\
+			case 0: l =((unsigned long)(*((c)++)));		\
+			case 1: l|=((unsigned long)(*((c)++)))<< 8;	\
+			case 2: l|=((unsigned long)(*((c)++)))<<16;	\
+			case 3: l|=((unsigned long)(*((c)++)))<<24;	\
+				} }
+#define HOST_p_c2l_p(c,l,sc,len) {					\
+			switch (sc) {					\
+			case 0: l =((unsigned long)(*((c)++)));		\
+				if (--len == 0) break;			\
+			case 1: l|=((unsigned long)(*((c)++)))<< 8;	\
+				if (--len == 0) break;			\
+			case 2: l|=((unsigned long)(*((c)++)))<<16;	\
+				} }
+/* NOTE the pointer is not incremented at the end of this */
+#define HOST_c2l_p(c,l,n)	{					\
+			l=0; (c)+=n;					\
+			switch (n) {					\
+			case 3: l =((unsigned long)(*(--(c))))<<16;	\
+			case 2: l|=((unsigned long)(*(--(c))))<< 8;	\
+			case 1: l|=((unsigned long)(*(--(c))));		\
+				} }
+#ifndef HOST_l2c
+#define HOST_l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>24)&0xff),	\
+			 l)
+#endif
+
+#endif
+
+/*
+ * Time for some action:-)
+ */
+
+int HASH_UPDATE (HASH_CTX *c, const void *data_, size_t len)
+	{
+	const unsigned char *data=data_;
+	register HASH_LONG * p;
+	register HASH_LONG l;
+	size_t sw,sc,ew,ec;
+
+	if (len==0) return 1;
+
+	l=(c->Nl+(((HASH_LONG)len)<<3))&0xffffffffUL;
+	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
+	 * Wei Dai <weidai@eskimo.com> for pointing it out. */
+	if (l < c->Nl) /* overflow */
+		c->Nh++;
+	c->Nh+=(unsigned int)(len>>29);	/* might cause compiler warning on 16-bit */
+	c->Nl=l;
+
+	if (c->num != 0)
+		{
+		p=c->data;
+		sw=c->num>>2;
+		sc=c->num&0x03;
+
+		if ((c->num+len) >= HASH_CBLOCK)
+			{
+			l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
+			for (; sw<HASH_LBLOCK; sw++)
+				{
+				HOST_c2l(data,l); p[sw]=l;
+				}
+			HASH_BLOCK_HOST_ORDER (c,p,1);
+			len-=(HASH_CBLOCK-c->num);
+			c->num=0;
+			/* drop through and do the rest */
+			}
+		else
+			{
+			c->num+=(unsigned int)len;
+			if ((sc+len) < 4) /* ugly, add char's to a word */
+				{
+				l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
+				}
+			else
+				{
+				ew=(c->num>>2);
+				ec=(c->num&0x03);
+				if (sc)
+					l=p[sw];
+				HOST_p_c2l(data,l,sc);
+				p[sw++]=l;
+				for (; sw < ew; sw++)
+					{
+					HOST_c2l(data,l); p[sw]=l;
+					}
+				if (ec)
+					{
+					HOST_c2l_p(data,l,ec); p[sw]=l;
+					}
+				}
+			return 1;
+			}
+		}
+
+	sw=len/HASH_CBLOCK;
+	if (sw > 0)
+		{
+#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+		/*
+		 * Note that HASH_BLOCK_DATA_ORDER_ALIGNED gets defined
+		 * only if sizeof(HASH_LONG)==4.
+		 */
+		if ((((size_t)data)%4) == 0)
+			{
+			/* data is properly aligned so that we can cast it: */
+			HASH_BLOCK_DATA_ORDER_ALIGNED (c,(const HASH_LONG *)data,sw);
+			sw*=HASH_CBLOCK;
+			data+=sw;
+			len-=sw;
+			}
+		else
+#if !defined(HASH_BLOCK_DATA_ORDER)
+			while (sw--)
+				{
+				memcpy (p=c->data,data,HASH_CBLOCK);
+				HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);
+				data+=HASH_CBLOCK;
+				len-=HASH_CBLOCK;
+				}
+#endif
+#endif
+#if defined(HASH_BLOCK_DATA_ORDER)
+			{
+			HASH_BLOCK_DATA_ORDER(c,data,sw);
+			sw*=HASH_CBLOCK;
+			data+=sw;
+			len-=sw;
+			}
+#endif
+		}
+
+	if (len!=0)
+		{
+		p = c->data;
+		c->num = (unsigned int)len;
+		ew=len>>2;	/* words to copy */
+		ec=len&0x03;
+		for (; ew; ew--,p++)
+			{
+			HOST_c2l(data,l); *p=l;
+			}
+		HOST_c2l_p(data,l,ec);
+		*p=l;
+		}
+	return 1;
+	}
+
+
+void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
+	{
+#if defined(HASH_BLOCK_DATA_ORDER_ALIGNED)
+	if ((((size_t)data)%4) == 0)
+		/* data is properly aligned so that we can cast it: */
+		HASH_BLOCK_DATA_ORDER_ALIGNED (c,(const HASH_LONG *)data,1);
+	else
+#if !defined(HASH_BLOCK_DATA_ORDER)
+		{
+		memcpy (c->data,data,HASH_CBLOCK);
+		HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);
+		}
+#endif
+#endif
+#if defined(HASH_BLOCK_DATA_ORDER)
+	HASH_BLOCK_DATA_ORDER (c,data,1);
+#endif
+	}
+
+
+int HASH_FINAL (unsigned char *md, HASH_CTX *c)
+	{
+	register HASH_LONG *p;
+	register unsigned long l;
+	register int i,j;
+	static const unsigned char end[4]={0x80,0x00,0x00,0x00};
+	const unsigned char *cp=end;
+
+	/* c->num should definitly have room for at least one more byte. */
+	p=c->data;
+	i=c->num>>2;
+	j=c->num&0x03;
+
+	l = (j==0) ? 0 : p[i];
+	HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */
+
+	if (i>(HASH_LBLOCK-2)) /* save room for Nl and Nh */
+		{
+		if (i<HASH_LBLOCK) p[i]=0;
+		HASH_BLOCK_HOST_ORDER (c,p,1);
+		i=0;
+		}
+	for (; i<(HASH_LBLOCK-2); i++)
+		p[i]=0;
+
+#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
+	p[HASH_LBLOCK-2]=c->Nh;
+	p[HASH_LBLOCK-1]=c->Nl;
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+	p[HASH_LBLOCK-2]=c->Nl;
+	p[HASH_LBLOCK-1]=c->Nh;
+#endif
+	HASH_BLOCK_HOST_ORDER (c,p,1);
+
+#ifndef HASH_MAKE_STRING
+#error "HASH_MAKE_STRING must be defined!"
+#else
+	HASH_MAKE_STRING(c,md);
+#endif
+
+	c->num=0;
+	/* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
+	 * but I'm not worried :-)
+	OPENSSL_cleanse((void *)c,sizeof(HASH_CTX));
+	 */
+	return 1;
+	}
+
+#ifndef MD32_REG_T
+#define MD32_REG_T long
+/*
+ * This comment was originaly written for MD5, which is why it
+ * discusses A-D. But it basically applies to all 32-bit digests,
+ * which is why it was moved to common header file.
+ *
+ * In case you wonder why A-D are declared as long and not
+ * as MD5_LONG. Doing so results in slight performance
+ * boost on LP64 architectures. The catch is we don't
+ * really care if 32 MSBs of a 64-bit register get polluted
+ * with eventual overflows as we *save* only 32 LSBs in
+ * *either* case. Now declaring 'em long excuses the compiler
+ * from keeping 32 MSBs zeroed resulting in 13% performance
+ * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
+ * Well, to be honest it should say that this *prevents* 
+ * performance degradation.
+ *				<appro@fy.chalmers.se>
+ * Apparently there're LP64 compilers that generate better
+ * code if A-D are declared int. Most notably GCC-x86_64
+ * generates better code.
+ *				<appro@fy.chalmers.se>
+ */
+#endif
diff --git a/wl/src/include/bcmcrypto/sha256.h b/wl/src/include/bcmcrypto/sha256.h
new file mode 100644
index 0000000..c7b9e9b
--- /dev/null
+++ b/wl/src/include/bcmcrypto/sha256.h
@@ -0,0 +1,141 @@
+/* sha256.h
+ * Code copied from openssl distribution and
+ * Modified just enough so that compiles and runs standalone
+ *
+ * Copyright (C) 2017, Broadcom. 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: sha256.h 523133 2014-12-27 05:50:30Z $
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_SHA_H
+#define HEADER_SHA_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/*
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * ! SHA_LONG has to be at least 32 bits wide. If it's wider, then !
+ * ! SHA_LONG_LOG2 has to be defined along.                        !
+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ */
+
+#if defined(OPENSSL_SYS_WIN16) || defined(__LP32__)
+#define SHA_LONG unsigned long
+#elif defined(OPENSSL_SYS_CRAY) || defined(__ILP64__)
+#define SHA_LONG unsigned long
+#define SHA_LONG_LOG2 3
+#else
+#define SHA_LONG unsigned int
+#endif
+
+#define SHA_LBLOCK	16
+#define SHA_CBLOCK	(SHA_LBLOCK*4)	/* SHA treats input data as a
+					 * contiguous array of 32 bit
+					 * wide big-endian values.
+					 */
+#define SHA_LAST_BLOCK  (SHA_CBLOCK-8)
+#define SHA_DIGEST_LENGTH 20
+
+#define SHA256_CBLOCK	(SHA_LBLOCK*4)	/* SHA-256 treats input data as a
+					 * contiguous array of 32 bit
+					 * wide big-endian values.
+					 */
+#define SHA224_DIGEST_LENGTH	28
+#define SHA256_DIGEST_LENGTH	32
+
+typedef struct SHA256state_st
+	{
+	SHA_LONG h[8];
+	SHA_LONG Nl, Nh;
+	SHA_LONG data[SHA_LBLOCK];
+	unsigned int num, md_len;
+	} SHA256_CTX;
+
+int SHA224_Init(SHA256_CTX *c);
+int SHA224_Update(SHA256_CTX *c, const void *data, size_t len);
+int SHA224_Final(unsigned char *md, SHA256_CTX *c);
+unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md);
+int SHA256_Init(SHA256_CTX *c);
+int SHA256_Update(SHA256_CTX *c, const void *data, size_t len);
+int SHA256_Final(unsigned char *md, SHA256_CTX *c);
+unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md);
+void SHA256_Transform(SHA256_CTX *c, const unsigned char *data);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* HEADER_SHA_H */
diff --git a/wl/src/include/bcmdefs.h b/wl/src/include/bcmdefs.h
new file mode 100644
index 0000000..4caa55f
--- /dev/null
+++ b/wl/src/include/bcmdefs.h
@@ -0,0 +1,605 @@
+/*
+ * Misc system wide definitions
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmdefs.h 659962 2016-09-16 18:46:17Z $
+ */
+
+#ifndef	_bcmdefs_h_
+#define	_bcmdefs_h_
+
+/*
+ * One doesn't need to include this file explicitly, gets included automatically if
+ * typedefs.h is included.
+ */
+
+/* Use BCM_REFERENCE to suppress warnings about intentionally-unused function
+ * arguments or local variables.
+ */
+#define BCM_REFERENCE(data)	((void)(data))
+
+/* Allow for suppressing unused variable warnings. */
+#ifdef __GNUC__
+#define UNUSED_VAR     __attribute__ ((unused))
+#else
+#define UNUSED_VAR
+#endif
+
+/* Compile-time assert can be used in place of ASSERT if the expression evaluates
+ * to a constant at compile time.
+ */
+#define STATIC_ASSERT(expr) { \
+	/* Make sure the expression is constant. */ \
+	typedef enum { _STATIC_ASSERT_NOT_CONSTANT = (expr) } _static_assert_e UNUSED_VAR; \
+	/* Make sure the expression is true. */ \
+	typedef char STATIC_ASSERT_FAIL[(expr) ? 1 : -1] UNUSED_VAR; \
+}
+
+/* Reclaiming text and data :
+ * The following macros specify special linker sections that can be reclaimed
+ * after a system is considered 'up'.
+ * BCMATTACHFN is also used for detach functions (it's not worth having a BCMDETACHFN,
+ * as in most cases, the attach function calls the detach function to clean up on error).
+ */
+#if defined(BCM_RECLAIM)
+
+extern bool bcm_reclaimed;
+extern bool bcm_attach_part_reclaimed;
+extern bool bcm_preattach_part_reclaimed;
+extern bool bcm_postattach_part_reclaimed;
+
+#define RECLAIMED()			(bcm_reclaimed)
+#define ATTACH_PART_RECLAIMED()		(bcm_attach_part_reclaimed)
+#define PREATTACH_PART_RECLAIMED()	(bcm_preattach_part_reclaimed)
+#define POSTATTACH_PART_RECLAIMED()	(bcm_postattach_part_reclaimed)
+
+#if defined(BCM_RECLAIM_ATTACH_FN_DATA)
+#define BCMATTACHDATA(_data)	__attribute__ ((__section__ (".dataini2." #_data))) _data
+#define BCMATTACHFN(_fn)	__attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn
+
+/* Relocate attach symbols to save-restore region to increase pre-reclaim heap size. */
+#define BCM_SRM_ATTACH_DATA(_data)    __attribute__ ((__section__ (".datasrm." #_data))) _data
+#define BCM_SRM_ATTACH_FN(_fn)        __attribute__ ((__section__ (".textsrm." #_fn), noinline)) _fn
+
+#ifndef PREATTACH_NORECLAIM
+#define BCMPREATTACHDATA(_data)	__attribute__ ((__section__ (".dataini3." #_data))) _data
+#define BCMPREATTACHFN(_fn)	__attribute__ ((__section__ (".textini3." #_fn), noinline)) _fn
+#else
+#define BCMPREATTACHDATA(_data)	__attribute__ ((__section__ (".dataini2." #_data))) _data
+#define BCMPREATTACHFN(_fn)	__attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn
+#endif /* PREATTACH_NORECLAIM  */
+#define BCMPOSTATTACHDATA(_data)	__attribute__ ((__section__ (".dataini5." #_data))) _data
+#define BCMPOSTATTACHFN(_fn)	__attribute__ ((__section__ (".textini5." #_fn), noinline)) _fn
+#else  /* BCM_RECLAIM_ATTACH_FN_DATA  */
+#define BCMATTACHDATA(_data)	_data
+#define BCMATTACHFN(_fn)	_fn
+#define BCMPREATTACHDATA(_data)	_data
+#define BCMPREATTACHFN(_fn)	_fn
+#define BCMPOSTATTACHDATA(_data)	_data
+#define BCMPOSTATTACHFN(_fn)	_fn
+#endif /* BCM_RECLAIM_ATTACH_FN_DATA  */
+
+#ifdef BCMDBG_SR
+/*
+ * Don't reclaim so we can compare SR ASM
+ */
+#define BCMPREATTACHDATASR(_data)	_data
+#define BCMPREATTACHFNSR(_fn)		_fn
+#define BCMATTACHDATASR(_data)		_data
+#define BCMATTACHFNSR(_fn)		_fn
+#else
+#define BCMPREATTACHDATASR(_data)	BCMPREATTACHDATA(_data)
+#define BCMPREATTACHFNSR(_fn)		BCMPREATTACHFN(_fn)
+#define BCMATTACHDATASR(_data)		BCMATTACHDATA(_data)
+#define BCMATTACHFNSR(_fn)		BCMATTACHFN(_fn)
+#endif
+
+#if defined(BCM_RECLAIM_INIT_FN_DATA)
+#define BCMINITDATA(_data)	__attribute__ ((__section__ (".dataini1." #_data))) _data
+#define BCMINITFN(_fn)		__attribute__ ((__section__ (".textini1." #_fn), noinline)) _fn
+#define CONST
+#else /* BCM_RECLAIM_INIT_FN_DATA  */
+#define BCMINITDATA(_data)	_data
+#define BCMINITFN(_fn)		_fn
+#ifndef CONST
+#define CONST	const
+#endif
+#endif /* BCM_RECLAIM_INIT_FN_DATA  */
+
+/* Non-manufacture or internal attach function/dat */
+#define	BCMNMIATTACHFN(_fn)	BCMATTACHFN(_fn)
+#define	BCMNMIATTACHDATA(_data)	BCMATTACHDATA(_data)
+
+/* SROM with OTP support */
+#if defined(BCMOTPSROM)
+#define	BCMSROMATTACHFN(_fn)		_fn
+#define	BCMSROMATTACHDATA(_data)	_data
+#else
+#define	BCMSROMATTACHFN(_fn)		BCMNMIATTACHFN(_fn)
+#define	BCMSROMATTACHDATA(_data)	BCMNMIATTACHFN(_data)
+#endif	/* BCMOTPSROM */
+
+#ifdef BCMNODOWN
+#define BCMUNINITFN(_fn)	BCMINITFN(_fn)
+#else
+#define BCMUNINITFN(_fn)	_fn
+#endif
+
+#else /* BCM_RECLAIM */
+
+#define bcm_reclaimed			(1)
+#define bcm_attach_part_reclaimed	(1)
+#define bcm_preattach_part_reclaimed	(1)
+#define bcm_postattach_part_reclaimed	(1)
+#define BCMATTACHDATA(_data)		_data
+#define BCMATTACHFN(_fn)		_fn
+#define BCM_SRM_ATTACH_DATA(_data)	_data
+#define BCM_SRM_ATTACH_FN(_fn)		_fn
+#define BCMPREATTACHDATA(_data)		_data
+#define BCMPREATTACHFN(_fn)		_fn
+#define BCMPOSTATTACHDATA(_data)	_data
+#define BCMPOSTATTACHFN(_fn)		_fn
+#define BCMINITDATA(_data)		_data
+#define BCMINITFN(_fn)			_fn
+#define BCMUNINITFN(_fn)		_fn
+#define	BCMNMIATTACHFN(_fn)		_fn
+#define	BCMNMIATTACHDATA(_data)		_data
+#define	BCMSROMATTACHFN(_fn)		_fn
+#define	BCMSROMATTACHDATA(_data)	_data
+#define BCMPREATTACHFNSR(_fn)		_fn
+#define BCMPREATTACHDATASR(_data)	_data
+#define BCMATTACHFNSR(_fn)		_fn
+#define BCMATTACHDATASR(_data)		_data
+#define CONST				const
+
+#define RECLAIMED()			(bcm_reclaimed)
+#define ATTACH_PART_RECLAIMED()		(bcm_attach_part_reclaimed)
+#define PREATTACH_PART_RECLAIMED()	(bcm_preattach_part_reclaimed)
+#define POSTATTACH_PART_RECLAIMED()	(bcm_postattach_part_reclaimed)
+
+#endif /* BCM_RECLAIM */
+
+#define BCMUCODEDATA(_data)		BCMINITDATA(_data)
+
+#if defined(BCM_DMA_CT) && !defined(BCM_DMA_CT_DISABLED)
+#define BCMUCODEFN(_fn)			BCMINITFN(_fn)
+#else
+#define BCMUCODEFN(_fn)			BCMATTACHFN(_fn)
+#endif /* BCM_DMA_CT */
+
+#if !defined STB
+#if defined(BCM47XX) && defined(__ARM_ARCH_7A__) && !defined(OEM_ANDROID)
+#define BCM47XX_CA9
+#else
+#undef BCM47XX_CA9
+#endif /* BCM47XX && __ARM_ARCH_7A__ && !OEM_ANDROID */
+#endif /* STB */
+
+/* BCMFASTPATH Related Macro defines
+*/
+#ifndef BCMFASTPATH
+#if defined(mips) || defined(BCM47XX_CA9) || defined(STB)
+#define BCMFASTPATH		__attribute__ ((__section__ (".text.fastpath")))
+#define BCMFASTPATH_HOST	__attribute__ ((__section__ (".text.fastpath_host")))
+#else /* mips || BCM47XX_CA9 || STB */
+#define BCMFASTPATH
+#define BCMFASTPATH_HOST
+#endif /* mips || BCM47XX_CA9 || STB */
+#endif /* BCMFASTPATH */
+
+/* Use the BCMRAMFN() macro to tag functions in source that must be included in RAM (excluded from
+ * ROM). This should eliminate the need to manually specify these functions in the ROM config file.
+ * It should only be used in special cases where the function must be in RAM for *all* ROM-based
+ * chips.
+ */
+#if defined(BCMROMBUILD)
+	#define BCMRAMFN(_fn)	__attribute__ ((__section__ (".text_ram." #_fn), noinline)) _fn
+#else
+	#define BCMRAMFN(_fn)	_fn
+#endif
+
+#define STATIC	static
+
+/* Bus types */
+#define	SI_BUS			0	/* SOC Interconnect */
+#define	PCI_BUS			1	/* PCI target */
+#define	PCMCIA_BUS		2	/* PCMCIA target */
+#define SDIO_BUS		3	/* SDIO target */
+#define JTAG_BUS		4	/* JTAG */
+#define USB_BUS			5	/* USB (does not support R/W REG) */
+#define SPI_BUS			6	/* gSPI target */
+#define RPC_BUS			7	/* RPC target */
+
+/* Allows size optimization for single-bus image */
+#ifdef BCMBUSTYPE
+#define BUSTYPE(bus)	(BCMBUSTYPE)
+#else
+#define BUSTYPE(bus)	(bus)
+#endif
+
+#ifdef BCMBUSCORETYPE
+#define BUSCORETYPE(ct)		(BCMBUSCORETYPE)
+#else
+#define BUSCORETYPE(ct)		(ct)
+#endif
+
+/* Allows size optimization for single-backplane image */
+#ifdef BCMCHIPTYPE
+#define CHIPTYPE(bus)	(BCMCHIPTYPE)
+#else
+#define CHIPTYPE(bus)	(bus)
+#endif
+
+
+/* Allows size optimization for SPROM support */
+#if defined(BCMSPROMBUS)
+#define SPROMBUS	(BCMSPROMBUS)
+#elif defined(SI_PCMCIA_SROM)
+#define SPROMBUS	(PCMCIA_BUS)
+#else
+#define SPROMBUS	(PCI_BUS)
+#endif
+
+/* Allows size optimization for single-chip image */
+#ifdef BCMCHIPID
+#define CHIPID(chip)	(BCMCHIPID)
+#else
+#define CHIPID(chip)	(chip)
+#endif
+
+#ifdef BCMCHIPREV
+#define CHIPREV(rev)	(BCMCHIPREV)
+#else
+#define CHIPREV(rev)	(rev)
+#endif
+
+#ifdef BCMPCIEREV
+#define PCIECOREREV(rev)	(BCMPCIEREV)
+#else
+#define PCIECOREREV(rev)	(rev)
+#endif
+
+#ifdef BCMPMUREV
+#define PMUREV(rev)	(BCMPMUREV)
+#else
+#define PMUREV(rev)	(rev)
+#endif
+
+#ifdef BCMCCREV
+#define CCREV(rev)	(BCMCCREV)
+#else
+#define CCREV(rev)	(rev)
+#endif
+
+#ifdef BCMGCIREV
+#define GCIREV(rev)	(BCMGCIREV)
+#else
+#define GCIREV(rev)	(rev)
+#endif
+
+/* Defines for DMA Address Width - Shared between OSL and HNDDMA */
+#define DMADDR_MASK_32 0x0		/* Address mask for 32-bits */
+#define DMADDR_MASK_30 0xc0000000	/* Address mask for 30-bits */
+#define DMADDR_MASK_26 0xFC000000	/* Address maks for 26-bits */
+#define DMADDR_MASK_0  0xffffffff	/* Address mask for 0-bits (hi-part) */
+
+#define	DMADDRWIDTH_26  26 /* 26-bit addressing capability */
+#define	DMADDRWIDTH_30  30 /* 30-bit addressing capability */
+#define	DMADDRWIDTH_32  32 /* 32-bit addressing capability */
+#define	DMADDRWIDTH_63  63 /* 64-bit addressing capability */
+#define	DMADDRWIDTH_64  64 /* 64-bit addressing capability */
+
+typedef struct {
+	uint32 loaddr;
+	uint32 hiaddr;
+} dma64addr_t;
+
+#define PHYSADDR64HI(_pa) ((_pa).hiaddr)
+#define PHYSADDR64HISET(_pa, _val) \
+	do { \
+		(_pa).hiaddr = (_val);		\
+	} while (0)
+#define PHYSADDR64LO(_pa) ((_pa).loaddr)
+#define PHYSADDR64LOSET(_pa, _val) \
+	do { \
+		(_pa).loaddr = (_val);		\
+	} while (0)
+
+#ifdef BCMDMA64OSL
+typedef dma64addr_t dmaaddr_t;
+#define PHYSADDRHI(_pa) PHYSADDR64HI(_pa)
+#define PHYSADDRHISET(_pa, _val) PHYSADDR64HISET(_pa, _val)
+#define PHYSADDRLO(_pa)  PHYSADDR64LO(_pa)
+#define PHYSADDRLOSET(_pa, _val) PHYSADDR64LOSET(_pa, _val)
+#define PHYSADDRTOULONG(_pa, _ulong) \
+	do { \
+		_ulong = ((unsigned long long)(_pa).hiaddr << 32) | ((_pa).loaddr); \
+	} while (0)
+
+#else
+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)
+#endif /* BCMDMA64OSL */
+#define PHYSADDRISZERO(_pa) (PHYSADDRLO(_pa) == 0 && PHYSADDRHI(_pa) == 0)
+
+/* One physical DMA segment */
+typedef struct  {
+	dmaaddr_t addr;
+	uint32	  length;
+} hnddma_seg_t;
+
+#if defined(linux)
+#define MAX_DMA_SEGS 8
+#else
+#define MAX_DMA_SEGS 4
+#endif
+
+
+typedef struct {
+	void *oshdmah; /* Opaque handle for OSL to store its information */
+	uint origsize; /* Size of the virtual packet */
+	uint nsegs;
+	hnddma_seg_t segs[MAX_DMA_SEGS];
+} hnddma_seg_map_t;
+
+
+/* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF).
+ * By doing, we avoid the need  to allocate an extra buffer for the header when bridging to WL.
+ * There is a compile time check in wlc.c which ensure that this value is at least as big
+ * as TXOFF. This value is used in dma_rxfill (hnddma.c).
+ */
+
+#if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY)
+/* add 40 bytes to allow for extra RPC header and info  */
+#define BCMEXTRAHDROOM 260
+#else /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */
+#if defined(linux) && (defined(BCM47XX_CA9) || defined(STB))
+#if defined(BCM_GMAC3)
+#define BCMEXTRAHDROOM 32 /* For FullDongle, no D11 headroom space required. */
+#define BCMEXTRAHDROOM_NIC 224
+#else
+#define BCMEXTRAHDROOM 224
+#endif /* ! BCM_GMAC3 */
+#else
+#ifdef CTFMAP
+#define BCMEXTRAHDROOM 208
+#else /* CTFMAP */
+#define BCMEXTRAHDROOM 204
+#endif /* CTFMAP */
+#endif /* linux && BCM47XX_CA9 */
+#endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */
+
+/* Packet alignment for most efficient SDIO (can change based on platform) */
+#ifndef SDALIGN
+#define SDALIGN	32
+#endif
+
+/* Headroom required for dongle-to-host communication.  Packets allocated
+ * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should
+ * leave this much room in front for low-level message headers which may
+ * be needed to get across the dongle bus to the host.  (These messages
+ * don't go over the network, so room for the full WL header above would
+ * be a waste.).
+*/
+#define BCMDONGLEHDRSZ 12
+#define BCMDONGLEPADSZ 16
+
+#define BCMDONGLEOVERHEAD	(BCMDONGLEHDRSZ + BCMDONGLEPADSZ)
+
+#ifdef BCMDBG
+
+#ifndef BCMDBG_ERR
+#define BCMDBG_ERR
+#endif /* BCMDBG_ERR */
+
+#ifndef BCMDBG_ASSERT
+#define BCMDBG_ASSERT
+#endif /* BCMDBG_ASSERT */
+
+#endif /* BCMDBG */
+
+#if defined(NO_BCMDBG_ASSERT)
+# undef BCMDBG_ASSERT
+# undef BCMASSERT_LOG
+#endif
+
+#if defined(BCMDBG_ASSERT) || defined(BCMASSERT_LOG)
+#define BCMASSERT_SUPPORT
+#endif /* BCMDBG_ASSERT || BCMASSERT_LOG */
+
+/* Macros for doing definition and get/set of bitfields
+ * Usage example, e.g. a three-bit field (bits 4-6):
+ *    #define <NAME>_M	BITFIELD_MASK(3)
+ *    #define <NAME>_S	4
+ * ...
+ *    regval = R_REG(osh, &regs->regfoo);
+ *    field = GFIELD(regval, <NAME>);
+ *    regval = SFIELD(regval, <NAME>, 1);
+ *    W_REG(osh, &regs->regfoo, regval);
+ */
+#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))
+
+/* define BCMSMALL to remove misc features for memory-constrained environments */
+#ifdef BCMSMALL
+#undef	BCMSPACE
+#define bcmspace	FALSE	/* if (bcmspace) code is discarded */
+#else
+#define	BCMSPACE
+#define bcmspace	TRUE	/* if (bcmspace) code is retained */
+#endif
+
+/* Max. nvram variable table size */
+#ifndef MAXSZ_NVRAM_VARS
+#ifdef LARGE_NVRAM_MAXSZ
+#define MAXSZ_NVRAM_VARS	(LARGE_NVRAM_MAXSZ * 2)
+#else
+#if defined(BCMROMBUILD) || defined(DONGLEBUILD)
+/* SROM12 changes */
+#define	MAXSZ_NVRAM_VARS	6144
+#else
+#define LARGE_NVRAM_MAXSZ	8192
+#define MAXSZ_NVRAM_VARS	(LARGE_NVRAM_MAXSZ * 2)
+#endif /* BCMROMBUILD || DONGLEBUILD */
+#endif /* LARGE_NVRAM_MAXSZ */
+#endif /* !MAXSZ_NVRAM_VARS */
+
+#ifdef ATE_BUILD
+#ifndef ATE_NVRAM_MAXSIZE
+#define ATE_NVRAM_MAXSIZE 32000
+#endif /* ATE_NVRAM_MAXSIZE */
+#endif /* ATE_BUILD */
+
+
+/* WL_ENAB_RUNTIME_CHECK may be set based upon the #define below (for ROM builds). It may also
+ * be defined via makefiles (e.g. ROM auto abandon unoptimized compiles).
+ */
+#if defined(BCMROMBUILD)
+	#ifndef WL_ENAB_RUNTIME_CHECK
+		#define WL_ENAB_RUNTIME_CHECK
+	#endif
+#endif /* BCMROMBUILD */
+
+#ifdef BCMLFRAG /* BCMLFRAG support enab macros  */
+	extern bool _bcmlfrag;
+	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+		#define BCMLFRAG_ENAB() (_bcmlfrag)
+	#elif defined(BCMLFRAG_DISABLED)
+		#define BCMLFRAG_ENAB()	(0)
+	#else
+		#define BCMLFRAG_ENAB()	(1)
+	#endif
+#else
+	#define BCMLFRAG_ENAB()		(0)
+#endif /* BCMLFRAG_ENAB */
+
+#ifdef BCMPCIEDEV /* BCMPCIEDEV support enab macros */
+extern bool _pciedevenab;
+	#if defined(WL_ENAB_RUNTIME_CHECK)
+		#define BCMPCIEDEV_ENAB() (_pciedevenab)
+	#elif defined(BCMPCIEDEV_ENABLED)
+		#define BCMPCIEDEV_ENAB()	1
+	#else
+		#define BCMPCIEDEV_ENAB()	0
+	#endif
+#else
+	#define BCMPCIEDEV_ENAB()	0
+#endif /* BCMPCIEDEV */
+
+#ifdef BCMRESVFRAGPOOL /* BCMRESVFRAGPOOL support enab macros */
+extern bool _resvfragpool_enab;
+	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+		#define  BCMRESVFRAGPOOL_ENAB() (_resvfragpool_enab)
+	#elif defined(BCMRESVFRAGPOOL_ENABLED)
+		#define BCMRESVFRAGPOOL_ENAB()	1
+	#else
+		#define BCMRESVFRAGPOOL_ENAB()	0
+	#endif
+#else
+	#define BCMRESVFRAGPOOL_ENAB()	0
+#endif /* BCMPCIEDEV */
+
+#ifdef BCMSDIODEV /* BCMSDIODEV support enab macros */
+extern bool _sdiodevenab;
+	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+		#define BCMSDIODEV_ENAB() (_sdiodevenab)
+	#elif defined(BCMSDIODEV_ENABLED)
+		#define BCMSDIODEV_ENAB()	1
+	#else
+		#define BCMSDIODEV_ENAB()	0
+	#endif
+#else
+	#define BCMSDIODEV_ENAB()	0
+#endif /* BCMSDIODEV */
+
+/* Max size for reclaimable NVRAM array */
+#ifndef ATE_BUILD
+#ifdef DL_NVRAM
+#define NVRAM_ARRAY_MAXSIZE	DL_NVRAM
+#else
+#define NVRAM_ARRAY_MAXSIZE	MAXSZ_NVRAM_VARS
+#endif /* DL_NVRAM */
+#else
+#define NVRAM_ARRAY_MAXSIZE	ATE_NVRAM_MAXSIZE
+#endif /* ATE_BUILD */
+
+extern uint32 gFWID;
+
+#ifdef BCMFRWDPOOLREORG /* BCMFRWDPOOLREORG support enab macros  */
+	extern bool _bcmfrwdpoolreorg;
+	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+		#define BCMFRWDPOOLREORG_ENAB() (_bcmfrwdpoolreorg)
+	#elif defined(BCMFRWDPOOLREORG_DISABLED)
+		#define BCMFRWDPOOLREORG_ENAB()	(0)
+	#else
+		#define BCMFRWDPOOLREORG_ENAB()	(1)
+	#endif
+#else
+	#define BCMFRWDPOOLREORG_ENAB()		(0)
+#endif /* BCMFRWDPOOLREORG */
+
+#ifdef BCMPOOLRECLAIM /* BCMPOOLRECLAIM support enab macros  */
+	extern bool _bcmpoolreclaim;
+	#if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD)
+		#define BCMPOOLRECLAIM_ENAB() (_bcmpoolreclaim)
+	#elif defined(BCMPOOLRECLAIM_DISABLED)
+		#define BCMPOOLRECLAIM_ENAB()	(0)
+	#else
+		#define BCMPOOLRECLAIM_ENAB()	(1)
+	#endif
+#else
+	#define BCMPOOLRECLAIM_ENAB()		(0)
+#endif /* BCMPOOLRECLAIM */
+
+/* Chip related low power flags (lpflags) */
+
+#ifndef PAD
+#define _PADLINE(line)  pad ## line
+#define _XSTR(line)     _PADLINE(line)
+#define PAD             _XSTR(__LINE__)
+#endif
+
+#ifndef FRAG_HEADROOM
+#define FRAG_HEADROOM	224	/* In absence of SFD, use default headroom of 224 */
+#endif
+
+#ifdef DONGLEBUILD
+#define MODULE_DETACH(var, detach_func)
+#define MODULE_DETACH_TYPECASTED(var, detach_func)
+#else
+#define MODULE_DETACH(var, detach_func)\
+	if (var) { \
+		detach_func(var); \
+		(var) = NULL; \
+	}
+#define MODULE_DETACH_TYPECASTED(var, detach_func) detach_func(var)
+#endif /* DONGLEBUILD */
+
+#endif /* _bcmdefs_h_ */
diff --git a/wl/src/include/bcmdevs.h b/wl/src/include/bcmdevs.h
new file mode 100644
index 0000000..4cb41c2
--- /dev/null
+++ b/wl/src/include/bcmdevs.h
@@ -0,0 +1,1342 @@
+/*
+ * Broadcom device-specific manifest constants.
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmdevs.h 663905 2017-02-16 07:49:38Z $
+ */
+
+#ifndef	_BCMDEVS_H
+#define	_BCMDEVS_H
+
+/* PCI vendor IDs */
+#define	VENDOR_EPIGRAM		0xfeda
+#define	VENDOR_BROADCOM		0x14e4
+#define	VENDOR_3COM		0x10b7
+#define	VENDOR_NETGEAR		0x1385
+#define	VENDOR_DIAMOND		0x1092
+#define	VENDOR_INTEL		0x8086
+#define	VENDOR_DELL		0x1028
+#define	VENDOR_HP		0x103c
+#define	VENDOR_HP_COMPAQ	0x0e11
+#define	VENDOR_APPLE		0x106b
+#define VENDOR_SI_IMAGE		0x1095		/* Silicon Image, used by Arasan SDIO Host */
+#define VENDOR_BUFFALO		0x1154		/* Buffalo vendor id */
+#define VENDOR_TI		0x104c		/* Texas Instruments */
+#define VENDOR_RICOH		0x1180		/* Ricoh */
+#define VENDOR_JMICRON		0x197b
+
+
+/* PCMCIA vendor IDs */
+#define	VENDOR_BROADCOM_PCMCIA	0x02d0
+
+/* SDIO vendor IDs */
+#define	VENDOR_BROADCOM_SDIO	0x00BF
+
+/* DONGLE VID/PIDs */
+#define CY_DNGL_VID		0x04b4
+#define BCM_DNGL_VID		0x0a5c
+#define BCM_DNGL_BL_PID_4328	0xbd12
+#define BCM_DNGL_BL_PID_4322	0xbd13
+#define BCM_DNGL_BL_PID_4319    0xbd16
+#define BCM_DNGL_BL_PID_43236   0xbd17
+#define BCM_DNGL_BL_PID_4332	0xbd18
+#define BCM_DNGL_BL_PID_4330	0xbd19
+#define BCM_DNGL_BL_PID_4334	0xbd1a
+#define BCM_DNGL_BL_PID_43239   0xbd1b
+#define BCM_DNGL_BL_PID_4324	0xbd1c
+#define BCM_DNGL_BL_PID_4360	0xbd1d
+#define BCM_DNGL_BL_PID_43143	0xbd1e
+#define BCM_DNGL_BL_PID_43242	0xbd1f
+#define BCM_DNGL_BL_PID_43342	0xbd21
+#define BCM_DNGL_BL_PID_4335	0xbd20
+#define BCM_DNGL_BL_PID_43341	0xbd22
+#define BCM_DNGL_BL_PID_4350    0xbd23
+#define BCM_DNGL_BL_PID_4345    0xbd24
+#define BCM_DNGL_BL_PID_4349	0xbd25
+#define BCM_DNGL_BL_PID_4354	0xbd26
+#define BCM_DNGL_BL_PID_43569   0xbd27
+#define BCM_DNGL_BL_PID_43909	0xbd28
+#define BCM_DNGL_BL_PID_4373	0xbd29
+
+#define BCM_DNGL_BDC_PID	0x0bdc
+#define BCM_DNGL_JTAG_PID	0x4a44
+
+/* HW USB BLOCK [CPULESS USB] PIDs */
+#define BCM_HWUSB_PID_43239     43239
+
+/* PCI Device IDs */
+#ifdef DEPRECATED /* These products have been deprecated */
+#define	BCM4210_DEVICE_ID	0x1072		/* never used */
+#define	BCM4230_DEVICE_ID	0x1086		/* never used */
+#define	BCM4401_ENET_ID		0x170c		/* 4401b0 production enet cards */
+#define	BCM3352_DEVICE_ID	0x3352		/* bcm3352 device id */
+#define	BCM3360_DEVICE_ID	0x3360		/* bcm3360 device id */
+#define	BCM4211_DEVICE_ID	0x4211
+#define	BCM4231_DEVICE_ID	0x4231
+#define	BCM4303_D11B_ID		0x4303		/* 4303 802.11b */
+#define	BCM4311_D11G_ID		0x4311		/* 4311 802.11b/g id */
+#define	BCM4311_D11DUAL_ID	0x4312		/* 4311 802.11a/b/g id */
+#define	BCM4311_D11A_ID		0x4313		/* 4311 802.11a id */
+#define	BCM4328_D11DUAL_ID	0x4314		/* 4328/4312 802.11a/g id */
+#define	BCM4328_D11G_ID		0x4315		/* 4328/4312 802.11g id */
+#define	BCM4328_D11A_ID		0x4316		/* 4328/4312 802.11a id */
+#define	BCM4318_D11A_ID		0x431a		/* 4318 802.11a id */
+#define	BCM4325_D11DUAL_ID	0x431b		/* 4325 802.11a/g id */
+#define	BCM4325_D11G_ID		0x431c		/* 4325 802.11g id */
+#define	BCM4325_D11A_ID		0x431d		/* 4325 802.11a id */
+#define	BCM4306_UART_ID		0x4322		/* 4306 uart */
+#define	BCM4306_V90_ID		0x4323		/* 4306 v90 codec */
+#define	BCM4306_D11G_ID2	0x4325		/* BCM4306_D11G_ID; INF w/loose binding war */
+#define	BCM4321_D11N_ID		0x4328		/* 4321 802.11n dualband id */
+#define	BCM4321_D11N2G_ID	0x4329		/* 4321 802.11n 2.4Ghz band id */
+#define	BCM4321_D11N5G_ID	0x432a		/* 4321 802.11n 5Ghz band id */
+#define BCM4322_D11N_ID		0x432b		/* 4322 802.11n dualband device */
+#define BCM4322_D11N2G_ID	0x432c		/* 4322 802.11n 2.4GHz device */
+#define BCM4322_D11N5G_ID	0x432d		/* 4322 802.11n 5GHz device */
+#define BCM4329_D11N_ID		0x432e		/* 4329 802.11n dualband device */
+#define BCM4329_D11N2G_ID	0x432f		/* 4329 802.11n 2.4G device */
+#define BCM4329_D11N5G_ID	0x4330		/* 4329 802.11n 5G device */
+#define	BCM4315_D11DUAL_ID	0x4334		/* 4315 802.11a/g id */
+#define	BCM4315_D11G_ID		0x4335		/* 4315 802.11g id */
+#define	BCM4315_D11A_ID		0x4336		/* 4315 802.11a id */
+#define BCM4319_D11N_ID		0x4337		/* 4319 802.11n dualband device */
+#define BCM4319_D11N2G_ID	0x4338		/* 4319 802.11n 2.4G device */
+#define BCM4319_D11N5G_ID	0x4339		/* 4319 802.11n 5G device */
+#define BCM43231_D11N2G_ID	0x4340		/* 43231 802.11n 2.4GHz device */
+#define BCM43221_D11N2G_ID	0x4341		/* 43221 802.11n 2.4GHz device */
+#define BCM43222_D11N_ID	0x4350		/* 43222 802.11n dualband device */
+#define BCM43222_D11N2G_ID	0x4351		/* 43222 802.11n 2.4GHz device */
+#define BCM43222_D11N5G_ID	0x4352		/* 43222 802.11n 5GHz device */
+#define BCM43226_D11N_ID	0x4354		/* 43226 802.11n dualband device */
+#endif /* DEPRECATED */
+/* DEPRECATED but used */
+#define	BCM4306_D11G_ID		0x4320		/* 4306 802.11g */
+#define	BCM4306_D11A_ID		0x4321		/* 4306 802.11a */
+#define	BCM4306_D11DUAL_ID	0x4324		/* 4306 dual A+B */
+#define	BCM4318_D11G_ID		0x4318		/* 4318 802.11b/g id */
+#define	BCM4318_D11DUAL_ID	0x4319		/* 4318 802.11a/b/g id */
+/* DEPRECATED */
+
+#define	BCM53572_D11N2G_ID	0x4329		/* 53572 802.11n 2.4Ghz band id (same as BCM4321) */
+#define BCM43224_D11N_ID	0x4353		/* 43224 802.11n dualband device */
+#define BCM43224_D11N_ID_VEN1	0x0576		/* Vendor specific 43224 802.11n db device */
+#define BCM43236_D11N_ID	0x4346		/* 43236 802.11n dualband device */
+#define BCM43236_D11N2G_ID	0x4347		/* 43236 802.11n 2.4GHz device */
+#define BCM43236_D11N5G_ID	0x4348		/* 43236 802.11n 5GHz device */
+#define BCM43225_D11N2G_ID	0x4357		/* 43225 802.11n 2.4GHz device */
+#define BCM43421_D11N_ID	0xA99D		/* 43421 802.11n dualband device */
+#define BCM4313_D11N2G_ID	0x4727		/* 4313 802.11n 2.4G device */
+#define BCM4330_D11N_ID         0x4360          /* 4330 802.11n dualband device */
+#define BCM4330_D11N2G_ID       0x4361          /* 4330 802.11n 2.4G device */
+#define BCM4330_D11N5G_ID       0x4362          /* 4330 802.11n 5G device */
+#define BCM4336_D11N_ID		0x4343		/* 4336 802.11n 2.4GHz device */
+#define BCM6362_D11N_ID		0x435f		/* 6362 802.11n dualband device */
+#define BCM6362_D11N2G_ID	0x433f		/* 6362 802.11n 2.4Ghz band id */
+#define BCM6362_D11N5G_ID	0x434f		/* 6362 802.11n 5Ghz band id */
+#define BCM4331_D11N_ID		0x4331		/* 4331 802.11n dualband id */
+#define BCM4331_D11N2G_ID	0x4332		/* 4331 802.11n 2.4Ghz band id */
+#define BCM4331_D11N5G_ID	0x4333		/* 4331 802.11n 5Ghz band id */
+#define BCM43237_D11N_ID	0x4355		/* 43237 802.11n dualband device */
+#define BCM43237_D11N5G_ID	0x4356		/* 43237 802.11n 5GHz device */
+#define BCM43227_D11N2G_ID	0x4358		/* 43228 802.11n 2.4GHz device */
+#define BCM43228_D11N_ID	0x4359		/* 43228 802.11n DualBand device */
+#define BCM43228_D11N5G_ID	0x435a		/* 43228 802.11n 5GHz device */
+#define BCM43362_D11N_ID	0x4363		/* 43362 802.11n 2.4GHz device */
+#define BCM43239_D11N_ID	0x4370		/* 43239 802.11n dualband device */
+#define BCM4324_D11N_ID		0x4374		/* 4324 802.11n dualband device */
+#define BCM43217_D11N2G_ID	0x43a9		/* 43217 802.11n 2.4GHz device */
+#define BCM43131_D11N2G_ID	0x43aa		/* 43131 802.11n 2.4GHz device */
+#define BCM4314_D11N2G_ID	0x4364		/* 4314 802.11n 2.4G device */
+#define BCM43142_D11N2G_ID	0x4365		/* 43142 802.11n 2.4G device */
+#define BCM43143_D11N2G_ID	0x4366		/* 43143 802.11n 2.4G device */
+#define BCM4334_D11N_ID		0x4380		/* 4334 802.11n dualband device */
+#define BCM4334_D11N2G_ID	0x4381		/* 4334 802.11n 2.4G device */
+#define BCM4334_D11N5G_ID	0x4382		/* 4334 802.11n 5G device */
+#define BCM43342_D11N_ID	0x4383		/* 43342 802.11n dualband device */
+#define BCM43342_D11N2G_ID	0x4384		/* 43342 802.11n 2.4G device */
+#define BCM43342_D11N5G_ID	0x4385		/* 43342 802.11n 5G device */
+#define BCM43341_D11N_ID	0x4386		/* 43341 802.11n dualband device */
+#define BCM43341_D11N2G_ID	0x4387		/* 43341 802.11n 2.4G device */
+#define BCM43341_D11N5G_ID	0x4388		/* 43341 802.11n 5G device */
+#define BCM4360_D11AC_ID	0x43a0
+#define BCM4360_D11AC2G_ID	0x43a1
+#define BCM4360_D11AC5G_ID	0x43a2
+#define BCM4345_D11AC_ID	0x43ab		/* 4345 802.11ac dualband device */
+#define BCM4345_D11AC2G_ID	0x43ac		/* 4345 802.11ac 2.4G device */
+#define BCM4345_D11AC5G_ID	0x43ad		/* 4345 802.11ac 5G device */
+#define BCM43455_D11AC_ID	0x43e3		/* 43455 802.11ac dualband device */
+#define BCM43455_D11AC2G_ID	0x43e4		/* 43455 802.11ac 2.4G device */
+#define BCM43455_D11AC5G_ID	0x43e5		/* 43455 802.11ac 5G device */
+#define BCM4335_D11AC_ID	0x43ae
+#define BCM4335_D11AC2G_ID	0x43af
+#define BCM4335_D11AC5G_ID	0x43b0
+#define BCM4352_D11AC_ID	0x43b1		/* 4352 802.11ac dualband device */
+#define BCM4352_D11AC2G_ID	0x43b2		/* 4352 802.11ac 2.4G device */
+#define BCM4352_D11AC5G_ID	0x43b3		/* 4352 802.11ac 5G device */
+#define BCM43602_D11AC_ID	0x43ba		/* ac dualband PCI devid SPROM programmed */
+#define BCM43602_D11AC2G_ID	0x43bb		/* 43602 802.11ac 2.4G device */
+#define BCM43602_D11AC5G_ID	0x43bc		/* 43602 802.11ac 5G device */
+#define BCM4349_D11AC_ID	0x4349		/* 4349 802.11ac dualband device */
+#define BCM4349_D11AC2G_ID	0x43dd		/* 4349 802.11ac 2.4G device */
+#define BCM4349_D11AC5G_ID	0x43de		/* 4349 802.11ac 5G device */
+#define BCM53573_D11AC_ID	0x43b4		/* 53573 802.11ac dualband device */
+#define BCM53573_D11AC2G_ID	0x43b5		/* 53573 802.11ac 2.4G device */
+#define BCM53573_D11AC5G_ID	0x43b6		/* 53573 802.11ac 5G device */
+#define BCM47189_D11AC_ID	0x43c6		/* 47189 802.11ac dualband device */
+#define BCM47189_D11AC2G_ID	0x43c7		/* 47189 802.11ac 2.4G device */
+#define BCM47189_D11AC5G_ID	0x43c8		/* 47189 802.11ac 5G device */
+#define BCM4355_D11AC_ID	0x43dc		/* 4355 802.11ac dualband device */
+#define BCM4355_D11AC2G_ID	0x43fc		/* 4355 802.11ac 2.4G device */
+#define BCM4355_D11AC5G_ID	0x43fd		/* 4355 802.11ac 5G device */
+#define BCM4359_D11AC_ID	0x43ef		/* 4359 802.11ac dualband device */
+#define BCM4359_D11AC2G_ID	0x43fe		/* 4359 802.11ac 2.4G device */
+#define BCM4359_D11AC5G_ID	0x43ff		/* 4359 802.11ac 5G device */
+#define BCM43596_D11AC_ID	0x4415		/* 43596 802.11ac dualband device */
+#define BCM43596_D11AC2G_ID	0x4416		/* 43596 802.11ac 2.4G device */
+#define BCM43596_D11AC5G_ID	0x4417		/* 43596 802.11ac 5G device */
+#define BCM43597_D11AC_ID	0x441c		/* 43597 802.11ac dualband device */
+#define BCM43597_D11AC2G_ID	0x441d		/* 43597 802.11ac 2.4G device */
+#define BCM43597_D11AC5G_ID	0x441e		/* 43597 802.11ac 5G device */
+#define BCM43909_D11AC_ID	0x43d0		/* 43909 802.11ac dualband device */
+#define BCM43909_D11AC2G_ID	0x43d1		/* 43909 802.11ac 2.4G device */
+#define BCM43909_D11AC5G_ID	0x43d2		/* 43909 802.11ac 5G device */
+#define BCM43012_D11N_ID	0xA804		/* 43012 802.11n dualband device */
+#define BCM43012_D11N2G_ID	0xA805		/* 43012 802.11n 2.4G device */
+#define BCM43012_D11N5G_ID	0xA806		/* 43012 802.11n 5G device */
+
+/* PCI Subsystem ID */
+#define BCM943228HMB_SSID_VEN1	0x0607
+#define BCM94313HMGBL_SSID_VEN1	0x0608
+#define BCM94313HMG_SSID_VEN1	0x0609
+#define BCM943142HM_SSID_VEN1	0x0611
+
+#define BCM43143_D11N2G_ID	0x4366		/* 43143 802.11n 2.4G device */
+
+#define BCM43242_D11N_ID	0x4367		/* 43242 802.11n dualband device */
+#define BCM43242_D11N2G_ID	0x4368		/* 43242 802.11n 2.4G device */
+#define BCM43242_D11N5G_ID	0x4369		/* 43242 802.11n 5G device */
+
+#define BCM4350_D11AC_ID	0x43a3
+#define BCM4350_D11AC2G_ID	0x43a4
+#define BCM4350_D11AC5G_ID	0x43a5
+
+#define BCM43556_D11AC_ID	0x43b7
+#define BCM43556_D11AC2G_ID	0x43b8
+#define BCM43556_D11AC5G_ID	0x43b9
+
+#define BCM43558_D11AC_ID	0x43c0
+#define BCM43558_D11AC2G_ID	0x43c1
+#define BCM43558_D11AC5G_ID	0x43c2
+
+#define BCM43566_D11AC_ID	0x43d3
+#define BCM43566_D11AC2G_ID	0x43d4
+#define BCM43566_D11AC5G_ID	0x43d5
+
+#define BCM43568_D11AC_ID	0x43d6
+#define BCM43568_D11AC2G_ID	0x43d7
+#define BCM43568_D11AC5G_ID	0x43d8
+
+#define BCM43569_D11AC_ID	0x43d9
+#define BCM43569_D11AC2G_ID	0x43da
+#define BCM43569_D11AC5G_ID	0x43db
+
+#define BCM43570_D11AC_ID	0x43d9
+#define BCM43570_D11AC2G_ID	0x43da
+#define BCM43570_D11AC5G_ID	0x43db
+
+#define BCM4354_D11AC_ID	0x43df		/* 4354 802.11ac dualband device */
+#define BCM4354_D11AC2G_ID	0x43e0		/* 4354 802.11ac 2.4G device */
+#define BCM4354_D11AC5G_ID	0x43e1		/* 4354 802.11ac 5G device */
+#define BCM43430_D11N2G_ID	0x43e2		/* 43430 802.11n 2.4G device */
+#define BCM43018_D11N2G_ID	0x441b		/* 43018 802.11n 2.4G device */
+
+
+#define BCM4347_D11AC_ID	0x440a		/* 4347 802.11ac dualband device */
+#define BCM4347_D11AC2G_ID	0x440b		/* 4347 802.11ac 2.4G device */
+#define BCM4347_D11AC5G_ID	0x440c		/* 4347 802.11ac 5G device */
+
+#define BCM4361_D11AC_ID	0x441f		/* 4361 802.11ac dualband device */
+#define BCM4361_D11AC2G_ID	0x4420		/* 4361 802.11ac 2.4G device */
+#define BCM4361_D11AC5G_ID	0x4421		/* 4361 802.11ac 5G device */
+
+#define BCM4364_D11AC_ID	0x4464		/* 4364 802.11ac dualband device */
+#define BCM4364_D11AC2G_ID	0x446a		/* 4364 802.11ac 2.4G device */
+#define BCM4364_D11AC5G_ID	0x446b		/* 4364 802.11ac 5G device */
+
+
+#define BCM4365_D11AC_ID	0x43ca
+#define BCM4365_D11AC2G_ID	0x43cb
+#define BCM4365_D11AC5G_ID	0x43cc
+
+#define BCM4366_D11AC_ID	0x43c3
+#define BCM4366_D11AC2G_ID	0x43c4
+#define BCM4366_D11AC5G_ID	0x43c5
+
+/* TBD change below values */
+#define BCM4369_D11AC_ID	0x4470		/* 4369 802.11ac dualband device */
+#define BCM4369_D11AC2G_ID	0x4471		/* 4369 802.11ac 2.4G device */
+#define BCM4369_D11AC5G_ID	0x4472		/* 4369 802.11ac 5G device */
+
+
+#define BCM43349_D11N_ID	0x43e6		/* 43349 802.11n dualband id */
+#define BCM43349_D11N2G_ID	0x43e7		/* 43349 802.11n 2.4Ghz band id */
+#define BCM43349_D11N5G_ID	0x43e8		/* 43349 802.11n 5Ghz band id */
+
+#define BCM4358_D11AC_ID        0x43e9          /* 4358 802.11ac dualband device */
+#define BCM4358_D11AC2G_ID      0x43ea          /* 4358 802.11ac 2.4G device */
+#define BCM4358_D11AC5G_ID      0x43eb          /* 4358 802.11ac 5G device */
+
+#define BCM4356_D11AC_ID	0x43ec		/* 4356 802.11ac dualband device */
+#define BCM4356_D11AC2G_ID	0x43ed		/* 4356 802.11ac 2.4G device */
+#define BCM4356_D11AC5G_ID	0x43ee		/* 4356 802.11ac 5G device */
+
+#define BCM4371_D11AC_ID	0x440d		/* 4371 802.11ac dualband device */
+#define BCM4371_D11AC2G_ID	0x440e		/* 4371 802.11ac 2.4G device */
+#define BCM4371_D11AC5G_ID	0x440f		/* 4371 802.11ac 5G device */
+#define BCM7271_D11AC_ID	0x4410		/* 7271 802.11ac dualband device */
+#define BCM7271_D11AC2G_ID	0x4411		/* 7271 802.11ac 2.4G device */
+#define BCM7271_D11AC5G_ID	0x4412		/* 7271 802.11ac 5G device */
+
+#define BCM4373_D11AC_ID	0x4418          /* 4373 802.11ac dualband device */
+#define BCM4373_D11AC2G_ID	0x4419          /* 4373 802.11ac 2.4G device */
+#define BCM4373_D11AC5G_ID	0x441a          /* 4373 802.11ac 5G device */
+
+#define	BCMGPRS_UART_ID		0x4333		/* Uart id used by 4306/gprs card */
+#define	BCMGPRS2_UART_ID	0x4344		/* Uart id used by 4306/gprs card */
+#define FPGA_JTAGM_ID		0x43f0		/* FPGA jtagm device id */
+#define BCM_JTAGM_ID		0x43f1		/* BCM jtagm device id */
+#define SDIOH_FPGA_ID		0x43f2		/* sdio host fpga */
+#define BCM_SDIOH_ID		0x43f3		/* BCM sdio host id */
+#define SDIOD_FPGA_ID		0x43f4		/* sdio device fpga */
+#define SPIH_FPGA_ID		0x43f5		/* PCI SPI Host Controller FPGA */
+#define BCM_SPIH_ID		0x43f6		/* Synopsis SPI Host Controller */
+#define MIMO_FPGA_ID		0x43f8		/* FPGA mimo minimacphy device id */
+#define BCM_JTAGM2_ID		0x43f9		/* BCM alternate jtagm device id */
+#define SDHCI_FPGA_ID		0x43fa		/* Standard SDIO Host Controller FPGA */
+#define	BCM4402_ENET_ID		0x4402		/* 4402 enet */
+#define	BCM4402_V90_ID		0x4403		/* 4402 v90 codec */
+#define	BCM4410_DEVICE_ID	0x4410		/* bcm44xx family pci iline */
+#define	BCM4412_DEVICE_ID	0x4412		/* bcm44xx family pci enet */
+#define	BCM4430_DEVICE_ID	0x4430		/* bcm44xx family cardbus iline */
+#define	BCM4432_DEVICE_ID	0x4432		/* bcm44xx family cardbus enet */
+#define	BCM4704_ENET_ID		0x4706		/* 4704 enet (Use 47XX_ENET_ID instead!) */
+#define	BCM4710_DEVICE_ID	0x4710		/* 4710 primary function 0 */
+#define	BCM47XX_AUDIO_ID	0x4711		/* 47xx audio codec */
+#define	BCM47XX_V90_ID		0x4712		/* 47xx v90 codec */
+#define	BCM47XX_ENET_ID		0x4713		/* 47xx enet */
+#define	BCM47XX_EXT_ID		0x4714		/* 47xx external i/f */
+#define	BCM47XX_GMAC_ID		0x4715		/* 47xx Unimac based GbE */
+#define	BCM47XX_USBH_ID		0x4716		/* 47xx usb host */
+#define	BCM47XX_USBD_ID		0x4717		/* 47xx usb device */
+#define	BCM47XX_IPSEC_ID	0x4718		/* 47xx ipsec */
+#define	BCM47XX_ROBO_ID		0x4719		/* 47xx/53xx roboswitch core */
+#define	BCM47XX_USB20H_ID	0x471a		/* 47xx usb 2.0 host */
+#define	BCM47XX_USB20D_ID	0x471b		/* 47xx usb 2.0 device */
+#define	BCM47XX_ATA100_ID	0x471d		/* 47xx parallel ATA */
+#define	BCM47XX_SATAXOR_ID	0x471e		/* 47xx serial ATA & XOR DMA */
+#define	BCM47XX_GIGETH_ID	0x471f		/* 47xx GbE (5700) */
+#ifdef DEPRECATED /* These products have been deprecated */
+#define	BCM4712_MIPS_ID		0x4720		/* 4712 base devid */
+#define	BCM4716_DEVICE_ID	0x4722		/* 4716 base devid */
+#endif /* DEPRECATED */
+#define	BCM47XX_USB30H_ID	0x472a		/* 47xx usb 3.0 host */
+#define	BCM47XX_USB30D_ID	0x472b		/* 47xx usb 3.0 device */
+#define	BCM47XX_USBHUB_ID	0x472c		/* 47xx usb hub */
+#define BCM47XX_SMBUS_EMU_ID	0x47fe		/* 47xx emulated SMBus device */
+#define	BCM47XX_XOR_EMU_ID	0x47ff		/* 47xx emulated XOR engine */
+#define	EPI41210_DEVICE_ID	0xa0fa		/* bcm4210 */
+#define	EPI41230_DEVICE_ID	0xa10e		/* bcm4230 */
+#define JINVANI_SDIOH_ID	0x4743		/* Jinvani SDIO Gold Host */
+#define BCM27XX_SDIOH_ID	0x2702		/* BCM27xx Standard SDIO Host */
+#define PCIXX21_FLASHMEDIA_ID	0x803b		/* TI PCI xx21 Standard Host Controller */
+#define PCIXX21_SDIOH_ID	0x803c		/* TI PCI xx21 Standard Host Controller */
+#define R5C822_SDIOH_ID		0x0822		/* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host */
+#define JMICRON_SDIOH_ID	0x2381		/* JMicron Standard SDIO Host Controller */
+
+#define BCM43452_D11AC_ID	0x47ab		/* 43452 802.11ac dualband device */
+#define BCM43452_D11AC2G_ID	0x47ac		/* 43452 802.11ac 2.4G device */
+#define BCM43452_D11AC5G_ID	0x47ad		/* 43452 802.11ac 5G device */
+
+/* Chip IDs */
+#ifdef DEPRECATED /* These products have been deprecated */
+#define	BCM4306_CHIP_ID		0x4306		/* 4306 chipcommon chipid */
+#define	BCM4311_CHIP_ID		0x4311		/* 4311 PCIe 802.11a/b/g */
+#define	BCM43111_CHIP_ID	43111		/* 43111 chipcommon chipid (OTP chipid) */
+#define	BCM43112_CHIP_ID	43112		/* 43112 chipcommon chipid (OTP chipid) */
+#define	BCM4312_CHIP_ID		0x4312		/* 4312 chipcommon chipid */
+#define	BCM4315_CHIP_ID		0x4315		/* 4315 chip id */
+#define	BCM4318_CHIP_ID		0x4318		/* 4318 chipcommon chipid */
+#define	BCM4319_CHIP_ID		0x4319		/* 4319 chip id */
+#define	BCM4320_CHIP_ID		0x4320		/* 4320 chipcommon chipid */
+#define	BCM4321_CHIP_ID		0x4321		/* 4321 chipcommon chipid */
+#define	BCM4322_CHIP_ID		0x4322		/* 4322 chipcommon chipid */
+#define	BCM43221_CHIP_ID	43221		/* 43221 chipcommon chipid (OTP chipid) */
+#define	BCM43222_CHIP_ID	43222		/* 43222 chipcommon chipid */
+#define	BCM43226_CHIP_ID	43226		/* 43226 chipcommon chipid */
+#define	BCM43231_CHIP_ID	43231		/* 43231 chipcommon chipid (OTP chipid) */
+#define	BCM4342_CHIP_ID		4342		/* 4342 chipcommon chipid (OTP, RBBU) */
+#define	BCM4325_CHIP_ID		0x4325		/* 4325 chip id */
+#define	BCM4328_CHIP_ID		0x4328		/* 4328 chip id */
+#define	BCM4329_CHIP_ID		0x4329		/* 4329 chipcommon chipid */
+#define	BCM4712_CHIP_ID		0x4712		/* 4712 chipcommon chipid */
+#endif /* DEPRECATED */
+
+/* DEPRECATED but still referenced in components - start */
+#define	BCM4716_CHIP_ID		0x4716		/* 4716 chipcommon chipid */
+#define	BCM4748_CHIP_ID		0x4748		/* 4716 chipcommon chipid (OTP, RBBU) */
+#define	BCM47162_CHIP_ID	47162		/* 47162 chipcommon chipid */
+#define	BCM5354_CHIP_ID		0x5354		/* 5354 chipcommon chipid */
+/* DEPRECATED but still referenced in components - end */
+
+#define	BCM43224_CHIP_ID	43224		/* 43224 chipcommon chipid */
+#define	BCM43225_CHIP_ID	43225		/* 43225 chipcommon chipid */
+#define	BCM43227_CHIP_ID	43227		/* 43227 chipcommon chipid */
+#define	BCM43228_CHIP_ID	43228		/* 43228 chipcommon chipid */
+#define	BCM43217_CHIP_ID	43217		/* 43217 chip id (OTP chipid) */
+#define BCM4313_CHIP_ID		0x4313		/* 4313 chip id */
+#define	BCM43131_CHIP_ID	43131		/* 43131 chip id (OTP chipid) */
+#define	BCM43234_CHIP_ID	43234		/* 43234 chipcommon chipid */
+#define	BCM43235_CHIP_ID	43235		/* 43235 chipcommon chipid */
+#define	BCM43236_CHIP_ID	43236		/* 43236 chipcommon chipid */
+#define	BCM43237_CHIP_ID	43237		/* 43237 chipcommon chipid */
+#define	BCM43238_CHIP_ID	43238		/* 43238 chipcommon chipid */
+#define	BCM43239_CHIP_ID	43239		/* 43239 chipcommon chipid */
+#define	BCM43420_CHIP_ID	43420		/* 43222 chipcommon chipid (OTP, RBBU) */
+#define	BCM43421_CHIP_ID	43421		/* 43224 chipcommon chipid (OTP, RBBU) */
+#define	BCM43428_CHIP_ID	43428		/* 43228 chipcommon chipid (OTP, RBBU) */
+#define	BCM43431_CHIP_ID	43431		/* 4331  chipcommon chipid (OTP, RBBU) */
+#define	BCM43460_CHIP_ID	43460		/* 4360  chipcommon chipid (OTP, RBBU) */
+#define	BCM43465_CHIP_ID	43465		/* 4366  chipcommon chipid (OTP, RBBU) */
+#define	BCM43525_CHIP_ID	43525		/* 4365  chipcommon chipid (OTP, RBBU) */
+#define	BCM47452_CHIP_ID	47452		/* 53573 chipcommon chipid (OTP, RBBU) */
+#define	BCM4331_CHIP_ID		0x4331		/* 4331 chipcommon chipid */
+#define BCM4336_CHIP_ID		0x4336		/* 4336 chipcommon chipid */
+#define BCM43362_CHIP_ID	43362		/* 43362 chipcommon chipid */
+#define BCM4330_CHIP_ID		0x4330		/* 4330 chipcommon chipid */
+#define BCM6362_CHIP_ID		0x6362		/* 6362 chipcommon chipid */
+#define BCM4314_CHIP_ID		0x4314		/* 4314 chipcommon chipid */
+#define BCM43142_CHIP_ID	43142		/* 43142 chipcommon chipid */
+#define BCM43143_CHIP_ID	43143		/* 43143 chipcommon chipid */
+#define	BCM4324_CHIP_ID		0x4324		/* 4324 chipcommon chipid */
+#define	BCM43242_CHIP_ID	43242		/* 43242 chipcommon chipid */
+#define	BCM43243_CHIP_ID	43243		/* 43243 chipcommon chipid */
+#define BCM4334_CHIP_ID		0x4334		/* 4334 chipcommon chipid */
+#define BCM4335_CHIP_ID		0x4335		/* 4335 chipcommon chipid */
+#define BCM4339_CHIP_ID		0x4339		/* 4339 chipcommon chipid */
+#define BCM43349_CHIP_ID	43349			/* 43349(0xA955) chipcommon chipid */
+#define BCM4360_CHIP_ID		0x4360          /* 4360 chipcommon chipid */
+#define BCM4364_CHIP_ID		0x4364			/* 4364 chipcommon chipid */
+#define BCM4352_CHIP_ID		0x4352          /* 4352 chipcommon chipid */
+#define BCM43526_CHIP_ID	0xAA06
+#define BCM43340_CHIP_ID	43340		/* 43340 chipcommon chipid */
+#define BCM43341_CHIP_ID	43341		/* 43341 chipcommon chipid */
+#define BCM43342_CHIP_ID	43342		/* 43342 chipcommon chipid */
+#define BCM4350_CHIP_ID		0x4350          /* 4350 chipcommon chipid */
+#define BCM4354_CHIP_ID		0x4354          /* 4354 chipcommon chipid */
+#define BCM4356_CHIP_ID		0x4356          /* 4356 chipcommon chipid */
+#define BCM4371_CHIP_ID		0x4371          /* 4371 chipcommon chipid */
+#define BCM43556_CHIP_ID	0xAA24          /* 43556 chipcommon chipid */
+#define BCM43558_CHIP_ID	0xAA26          /* 43558 chipcommon chipid */
+#define BCM43562_CHIP_ID	0xAA2A		/* 43562 chipcommon chipid */
+#define BCM43566_CHIP_ID	0xAA2E          /* 43566 chipcommon chipid */
+#define BCM43567_CHIP_ID	0xAA2F          /* 43567 chipcommon chipid */
+#define BCM43568_CHIP_ID	0xAA30          /* 43568 chipcommon chipid */
+#define BCM43569_CHIP_ID	0xAA31          /* 43569 chipcommon chipid */
+#define BCM43570_CHIP_ID	0xAA32          /* 43570 chipcommon chipid */
+#define BCM4358_CHIP_ID		0x4358          /* 4358 chipcommon chipid */
+#define	BCM43012_CHIP_ID	0xA804			/* 43012 chipcommon chipid */
+#define BCM4350_CHIP(chipid)	((CHIPID(chipid) == BCM4350_CHIP_ID) || \
+				(CHIPID(chipid) == BCM4354_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43556_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43558_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43566_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43567_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43568_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43569_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43570_CHIP_ID) || \
+				(CHIPID(chipid) == BCM4358_CHIP_ID)) /* 4350 variations */
+
+#define BCM4345_CHIP_ID		0x4345		/* 4345 chipcommon chipid */
+#define BCM43454_CHIP_ID	43454		/* 43454 chipcommon chipid */
+#define BCM43455_CHIP_ID	43455		/* 43455 chipcommon chipid */
+#define BCM43457_CHIP_ID	43457		/* 43457 chipcommon chipid */
+#define BCM43458_CHIP_ID	43458		/* 43458 chipcommon chipid */
+
+#define BCM4345_CHIP(chipid)	(CHIPID(chipid) == BCM4345_CHIP_ID || \
+				 CHIPID(chipid) == BCM43454_CHIP_ID || \
+				 CHIPID(chipid) == BCM43455_CHIP_ID || \
+				 CHIPID(chipid) == BCM43457_CHIP_ID || \
+				 CHIPID(chipid) == BCM43458_CHIP_ID)
+
+#define CASE_BCM4345_CHIP	case BCM4345_CHIP_ID: /* fallthrough */ \
+				case BCM43454_CHIP_ID: /* fallthrough */ \
+				case BCM43455_CHIP_ID: /* fallthrough */ \
+				case BCM43457_CHIP_ID: /* fallthrough */ \
+				case BCM43458_CHIP_ID
+
+#define BCM43430_CHIP_ID	43430		/* 43430 chipcommon chipid */
+#define BCM43018_CHIP_ID	43018		/* 43018 chipcommon chipid */
+#define BCM4349_CHIP_ID		0x4349		/* 4349 chipcommon chipid */
+#define BCM4355_CHIP_ID		0x4355		/* 4355 chipcommon chipid */
+#define BCM4359_CHIP_ID		0x4359		/* 4359 chipcommon chipid */
+#define BCM4349_CHIP(chipid)	((CHIPID(chipid) == BCM4349_CHIP_ID) || \
+				(CHIPID(chipid) == BCM4355_CHIP_ID) || \
+				(CHIPID(chipid) == BCM4359_CHIP_ID))
+#define BCM4349_CHIP_GRPID		BCM4349_CHIP_ID: \
+					case BCM4355_CHIP_ID: \
+					case BCM4359_CHIP_ID
+#define BCM43596_CHIP_ID		43596		/* 43596 chipcommon chipid */
+
+
+#define BCM4347_CHIP_ID		0x4347          /* 4347 chipcommon chipid */
+#define BCM4357_CHIP_ID		0x4357          /* 4357 chipcommon chipid */
+#define BCM4361_CHIP_ID		0x4361          /* 4361 chipcommon chipid */
+#define BCM4369_CHIP_ID		0x4369          /* 436/ chipcommon chipid */
+#define BCM4347_CHIP(chipid)	((CHIPID(chipid) == BCM4347_CHIP_ID) || \
+				(CHIPID(chipid) == BCM4357_CHIP_ID) || \
+				(CHIPID(chipid) == BCM4361_CHIP_ID))
+#define BCM4347_CHIP_GRPID		BCM4347_CHIP_ID: \
+					case BCM4357_CHIP_ID: \
+					case BCM4361_CHIP_ID
+
+#define BCM4365_CHIP_ID		0x4365		/* 4365 chipcommon chipid */
+#define BCM4366_CHIP_ID		0x4366		/* 4366 chipcommon chipid */
+#define BCM43664_CHIP_ID	43664		/* 4366E chipcommon chipid */
+#define BCM43666_CHIP_ID	43666		/* 4365E chipcommon chipid */
+#define BCM4365_CHIP(chipid)	((CHIPID(chipid) == BCM4365_CHIP_ID) || \
+				(CHIPID(chipid) == BCM4366_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43664_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43666_CHIP_ID))
+#define CASE_BCM4365_CHIP	case BCM4365_CHIP_ID: /* fallthrough */ \
+				case BCM4366_CHIP_ID: /* fallthrough */ \
+				case BCM43664_CHIP_ID: /* fallthrough */ \
+				case BCM43666_CHIP_ID
+
+#define BCM43909_CHIP_ID	0xab85		/* 43909 chipcommon chipid */
+
+#define BCM43602_CHIP_ID	0xaa52		/* 43602 chipcommon chipid */
+#define BCM43462_CHIP_ID	0xa9c6		/* 43462 chipcommon chipid */
+#define BCM43522_CHIP_ID	0xaa02		/* 43522 chipcommon chipid */
+#define BCM43602_CHIP(chipid)	((CHIPID(chipid) == BCM43602_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43462_CHIP_ID) || \
+				(CHIPID(chipid) == BCM43522_CHIP_ID)) /* 43602 variations */
+#define BCM43012_CHIP(chipid)	(CHIPID(chipid) == BCM43012_CHIP_ID)
+#define CASE_BCM43602_CHIP		case BCM43602_CHIP_ID: /* fallthrough */ \
+				case BCM43462_CHIP_ID: /* fallthrough */ \
+				case BCM43522_CHIP_ID
+
+#define	BCM4402_CHIP_ID		0x4402		/* 4402 chipid */
+#define	BCM4704_CHIP_ID		0x4704		/* 4704 chipcommon chipid */
+#define	BCM4706_CHIP_ID		0x5300		/* 4706 chipcommon chipid */
+#define BCM4707_CHIP_ID		53010		/* 4707 chipcommon chipid */
+#define BCM47094_CHIP_ID	53030		/* 47094 chipcommon chipid */
+#define BCM53018_CHIP_ID	53018		/* 53018 chipcommon chipid */
+#define BCM4707_CHIP(chipid)	(((chipid) == BCM4707_CHIP_ID) || \
+				((chipid) == BCM53018_CHIP_ID) || \
+				((chipid) == BCM47094_CHIP_ID))
+#define	BCM4710_CHIP_ID		0x4710		/* 4710 chipid */
+#define	BCM4749_CHIP_ID		0x4749		/* 5357 chipcommon chipid (OTP, RBBU) */
+#define BCM4785_CHIP_ID		0x4785		/* 4785 chipcommon chipid */
+#define	BCM5350_CHIP_ID		0x5350		/* 5350 chipcommon chipid */
+#define	BCM5352_CHIP_ID		0x5352		/* 5352 chipcommon chipid */
+#define BCM5365_CHIP_ID		0x5365		/* 5365 chipcommon chipid */
+#define	BCM5356_CHIP_ID		0x5356		/* 5356 chipcommon chipid */
+#define	BCM5357_CHIP_ID		0x5357		/* 5357 chipcommon chipid */
+#define	BCM53572_CHIP_ID	53572		/* 53572 chipcommon chipid */
+#define	BCM53573_CHIP_ID	53573		/* 53573 chipcommon chipid */
+#define	BCM53574_CHIP_ID	53574		/* 53574 chipcommon chipid */
+#define BCM53573_CHIP(chipid)	((CHIPID(chipid) == BCM53573_CHIP_ID) || \
+				(CHIPID(chipid) == BCM53574_CHIP_ID) || \
+				(CHIPID(chipid) == BCM47452_CHIP_ID))
+#define BCM53573_CHIP_GRPID	BCM53573_CHIP_ID : \
+				case BCM53574_CHIP_ID : \
+				case BCM47452_CHIP_ID
+#define BCM53573_DEVICE(devid)	(((devid) == BCM53573_D11AC_ID) || \
+				((devid) == BCM53573_D11AC2G_ID) || \
+				((devid) == BCM53573_D11AC5G_ID) || \
+				((devid) == BCM47189_D11AC_ID) || \
+				((devid) == BCM47189_D11AC2G_ID) || \
+				((devid) == BCM47189_D11AC5G_ID))
+
+#define	BCM7271_CHIP_ID		0x05c9		/* 7271 chipcommon chipid */
+#define BCM7271_CHIP(chipid)	((CHIPID(chipid) == BCM7271_CHIP_ID))
+
+#define	BCM4373_CHIP_ID		0x4373		/* 4373 chipcommon chipid */
+
+/* Package IDs */
+#ifdef DEPRECATED /* These products have been deprecated */
+#define	BCM4303_PKG_ID		2		/* 4303 package id */
+#define	BCM4309_PKG_ID		1		/* 4309 package id */
+#define	BCM4712LARGE_PKG_ID	0		/* 340pin 4712 package id */
+#define	BCM4712SMALL_PKG_ID	1		/* 200pin 4712 package id */
+#define	BCM4712MID_PKG_ID	2		/* 225pin 4712 package id */
+#define BCM4328USBD11G_PKG_ID	2		/* 4328 802.11g USB package id */
+#define BCM4328USBDUAL_PKG_ID	3		/* 4328 802.11a/g USB package id */
+#define BCM4328SDIOD11G_PKG_ID	4		/* 4328 802.11g SDIO package id */
+#define BCM4328SDIODUAL_PKG_ID	5		/* 4328 802.11a/g SDIO package id */
+#define BCM4329_289PIN_PKG_ID	0		/* 4329 289-pin package id */
+#define BCM4329_182PIN_PKG_ID	1		/* 4329N 182-pin package id */
+#define BCM5354E_PKG_ID		1		/* 5354E package id */
+#define	BCM4716_PKG_ID		8		/* 4716 package id */
+#define	BCM4717_PKG_ID		9		/* 4717 package id */
+#define	BCM4718_PKG_ID		10		/* 4718 package id */
+#endif  /* DEPRECATED */
+#define BCM5356_PKG_NONMODE	1		/* 5356 package without nmode suppport */
+#define BCM5358U_PKG_ID		8		/* 5358U package id */
+#define BCM5358_PKG_ID		9		/* 5358 package id */
+#define BCM47186_PKG_ID		10		/* 47186 package id */
+#define BCM5357_PKG_ID		11		/* 5357 package id */
+#define BCM5356U_PKG_ID		12		/* 5356U package id */
+#define BCM53572_PKG_ID		8		/* 53572 package id */
+#define BCM5357C0_PKG_ID	8		/* 5357c0 package id (the same as 53572) */
+#define BCM47188_PKG_ID		9		/* 47188 package id */
+#define BCM5358C0_PKG_ID	0xa		/* 5358c0 package id */
+#define BCM5356C0_PKG_ID	0xb		/* 5356c0 package id */
+#define BCM4331TT_PKG_ID        8		/* 4331 12x12 package id */
+#define BCM4331TN_PKG_ID        9		/* 4331 12x9 package id */
+#define BCM4331TNA0_PKG_ID     0xb		/* 4331 12x9 package id */
+#define BCM47189_PKG_ID		1		/* 47189 package id */
+#define BCM53573_PKG_ID		0		/* 53573 package id */
+#define	BCM4706L_PKG_ID		1		/* 4706L package id */
+
+#define HDLSIM5350_PKG_ID	1		/* HDL simulator package id for a 5350 */
+#define HDLSIM_PKG_ID		14		/* HDL simulator package id */
+#define HWSIM_PKG_ID		15		/* Hardware simulator package id */
+#define BCM43224_FAB_CSM	0x8		/* the chip is manufactured by CSM */
+#define BCM43224_FAB_SMIC	0xa		/* the chip is manufactured by SMIC */
+#define BCM4336_WLBGA_PKG_ID	0x8
+#define BCM4330_WLBGA_PKG_ID	0x0
+#define BCM4314PCIE_ARM_PKG_ID		(8 | 0)	/* 4314 QFN PCI package id, bit 3 tie high */
+#define BCM4314SDIO_PKG_ID		(8 | 1)	/* 4314 QFN SDIO package id */
+#define BCM4314PCIE_PKG_ID		(8 | 2)	/* 4314 QFN PCI (ARM-less) package id */
+#define BCM4314SDIO_ARM_PKG_ID		(8 | 3)	/* 4314 QFN SDIO (ARM-less) package id */
+#define BCM4314SDIO_FPBGA_PKG_ID	(8 | 4)	/* 4314 FpBGA SDIO package id */
+#define BCM4314DEV_PKG_ID		(8 | 6)	/* 4314 Developement package id */
+
+#define BCM4707_PKG_ID		1		/* 4707 package id */
+#define BCM4708_PKG_ID		2		/* 4708 package id */
+#define BCM4709_PKG_ID		0		/* 4709 package id */
+
+#define PCIXX21_FLASHMEDIA0_ID	0x8033		/* TI PCI xx21 Standard Host Controller */
+#define PCIXX21_SDIOH0_ID	0x8034		/* TI PCI xx21 Standard Host Controller */
+
+#define BCM4335_WLCSP_PKG_ID	(0x0)	/* WLCSP Module/Mobile SDIO/HSIC. */
+#define BCM4335_FCBGA_PKG_ID	(0x1)	/* FCBGA PC/Embeded/Media PCIE/SDIO */
+#define BCM4335_WLBGA_PKG_ID	(0x2)	/* WLBGA COB/Mobile SDIO/HSIC. */
+#define BCM4335_FCBGAD_PKG_ID	(0x3)	/* FCBGA Debug Debug/Dev All if's. */
+#define BCM4335_PKG_MASK	(0x3)
+#define BCM43602_12x12_PKG_ID	(0x1)	/* 12x12 pins package, used for e.g. router designs */
+
+
+/* boardflags */
+#define	BFL_BTC2WIRE		0x00000001  /* old 2wire Bluetooth coexistence, OBSOLETE */
+#define BFL_BTCOEX      0x00000001      /* Board supports BTCOEX */
+#define	BFL_PACTRL		0x00000002  /* Board has gpio 9 controlling the PA */
+#define BFL_AIRLINEMODE	0x00000004  /* Board implements gpio radio disable indication */
+#define	BFL_ADCDIV		0x00000008  /* Board has the rssi ADC divider */
+#define BFL_DIS_256QAM		0x00000008
+#define	BFL_ENETROBO		0x00000010  /* Board has robo switch or core */
+#define	BFL_TSSIAVG   		0x00000010  /* TSSI averaging for ACPHY chips */
+#define	BFL_NOPLLDOWN		0x00000020  /* Not ok to power down the chip pll and oscillator */
+#define	BFL_CCKHIPWR		0x00000040  /* Can do high-power CCK transmission */
+#define	BFL_ENETADM		0x00000080  /* Board has ADMtek switch */
+#define	BFL_ENETVLAN		0x00000100  /* Board has VLAN capability */
+#define	BFL_LTECOEX		0x00000200  /* LTE Coex enabled */
+#define BFL_NOPCI		0x00000400  /* Board leaves PCI floating */
+#define BFL_FEM			0x00000800  /* Board supports the Front End Module */
+#define BFL_EXTLNA		0x00001000  /* Board has an external LNA in 2.4GHz band */
+#define BFL_HGPA		0x00002000  /* Board has a high gain PA */
+#define	BFL_BTC2WIRE_ALTGPIO	0x00004000  /* Board's BTC 2wire is in the alternate gpios */
+#define	BFL_ALTIQ		0x00008000  /* Alternate I/Q settings */
+#define BFL_NOPA		0x00010000  /* Board has no PA */
+#define BFL_RSSIINV		0x00020000  /* Board's RSSI uses positive slope(not TSSI) */
+#define BFL_PAREF		0x00040000  /* Board uses the PARef LDO */
+#define BFL_3TSWITCH		0x00080000  /* Board uses a triple throw switch shared with BT */
+#define BFL_PHASESHIFT		0x00100000  /* Board can support phase shifter */
+#define BFL_BUCKBOOST		0x00200000  /* Power topology uses BUCKBOOST */
+#define BFL_FEM_BT		0x00400000  /* Board has FEM and switch to share antenna w/ BT */
+#define BFL_NOCBUCK		0x00800000  /* Power topology doesn't use CBUCK */
+#define BFL_CCKFAVOREVM		0x01000000  /* Favor CCK EVM over spectral mask */
+#define BFL_PALDO		0x02000000  /* Power topology uses PALDO */
+#define BFL_LNLDO2_2P5		0x04000000  /* Select 2.5V as LNLDO2 output voltage */
+#define BFL_FASTPWR		0x08000000
+#define BFL_UCPWRCTL_MININDX	0x08000000  /* Enforce min power index to avoid FEM damage */
+#define BFL_EXTLNA_5GHz		0x10000000  /* Board has an external LNA in 5GHz band */
+#define BFL_TRSW_1by2		0x20000000  /* Board has 2 TRSW's in 1by2 designs */
+#define BFL_GAINBOOSTA01        0x20000000  /* 5g Gainboost for core0 and core1 */
+#define BFL_LO_TRSW_R_5GHz	0x40000000  /* In 5G do not throw TRSW to T for clipLO gain */
+#define BFL_ELNA_GAINDEF	0x80000000  /* Backoff InitGain based on elna_2g/5g field
+					     * when this flag is set
+					     */
+#define BFL_EXTLNA_TX	0x20000000	/* Temp boardflag to indicate to */
+
+/* boardflags2 */
+#define BFL2_RXBB_INT_REG_DIS	0x00000001  /* Board has an external rxbb regulator */
+#define BFL2_APLL_WAR		0x00000002  /* Flag to implement alternative A-band PLL settings */
+#define BFL2_TXPWRCTRL_EN	0x00000004  /* Board permits enabling TX Power Control */
+#define BFL2_2X4_DIV		0x00000008  /* Board supports the 2X4 diversity switch */
+#define BFL2_5G_PWRGAIN		0x00000010  /* Board supports 5G band power gain */
+#define BFL2_PCIEWAR_OVR	0x00000020  /* Board overrides ASPM and Clkreq settings */
+#define BFL2_CAESERS_BRD	0x00000040  /* Board is Caesers brd (unused by sw) */
+#define BFL2_WLCX_ATLAS		0x00000040  /* Board flag to initialize ECI for WLCX on FL-ATLAS */
+#define BFL2_BTC3WIRE		0x00000080  /* Board support legacy 3 wire or 4 wire */
+#define BFL2_BTCLEGACY          0x00000080  /* Board support legacy 3/4 wire, to replace
+					     * BFL2_BTC3WIRE
+					     */
+#define BFL2_SKWRKFEM_BRD	0x00000100  /* 4321mcm93 board uses Skyworks FEM */
+#define BFL2_SPUR_WAR		0x00000200  /* Board has a WAR for clock-harmonic spurs */
+#define BFL2_GPLL_WAR		0x00000400  /* Flag to narrow G-band PLL loop b/w */
+#define BFL2_TRISTATE_LED	0x00000800  /* Tri-state the LED */
+#define BFL2_SINGLEANT_CCK	0x00001000  /* Tx CCK pkts on Ant 0 only */
+#define BFL2_2G_SPUR_WAR	0x00002000  /* WAR to reduce and avoid clock-harmonic spurs in 2G */
+#define BFL2_BPHY_ALL_TXCORES	0x00004000  /* Transmit bphy frames using all tx cores */
+#define BFL2_FCC_BANDEDGE_WAR	0x00008000  /* Activates WAR to improve FCC bandedge performance */
+#define BFL2_DAC_SPUR_IMPROVEMENT 0x00008000       /* Reducing DAC Spurs */
+#define BFL2_GPLL_WAR2	        0x00010000  /* Flag to widen G-band PLL loop b/w */
+#define BFL2_REDUCED_PA_TURNONTIME 0x00010000  /* Flag to reduce PA turn on Time */
+#define BFL2_IPALVLSHIFT_3P3    0x00020000
+#define BFL2_INTERNDET_TXIQCAL  0x00040000  /* Use internal envelope detector for TX IQCAL */
+#define BFL2_XTALBUFOUTEN       0x00080000  /* Keep the buffered Xtal output from radio on */
+				/* Most drivers will turn it off without this flag */
+				/* to save power. */
+
+#define BFL2_ANAPACTRL_2G	0x00100000  /* 2G ext PAs are controlled by analog PA ctrl lines */
+#define BFL2_ANAPACTRL_5G	0x00200000  /* 5G ext PAs are controlled by analog PA ctrl lines */
+#define BFL2_ELNACTRL_TRSW_2G	0x00400000  /* AZW4329: 2G gmode_elna_gain controls TR Switch */
+#define BFL2_BT_SHARE_ANT0	0x00800000  /* share core0 antenna with BT */
+#define BFL2_TEMPSENSE_HIGHER	0x01000000  /* The tempsense threshold can sustain higher value
+					     * than programmed. The exact delta is decided by
+					     * driver per chip/boardtype. This can be used
+					     * when tempsense qualification happens after shipment
+					     */
+#define BFL2_BTC3WIREONLY       0x02000000  /* standard 3 wire btc only.  4 wire not supported */
+#define BFL2_PWR_NOMINAL	0x04000000  /* 0: power reduction on, 1: no power reduction */
+#define BFL2_EXTLNA_PWRSAVE	0x08000000  /* boardflag to enable ucode to apply power save */
+						/* ucode control of eLNA during Tx */
+#define BFL2_4313_RADIOREG	0x10000000
+									   /*  board rework */
+#define BFL2_DYNAMIC_VMID	0x10000000  /* enable dynamic Vmid in idle TSSI CAL for 4331 */
+
+#define BFL2_SDR_EN		0x20000000  /* SDR enabled or disabled */
+#define BFL2_DYNAMIC_VMID	0x10000000  /* boardflag to enable dynamic Vmid idle TSSI CAL */
+#define BFL2_LNA1BYPFORTR2G	0x40000000  /* acphy, enable lna1 bypass for clip gain, 2g */
+#define BFL2_LNA1BYPFORTR5G	0x80000000  /* acphy, enable lna1 bypass for clip gain, 5g */
+
+/* SROM 11 - 11ac boardflag definitions */
+#define BFL_SROM11_BTCOEX  0x00000001  /* Board supports BTCOEX */
+#define BFL_SROM11_WLAN_BT_SH_XTL  0x00000002  /* bluetooth and wlan share same crystal */
+#define BFL_SROM11_EXTLNA	0x00001000  /* Board has an external LNA in 2.4GHz band */
+#define BFL_SROM11_EPA_TURNON_TIME     0x00018000  /* 2 bits for different PA turn on times */
+#define BFL_SROM11_EPA_TURNON_TIME_SHIFT  15
+#define BFL_SROM11_PRECAL_TX_IDX	0x00040000  /* Dedicated TX IQLOCAL IDX values */
+				/* per subband, as derived from 43602A1 MCH5 */
+#define BFL_SROM11_EXTLNA_5GHz	0x10000000  /* Board has an external LNA in 5GHz band */
+#define BFL_SROM11_GAINBOOSTA01	0x20000000  /* 5g Gainboost for core0 and core1 */
+#define BFL2_SROM11_APLL_WAR	0x00000002  /* Flag to implement alternative A-band PLL settings */
+#define BFL2_SROM11_ANAPACTRL_2G  0x00100000  /* 2G ext PAs are ctrl-ed by analog PA ctrl lines */
+#define BFL2_SROM11_ANAPACTRL_5G  0x00200000  /* 5G ext PAs are ctrl-ed by analog PA ctrl lines */
+#define BFL2_SROM11_SINGLEANT_CCK	0x00001000  /* Tx CCK pkts on Ant 0 only */
+#define BFL2_SROM11_EPA_ON_DURING_TXIQLOCAL    0x00020000  /* Keep ext. PA's on in TX IQLO CAL */
+
+/* boardflags3 */
+#define BFL3_FEMCTRL_SUB	  0x00000007  /* acphy, subrevs of femctrl on top of srom_femctrl */
+#define BFL3_RCAL_WAR		  0x00000008  /* acphy, rcal war active on this board (4335a0) */
+#define BFL3_TXGAINTBLID	  0x00000070  /* acphy, txgain table id */
+#define BFL3_TXGAINTBLID_SHIFT	  0x4         /* acphy, txgain table id shift bit */
+#define BFL3_TSSI_DIV_WAR	  0x00000080  /* acphy, Seperate paparam for 20/40/80 */
+#define BFL3_TSSI_DIV_WAR_SHIFT	  0x7         /* acphy, Seperate paparam for 20/40/80 shift bit */
+#define BFL3_FEMTBL_FROM_NVRAM    0x00000100  /* acphy, femctrl table is read from nvram */
+#define BFL3_FEMTBL_FROM_NVRAM_SHIFT 0x8         /* acphy, femctrl table is read from nvram */
+#define BFL3_AGC_CFG_2G           0x00000200  /* acphy, gain control configuration for 2G */
+#define BFL3_AGC_CFG_5G           0x00000400  /* acphy, gain control configuration for 5G */
+#define BFL3_PPR_BIT_EXT          0x00000800  /* acphy, bit position for 1bit extension for ppr */
+#define BFL3_PPR_BIT_EXT_SHIFT    11          /* acphy, bit shift for 1bit extension for ppr */
+#define BFL3_BBPLL_SPR_MODE_DIS	  0x00001000  /* acphy, disables bbpll spur modes */
+#define BFL3_RCAL_OTP_VAL_EN      0x00002000  /* acphy, to read rcal_trim value from otp */
+#define BFL3_2GTXGAINTBL_BLANK	  0x00004000  /* acphy, blank the first X ticks of 2g gaintbl */
+#define BFL3_2GTXGAINTBL_BLANK_SHIFT 14       /* acphy, blank the first X ticks of 2g gaintbl */
+#define BFL3_5GTXGAINTBL_BLANK	  0x00008000  /* acphy, blank the first X ticks of 5g gaintbl */
+#define BFL3_5GTXGAINTBL_BLANK_SHIFT 15       /* acphy, blank the first X ticks of 5g gaintbl */
+#define BFL3_PHASETRACK_MAX_ALPHABETA	  0x00010000  /* acphy, to max out alpha,beta to 511 */
+#define BFL3_PHASETRACK_MAX_ALPHABETA_SHIFT 16       /* acphy, to max out alpha,beta to 511 */
+/* acphy, to use backed off gaintbl for lte-coex */
+#define BFL3_LTECOEX_GAINTBL_EN           0x00060000
+/* acphy, to use backed off gaintbl for lte-coex */
+#define BFL3_LTECOEX_GAINTBL_EN_SHIFT 17
+#define BFL3_5G_SPUR_WAR          0x00080000  /* acphy, enable spur WAR in 5G band */
+#define BFL3_1X1_RSDB_ANT	  0x01000000  /* to find if 2-ant RSDB board or 1-ant RSDB board */
+#define BFL3_1X1_RSDB_ANT_SHIFT           24
+
+/* acphy: lpmode2g and lpmode_5g related boardflags */
+#define BFL3_ACPHY_LPMODE_2G	  0x00300000  /* bits 20:21 for lpmode_2g choice */
+#define BFL3_ACPHY_LPMODE_2G_SHIFT	  20
+
+#define BFL3_ACPHY_LPMODE_5G	  0x00C00000  /* bits 22:23 for lpmode_5g choice */
+#define BFL3_ACPHY_LPMODE_5G_SHIFT	  22
+
+#define BFL3_EXT_LPO_ISCLOCK      0x02000000  /* External LPO is clock, not x-tal */
+#define BFL3_FORCE_INT_LPO_SEL    0x04000000  /* Force internal lpo */
+#define BFL3_FORCE_EXT_LPO_SEL    0x08000000  /* Force external lpo */
+
+#define BFL3_EN_BRCM_IMPBF        0x10000000  /* acphy, Allow BRCM Implicit TxBF */
+#define BFL3_AVVMID_FROM_NVRAM    0x40000000  /* Read Av Vmid from NVRAM  */
+#define BFL3_VLIN_EN_FROM_NVRAM    0x80000000  /* Read Vlin En from NVRAM  */
+
+#define BFL3_AVVMID_FROM_NVRAM_SHIFT   30   /* Read Av Vmid from NVRAM  */
+#define BFL3_VLIN_EN_FROM_NVRAM_SHIFT   31   /* Enable Vlin  from NVRAM  */
+
+/* boardflags4 for SROM12/SROM13 */
+#define BFL4_SROM12_4dBPAD      (1 << 0)   /* To distinguigh between normal and 4dB pad board */
+#define BFL4_SROM12_2G_DETTYPE      (1 << 1)   /* Determine power detector type for 2G */
+#define BFL4_SROM12_5G_DETTYPE      (1 << 2)   /* Determine power detector type for 5G */
+#define BFL4_SROM13_DETTYPE_EN      (1 << 3)   /* using pa_dettype from SROM13 flags */
+#define BFL4_SROM13_CCK_SPUR_EN     (1 << 4)   /* using cck spur reduction setting in 4366 */
+#define BFL4_SROM13_1P5V_CBUCK		(1 << 7)   /* using 1.5V cbuck board in 4366 */
+#define BFL4_SROM13_EN_SW_TXRXCHAIN_MASK (1 << 8)   /* Enable/disable bit for sw chain mask */
+
+#define BFL4_4364_HARPOON 0x0100   /* Harpoon module 4364 */
+#define BFL4_4364_GODZILLA 0x0200   /* Godzilla module 4364 */
+#define BFL4_BTCOEX_OVER_SECI	0x00000400 /* Enable btcoex over gci seci */
+
+/* papd params */
+#define PAPD_TX_ATTN_2G 0xFF
+#define PAPD_TX_ATTN_5G 0xFF00
+#define PAPD_TX_ATTN_5G_SHIFT 8
+#define PAPD_RX_ATTN_2G 0xFF
+#define PAPD_RX_ATTN_5G 0xFF00
+#define PAPD_RX_ATTN_5G_SHIFT 8
+#define PAPD_CAL_IDX_2G 0xFF
+#define PAPD_CAL_IDX_5G 0xFF00
+#define PAPD_CAL_IDX_5G_SHIFT 8
+#define PAPD_BBMULT_2G 0xFF
+#define PAPD_BBMULT_5G 0xFF00
+#define PAPD_BBMULT_5G_SHIFT 8
+#define TIA_GAIN_MODE_2G 0xFF
+#define TIA_GAIN_MODE_5G 0xFF00
+#define TIA_GAIN_MODE_5G_SHIFT 8
+#define PAPD_EPS_OFFSET_2G 0xFFFF
+#define PAPD_EPS_OFFSET_5G 0xFFFF0000
+#define PAPD_EPS_OFFSET_5G_SHIFT 16
+#define PAPD_CALREF_DB_2G 0xFF
+#define PAPD_CALREF_DB_5G 0xFF00
+#define PAPD_CALREF_DB_5G_SHIFT 8
+
+
+/* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */
+#define	BOARD_GPIO_BTC3W_IN	0x850	/* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */
+#define	BOARD_GPIO_BTC3W_OUT	0x020	/* bit 5 is TX_CONF */
+#define	BOARD_GPIO_BTCMOD_IN	0x010	/* bit 4 is the alternate BT Coexistence Input */
+#define	BOARD_GPIO_BTCMOD_OUT	0x020	/* bit 5 is the alternate BT Coexistence Out */
+#define	BOARD_GPIO_BTC_IN	0x080	/* bit 7 is BT Coexistence Input */
+#define	BOARD_GPIO_BTC_OUT	0x100	/* bit 8 is BT Coexistence Out */
+#define	BOARD_GPIO_PACTRL	0x200	/* bit 9 controls the PA on new 4306 boards */
+#define BOARD_GPIO_12		0x1000	/* gpio 12 */
+#define BOARD_GPIO_13		0x2000	/* gpio 13 */
+#define BOARD_GPIO_BTC4_IN	0x0800	/* gpio 11, coex4, in */
+#define BOARD_GPIO_BTC4_BT	0x2000	/* gpio 12, coex4, bt active */
+#define BOARD_GPIO_BTC4_STAT	0x4000	/* gpio 14, coex4, status */
+#define BOARD_GPIO_BTC4_WLAN	0x8000	/* gpio 15, coex4, wlan active */
+#define	BOARD_GPIO_1_WLAN_PWR	0x02	/* throttle WLAN power on X21 board */
+#define	BOARD_GPIO_2_WLAN_PWR	0x04	/* throttle WLAN power on X29C board */
+#define	BOARD_GPIO_3_WLAN_PWR	0x08	/* throttle WLAN power on X28 board */
+#define	BOARD_GPIO_4_WLAN_PWR	0x10	/* throttle WLAN power on X19 board */
+#define	BOARD_GPIO_13_WLAN_PWR	0x2000	/* throttle WLAN power on X14 board */
+
+#define GPIO_BTC4W_OUT_4312  0x010  /* bit 4 is BT_IODISABLE */
+#define GPIO_BTC4W_OUT_43224  0x020  /* bit 5 is BT_IODISABLE */
+#define GPIO_BTC4W_OUT_43224_SHARED  0x0e0  /* bit 5 is BT_IODISABLE */
+#define GPIO_BTC4W_OUT_43225  0x0e0  /* bit 5 BT_IODISABLE, bit 6 SW_BT, bit 7 SW_WL */
+#define GPIO_BTC4W_OUT_43421  0x020  /* bit 5 is BT_IODISABLE */
+#define GPIO_BTC4W_OUT_4313  0x060  /* bit 5 SW_BT, bit 6 SW_WL */
+#define GPIO_BTC4W_OUT_4331_SHARED  0x010  /* GPIO 4  */
+
+#define	PCI_CFG_GPIO_SCS	0x10	/* PCI config space bit 4 for 4306c0 slow clock source */
+#define PCI_CFG_GPIO_HWRAD	0x20	/* PCI config space GPIO 13 for hw radio disable */
+#define PCI_CFG_GPIO_XTAL	0x40	/* PCI config space GPIO 14 for Xtal power-up */
+#define PCI_CFG_GPIO_PLL	0x80	/* PCI config space GPIO 15 for PLL power-down */
+
+/* power control defines */
+#define PLL_DELAY		150		/* us pll on delay */
+#define FREF_DELAY		200		/* us fref change delay */
+#define MIN_SLOW_CLK		32		/* us Slow clock period */
+#define	XTAL_ON_DELAY		1000		/* us crystal power-on delay */
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/* Reference Board Types */
+#define	BU4710_BOARD		0x0400
+#define	VSIM4710_BOARD		0x0401
+#define	QT4710_BOARD		0x0402
+
+#define	BU4309_BOARD		0x040a
+#define	BCM94309CB_BOARD	0x040b
+#define	BCM94309MP_BOARD	0x040c
+#define	BCM4309AP_BOARD		0x040d
+
+#define	BCM94302MP_BOARD	0x040e
+
+#define	BU4306_BOARD		0x0416
+#define	BCM94306CB_BOARD	0x0417
+#define	BCM94306MP_BOARD	0x0418
+
+#define	BCM94710D_BOARD		0x041a
+#define	BCM94710R1_BOARD	0x041b
+#define	BCM94710R4_BOARD	0x041c
+#define	BCM94710AP_BOARD	0x041d
+
+#define	BU2050_BOARD		0x041f
+
+#define	BCM94306P50_BOARD	0x0420
+
+#define	BCM94309G_BOARD		0x0421
+
+#define	BU4704_BOARD		0x0423
+#define	BU4702_BOARD		0x0424
+
+#define	BCM94306PC_BOARD	0x0425		/* pcmcia 3.3v 4306 card */
+
+#define	MPSG4306_BOARD		0x0427
+
+#define	BCM94702MN_BOARD	0x0428
+
+/* BCM4702 1U CompactPCI Board */
+#define	BCM94702CPCI_BOARD	0x0429
+
+/* BCM4702 with BCM95380 VLAN Router */
+#define	BCM95380RR_BOARD	0x042a
+
+/* cb4306 with SiGe PA */
+#define	BCM94306CBSG_BOARD	0x042b
+
+/* cb4306 with SiGe PA */
+#define	PCSG94306_BOARD		0x042d
+
+/* bu4704 with sdram */
+#define	BU4704SD_BOARD		0x042e
+
+/* Dual 11a/11g Router */
+#define	BCM94704AGR_BOARD	0x042f
+
+/* 11a-only minipci */
+#define	BCM94308MP_BOARD	0x0430
+
+/* 4306/gprs combo */
+#define	BCM94306GPRS_BOARD	0x0432
+
+/* BCM5365/BCM4704 FPGA Bringup Board */
+#define BU5365_FPGA_BOARD	0x0433
+
+#define BU4712_BOARD		0x0444
+#define	BU4712SD_BOARD		0x045d
+#define	BU4712L_BOARD		0x045f
+
+/* BCM4712 boards */
+#define BCM94712AP_BOARD	0x0445
+#define BCM94712P_BOARD		0x0446
+
+/* BCM4318 boards */
+#define BU4318_BOARD		0x0447
+#define CB4318_BOARD		0x0448
+#define MPG4318_BOARD		0x0449
+#define MP4318_BOARD		0x044a
+#define SD4318_BOARD		0x044b
+
+/* BCM4313 boards */
+#define BCM94313BU_BOARD	0x050f
+#define BCM94313HM_BOARD	0x0510
+#define BCM94313EPA_BOARD	0x0511
+#define BCM94313HMG_BOARD       0x051C
+
+/* BCM63XX boards */
+#define BCM96338_BOARD		0x6338
+#define BCM96348_BOARD		0x6348
+#define BCM96358_BOARD		0x6358
+#define BCM96368_BOARD		0x6368
+
+/* Another mp4306 with SiGe */
+#define	BCM94306P_BOARD		0x044c
+
+/* mp4303 */
+#define	BCM94303MP_BOARD	0x044e
+
+/* mpsgh4306 */
+#define	BCM94306MPSGH_BOARD	0x044f
+
+/* BRCM 4306 w/ Front End Modules */
+#define BCM94306MPM		0x0450
+#define BCM94306MPL		0x0453
+
+/* 4712agr */
+#define	BCM94712AGR_BOARD	0x0451
+
+/* pcmcia 4303 */
+#define	PC4303_BOARD		0x0454
+
+/* 5350K */
+#define	BCM95350K_BOARD		0x0455
+
+/* 5350R */
+#define	BCM95350R_BOARD		0x0456
+
+/* 4306mplna */
+#define	BCM94306MPLNA_BOARD	0x0457
+
+/* 4320 boards */
+#define	BU4320_BOARD		0x0458
+#define	BU4320S_BOARD		0x0459
+#define	BCM94320PH_BOARD	0x045a
+
+/* 4306mph */
+#define	BCM94306MPH_BOARD	0x045b
+
+/* 4306pciv */
+#define	BCM94306PCIV_BOARD	0x045c
+
+#define	BU4712SD_BOARD		0x045d
+
+#define	BCM94320PFLSH_BOARD	0x045e
+
+#define	BU4712L_BOARD		0x045f
+#define	BCM94712LGR_BOARD	0x0460
+#define	BCM94320R_BOARD		0x0461
+
+#define	BU5352_BOARD		0x0462
+
+#define	BCM94318MPGH_BOARD	0x0463
+
+#define	BU4311_BOARD		0x0464
+#define	BCM94311MC_BOARD	0x0465
+#define	BCM94311MCAG_BOARD	0x0466
+
+#define	BCM95352GR_BOARD	0x0467
+
+/* bcm95351agr */
+#define	BCM95351AGR_BOARD	0x0470
+
+/* bcm94704mpcb */
+#define	BCM94704MPCB_BOARD	0x0472
+
+/* 4785 boards */
+#define BU4785_BOARD		0x0478
+
+/* 4321 boards */
+#define BU4321_BOARD		0x046b
+#define BU4321E_BOARD		0x047c
+#define MP4321_BOARD		0x046c
+#define CB2_4321_BOARD		0x046d
+#define CB2_4321_AG_BOARD	0x0066
+#define MC4321_BOARD		0x046e
+
+/* 4328 boards */
+#define BU4328_BOARD		0x0481
+#define BCM4328SDG_BOARD	0x0482
+#define BCM4328SDAG_BOARD	0x0483
+#define BCM4328UG_BOARD		0x0484
+#define BCM4328UAG_BOARD	0x0485
+#define BCM4328PC_BOARD		0x0486
+#define BCM4328CF_BOARD		0x0487
+
+/* 4325 boards */
+#define BCM94325DEVBU_BOARD	0x0490
+#define BCM94325BGABU_BOARD	0x0491
+
+#define BCM94325SDGWB_BOARD	0x0492
+
+#define BCM94325SDGMDL_BOARD	0x04aa
+#define BCM94325SDGMDL2_BOARD	0x04c6
+#define BCM94325SDGMDL3_BOARD	0x04c9
+
+#define BCM94325SDABGWBA_BOARD	0x04e1
+
+#ifdef DEPRECATED
+/* 4322 boards */
+#define BCM94322MC_SSID		0x04a4
+#define BCM94322USB_SSID	0x04a8	/* dualband */
+#define BCM94322HM_SSID		0x04b0
+#define BCM94322USB2D_SSID	0x04bf	/* single band discrete front end */
+
+/* 4312 boards */
+#define	BCM4312MCGSG_BOARD	0x04b5
+
+/* 4315 boards */
+#define BCM94315DEVBU_SSID	0x04c2
+#define BCM94315USBGP_SSID	0x04c7
+#define BCM94315BGABU_SSID	0x04ca
+#define BCM94315USBGP41_SSID	0x04cb
+
+/* 4319 boards */
+#define BCM94319DEVBU_SSID	0X04e5
+#define BCM94319USB_SSID	0X04e6
+#define BCM94319SD_SSID		0X04e7
+
+/* 4716 boards */
+#define BCM94716NR2_SSID	0x04cd
+
+/* 4319 boards */
+#define BCM94319DEVBU_SSID	0X04e5
+#define BCM94319USBNP4L_SSID	0X04e6
+#define BCM94319WLUSBN4L_SSID	0X04e7
+#define BCM94319SDG_SSID	0X04ea
+#define BCM94319LCUSBSDN4L_SSID	0X04eb
+#define BCM94319USBB_SSID       0x04ee
+#define BCM94319LCSDN4L_SSID	0X0507
+#define BCM94319LSUSBN4L_SSID	0X0508
+#define BCM94319SDNA4L_SSID	0X0517
+#define BCM94319SDELNA4L_SSID	0X0518
+#define BCM94319SDELNA6L_SSID	0X0539
+#define BCM94319ARCADYAN_SSID	0X0546
+#define BCM94319WINDSOR_SSID    0x0561
+#define BCM94319MLAP_SSID       0x0562
+#define BCM94319SDNA_SSID       0x058b
+#define BCM94319BHEMU3_SSID     0x0563
+#define BCM94319SDHMB_SSID     0x058c
+#define BCM94319SDBREF_SSID     0x05a1
+#define BCM94319USBSDB_SSID     0x05a2
+
+
+/* 4329 boards */
+#define BCM94329AGB_SSID	0X04b9
+#define BCM94329TDKMDL1_SSID	0X04ba
+#define BCM94329TDKMDL11_SSID	0X04fc
+#define BCM94329OLYMPICN18_SSID	0X04fd
+#define BCM94329OLYMPICN90_SSID	0X04fe
+#define BCM94329OLYMPICN90U_SSID 0X050c
+#define BCM94329OLYMPICN90M_SSID 0X050b
+#define BCM94329AGBF_SSID	0X04ff
+#define BCM94329OLYMPICX17_SSID	0X0504
+#define BCM94329OLYMPICX17M_SSID	0X050a
+#define BCM94329OLYMPICX17U_SSID	0X0509
+#define BCM94329OLYMPICUNO_SSID	0X0564
+#define BCM94329MOTOROLA_SSID   0X0565
+#define BCM94329OLYMPICLOCO_SSID	0X0568
+#endif /* DEPRICATED */
+
+/* 4336 SDIO board types */
+#define BCM94336SD_WLBGABU_SSID		0x0511
+#define BCM94336SD_WLBGAREF_SSID	0x0519
+#define BCM94336SDGP_SSID	0x0538
+#define BCM94336SDG_SSID	0x0519
+#define BCM94336SDGN_SSID	0x0538
+#define BCM94336SDGFC_SSID	0x056B
+
+/* 4330 SDIO board types */
+#define BCM94330SDG_SSID	0x0528
+#define BCM94330SD_FCBGABU_SSID	0x052e
+#define BCM94330SD_WLBGABU_SSID	0x052f
+#define BCM94330SD_FCBGA_SSID	0x0530
+#define BCM94330FCSDAGB_SSID		0x0532
+#define BCM94330OLYMPICAMG_SSID		0x0549
+#define BCM94330OLYMPICAMGEPA_SSID		0x054F
+#define BCM94330OLYMPICUNO3_SSID	0x0551
+#define BCM94330WLSDAGB_SSID	0x0547
+#define BCM94330CSPSDAGBB_SSID	0x054A
+
+/* 43224 boards */
+#define BCM943224X21        0x056e
+#define BCM943224X21_FCC    0x00d1
+#define BCM943224X21B	    0x00e9
+#define BCM943224M93	    0x008b
+#define BCM943224M93A	    0x0090
+#define BCM943224X16	    0x0093
+#define BCM94322X9		    0x008d
+#define BCM94322M35e	    0x008e
+
+/* 43228 Boards */
+#define BCM943228BU8_SSID	0x0540
+#define BCM943228BU9_SSID	0x0541
+#define BCM943228BU_SSID	0x0542
+#define BCM943227HM4L_SSID	0x0543
+#define BCM943227HMB_SSID	0x0544
+#define BCM943228HM4L_SSID	0x0545
+#define BCM943228SD_SSID	0x0573
+
+/* 43239 Boards */
+#define BCM943239MOD_SSID	0x05ac
+#define BCM943239REF_SSID	0x05aa
+
+/* 4331 boards */
+#define BCM94331X19               0x00D6	/* X19B */
+#define BCM94331X28               0x00E4	/* X28 */
+#define BCM94331X28B              0x010E	/* X28B */
+#define BCM94331PCIEBT3Ax_SSID    BCM94331X28
+#define BCM94331X12_2G_SSID       0x00EC	/* X12 2G */
+#define BCM94331X12_5G_SSID       0x00ED	/* X12 5G */
+#define BCM94331X29B              0x00EF	/* X29B */
+#define BCM94331X29D              0x010F	/* X29D */
+#define BCM94331CSAX_SSID         BCM94331X29B
+#define BCM94331X19C              0x00F5	/* X19C */
+#define BCM94331X33	          0x00F4	/* X33 */
+#define BCM94331BU_SSID           0x0523
+#define BCM94331S9BU_SSID         0x0524
+#define BCM94331MC_SSID           0x0525
+#define BCM94331MCI_SSID          0x0526
+#define BCM94331PCIEBT4_SSID      0x0527
+#define BCM94331HM_SSID           0x0574
+#define BCM94331PCIEDUAL_SSID     0x059B
+#define BCM94331MCH5_SSID         0x05A9
+#define BCM94331CS_SSID           0x05C6
+#define BCM94331CD_SSID           0x05DA
+
+/* 4314 Boards */
+#define BCM94314BU_SSID         0x05b1
+
+/* 53572 Boards */
+#define BCM953572BU_SSID       0x058D
+#define BCM953572NR2_SSID      0x058E
+#define BCM947188NR2_SSID      0x058F
+#define BCM953572SDRNR2_SSID   0x0590
+
+/* 43236 boards */
+#define BCM943236OLYMPICSULLEY_SSID 0x594
+#define BCM943236PREPROTOBLU2O3_SSID 0x5b9
+#define BCM943236USBELNA_SSID 0x5f8
+
+/* 4314 Boards */
+#define BCM94314BUSDIO_SSID	0x05c8
+#define BCM94314BGABU_SSID	0x05c9
+#define BCM94314HMEPA_SSID	0x05ca
+#define BCM94314HMEPABK_SSID	0x05cb
+#define BCM94314SUHMEPA_SSID	0x05cc
+#define BCM94314SUHM_SSID	0x05cd
+#define BCM94314HM_SSID		0x05d1
+
+/* 4334 Boards */
+#define BCM94334FCAGBI_SSID	0x05df
+#define BCM94334WLAGBI_SSID	0x05dd
+
+/* 4335 Boards */
+#define BCM94335X52             0x0114
+
+/* 4345 Boards */
+#define BCM94345_SSID           0x0687
+
+/* 4360 Boards */
+#define BCM94360X52C            0X0117
+#define BCM94360X52D            0X0137
+#define BCM94360X29C            0X0112
+#define BCM94360X29CP2          0X0134
+#define BCM94360X29CP3          0X013B
+#define BCM94360X51             0x0111
+#define BCM94360X51P2           0x0129
+#define BCM94360X51P3           0x0142
+#define BCM94360X51A            0x0135
+#define BCM94360X51B            0x0136
+#define BCM94360CS              0x061B
+#define BCM94360J28_D11AC2G     0x0c00
+#define BCM94360J28_D11AC5G     0x0c01
+#define BCM94360USBH5_D11AC5G   0x06aa
+#define BCM94360MCM5            0x06d8
+
+/* 4350 Boards */
+#define BCM94350X52B            0X0116
+#define BCM94350X14             0X0131
+#define BCM94350X14P2           0X0158
+#define BCM94350X14P3           0X0159
+
+/* 43217 Boards */
+#define BCM943217BU_SSID	0x05d5
+#define BCM943217HM2L_SSID	0x05d6
+#define BCM943217HMITR2L_SSID	0x05d7
+
+/* 43142 Boards */
+#define BCM943142HM_SSID	0x05e0
+
+/* 4357 Boards */
+#define BCM94361SSMOD_TYPE8_ALLEPA		0x080f
+#define BCM94361FCPAGBSS				0x0817
+#define BCM94361WLPAGBI					0x081a
+#define BCM94357FCPAGBE					0x07ec
+#define BCM94361FCPAGBI					0x07eb
+
+/* 4364 Boards */
+#define BCM94364FCPAGB					0x07A2
+#endif /* LINUX_POSTMOGRIFY_REMOVAL */
+
+/* 43341 Boards */
+#define BCM943341WLABGS_SSID	0x062d
+
+/* 43342 Boards */
+#define BCM943342FCAGBI_SSID	0x0641
+
+/* 43012 wlbga Board */
+#define BCM943012WLREF_SSID	0x07d7
+
+/* 43012 fcbga Board */
+#define BCM943012FCREF_SSID	0x07d4
+
+/* 43602 Boards, unclear yet what boards will be created. */
+#define BCM943602RSVD1_SSID	0x06a5
+#define BCM943602RSVD2_SSID	0x06a6
+#define BCM943602X87            0X0133
+#define BCM943602X87P2          0X0152
+#define BCM943602X87P3          0X0153
+#define BCM943602X238           0X0132
+#define BCM943602X238D          0X014A
+#define BCM943602X238DP2        0X0155
+#define BCM943602X238DP3        0X0156
+#define BCM943602X100           0x0761
+#define BCM943602X100GS         0x0157
+#define BCM943602X100P2         0x015A
+
+/* # of GPIO pins */
+#define GPIO_NUMPINS		32
+
+/* These values are used by dhd host driver. */
+#define RDL_RAM_BASE_4319 0x60000000
+#define RDL_RAM_BASE_4329 0x60000000
+#define RDL_RAM_SIZE_4319 0x48000
+#define RDL_RAM_SIZE_4329  0x48000
+#define RDL_RAM_SIZE_43236 0x70000
+#define RDL_RAM_BASE_43236 0x60000000
+#define RDL_RAM_SIZE_4328 0x60000
+#define RDL_RAM_BASE_4328 0x80000000
+#define RDL_RAM_SIZE_4322 0x60000
+#define RDL_RAM_BASE_4322 0x60000000
+#define RDL_RAM_SIZE_4360  0xA0000
+#define RDL_RAM_BASE_4360  0x60000000
+#define RDL_RAM_SIZE_43242  0x90000
+#define RDL_RAM_BASE_43242  0x60000000
+#define RDL_RAM_SIZE_43143  0x70000
+#define RDL_RAM_BASE_43143  0x60000000
+#define RDL_RAM_SIZE_4350  0xC0000
+#define RDL_RAM_BASE_4350  0x180800
+
+/* generic defs for nvram "muxenab" bits
+* Note: these differ for 4335a0. refer bcmchipc.h for specific mux options.
+*/
+#define MUXENAB_UART		0x00000001
+#define MUXENAB_GPIO		0x00000002
+#define MUXENAB_ERCX		0x00000004	/* External Radio BT coex */
+#define MUXENAB_JTAG		0x00000008
+#define MUXENAB_HOST_WAKE	0x00000010	/* configure GPIO for SDIO host_wake */
+#define MUXENAB_I2S_EN		0x00000020
+#define MUXENAB_I2S_MASTER	0x00000040
+#define MUXENAB_I2S_FULL	0x00000080
+#define MUXENAB_SFLASH		0x00000100
+#define MUXENAB_RFSWCTRL0	0x00000200
+#define MUXENAB_RFSWCTRL1	0x00000400
+#define MUXENAB_RFSWCTRL2	0x00000800
+#define MUXENAB_SECI		0x00001000
+#define MUXENAB_BT_LEGACY	0x00002000
+#define MUXENAB_HOST_WAKE1	0x00004000	/* configure alternative GPIO for SDIO host_wake */
+
+/* Boot flags */
+#define FLASH_KERNEL_NFLASH	0x00000001
+#define FLASH_BOOT_NFLASH	0x00000002
+
+#endif /* _BCMDEVS_H */
diff --git a/wl/src/include/bcmendian.h b/wl/src/include/bcmendian.h
new file mode 100644
index 0000000..40678e8
--- /dev/null
+++ b/wl/src/include/bcmendian.h
@@ -0,0 +1,450 @@
+/*
+ * Byte order utilities
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmendian.h 633810 2016-04-25 16:46:55Z $
+ *
+ * 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>
+
+/* Reverse the bytes in a 16-bit value */
+#define BCMSWAP16(val) \
+	((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \
+		  (((uint16)(val) & (uint16)0xff00U) >> 8)))
+
+/* Reverse the bytes in a 32-bit value */
+#define BCMSWAP32(val) \
+	((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \
+		  (((uint32)(val) & (uint32)0x0000ff00U) <<  8) | \
+		  (((uint32)(val) & (uint32)0x00ff0000U) >>  8) | \
+		  (((uint32)(val) & (uint32)0xff000000U) >> 24)))
+
+/* Reverse the two 16-bit halves of a 32-bit value */
+#define BCMSWAP32BY16(val) \
+	((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \
+		  (((uint32)(val) & (uint32)0xffff0000U) >> 16)))
+
+/* Reverse the bytes in a 64-bit value */
+#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)))
+
+/* Reverse the two 32-bit halves of a 64-bit value */
+#define BCMSWAP64BY32(val) \
+	((uint64)((((uint64)(val) & 0x00000000ffffffffULL) << 32) | \
+	          (((uint64)(val) & 0xffffffff00000000ULL) >> 32)))
+
+
+/* Byte swapping macros
+ *    Host <=> Network (Big Endian) for 16- and 32-bit values
+ *    Host <=> Little-Endian for 16- and 32-bit values
+ */
+#ifndef hton16
+#ifndef IL_BIGENDIAN
+#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)
+#else /* IL_BIGENDIAN */
+#define HTON16(i) (i)
+#define	hton16(i) (i)
+#define	HTON32(i) (i)
+#define	hton32(i) (i)
+#define	NTOH16(i) (i)
+#define	ntoh16(i) (i)
+#define	NTOH32(i) (i)
+#define	ntoh32(i) (i)
+#define	LTOH16(i) BCMSWAP16(i)
+#define	ltoh16(i) bcmswap16(i)
+#define	LTOH32(i) BCMSWAP32(i)
+#define	ltoh32(i) bcmswap32(i)
+#define HTOL16(i) BCMSWAP16(i)
+#define htol16(i) bcmswap16(i)
+#define HTOL32(i) BCMSWAP32(i)
+#define htol32(i) bcmswap32(i)
+#define HTOL64(i) BCMSWAP64(i)
+#define htol64(i) bcmswap64(i)
+#endif /* IL_BIGENDIAN */
+#endif /* hton16 */
+
+#ifndef IL_BIGENDIAN
+#define ltoh16_buf(buf, i)
+#define htol16_buf(buf, i)
+#define ltoh32_buf(buf, i)
+#define htol32_buf(buf, i)
+#define ltoh64_buf(buf, i)
+#define htol64_buf(buf, i)
+#else
+#define ltoh16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i))
+#define htol16_buf(buf, i) bcmswap16_buf((uint16 *)(buf), (i))
+#define ltoh32_buf(buf, i) bcmswap32_buf((uint16 *)(buf), (i))
+#define htol32_buf(buf, i) bcmswap32_buf((uint16 *)(buf), (i))
+#define ltoh64_buf(buf, i) bcmswap64_buf((uint16 *)(buf), (i))
+#define htol64_buf(buf, i) bcmswap64_buf((uint16 *)(buf), (i))
+#endif /* IL_BIGENDIAN */
+
+/* Unaligned loads and stores in host byte order */
+#ifndef IL_BIGENDIAN
+#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 load64_ua(a)		ltoh64_ua(a)
+#define store64_ua(a, v)	htol64_ua_store(v, a)
+#else
+#define load32_ua(a)		ntoh32_ua(a)
+#define store32_ua(a, v)	hton32_ua_store(v, a)
+#define load16_ua(a)		ntoh16_ua(a)
+#define store16_ua(a, v)	hton16_ua_store(v, a)
+#define load64_ua(a)		ntoh64_ua(a)
+#define store64_ua(a, v)	hton64_ua_store(v, a)
+#endif /* IL_BIGENDIAN */
+
+#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 _LTOH64_UA(cp)	((uint64)(cp)[0] | ((uint64)(cp)[1] << 8) | \
+	((uint64)(cp)[2] << 16) | ((uint64)(cp)[3] << 24) | \
+	((uint64)(cp)[4] << 32) | ((uint64)(cp)[5] << 40) | \
+	((uint64)(cp)[6] << 48) | ((uint64)(cp)[7] << 56))
+
+#define _NTOH64_UA(cp)	((uint64)(cp)[7] | ((uint64)(cp)[6] << 8) | \
+	((uint64)(cp)[5] << 16) | ((uint64)(cp)[4] << 24) | \
+	((uint64)(cp)[3] << 32) | ((uint64)(cp)[2] << 40) | \
+	((uint64)(cp)[1] << 48) | ((uint64)(cp)[0] << 56))
+
+#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__
+
+/* GNU macro versions avoid referencing the argument multiple times, while also
+ * avoiding the -fno-inline used in ROM builds.
+ */
+
+#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 bcmswap32_buf(buf, len) ({ \
+	uint32 *_buf = (uint32 *)(buf); \
+	uint _wds = (len) / 4; \
+	while (_wds--) { \
+		*_buf = bcmswap32(*_buf); \
+		_buf++; \
+	} \
+})
+
+#define bcmswap64_buf(buf, len) ({ \
+	uint64 *_buf = (uint64 *)(buf); \
+	uint _wds = (len) / 8; \
+	while (_wds--) { \
+		*_buf = bcmswap64(*_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 htol64_ua_store(val, bytes) ({ \
+	uint64 _val = (val); \
+	uint8 *_bytes = (uint8 *)(bytes); \
+	int i; \
+	for (i = 0; i < (int)sizeof(_val); ++i) { \
+		*_bytes++ = _val & 0xff; \
+		_val >>= 8; \
+	} \
+})
+
+#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 ltoh64_ua(bytes) ({ \
+	const uint8 *_bytes = (const uint8 *)(bytes); \
+	_LTOH64_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); \
+})
+
+#define ntoh64_ua(bytes) ({ \
+	const uint8 *_bytes = (const uint8 *)(bytes); \
+	_NTOH64_UA(_bytes); \
+})
+
+#else /* !__GNUC__ */
+
+/* Inline versions avoid referencing the argument multiple times */
+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);
+}
+
+/* Reverse pairs of bytes in a buffer (not for high-performance use) */
+/* buf	- start of buffer of shorts to swap */
+/* len  - byte length of buffer */
+static INLINE void
+bcmswap16_buf(uint16 *buf, uint len)
+{
+	len = len / 2;
+
+	while (len--) {
+		*buf = bcmswap16(*buf);
+		buf++;
+	}
+}
+
+/*
+ * Store 16-bit value to unaligned little-endian byte array.
+ */
+static INLINE void
+htol16_ua_store(uint16 val, uint8 *bytes)
+{
+	bytes[0] = val & 0xff;
+	bytes[1] = val >> 8;
+}
+
+/*
+ * Store 32-bit value to unaligned little-endian byte array.
+ */
+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;
+}
+
+/*
+ * Store 64-bit value to unaligned little-endian byte array.
+ */
+static INLINE void
+htol64_ua_store(uint64 val, uint8 *bytes)
+{
+	int i;
+	for (i = 0; i < sizeof(val); ++i) {
+		*bytes++ = (uint8)(val & 0xff);
+		val >>= 8;
+	}
+}
+
+/*
+ * Store 16-bit value to unaligned network-(big-)endian byte array.
+ */
+static INLINE void
+hton16_ua_store(uint16 val, uint8 *bytes)
+{
+	bytes[0] = val >> 8;
+	bytes[1] = val & 0xff;
+}
+
+/*
+ * Store 32-bit value to unaligned network-(big-)endian byte array.
+ */
+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;
+}
+
+/*
+ * Load 16-bit value from unaligned little-endian byte array.
+ */
+static INLINE uint16
+ltoh16_ua(const void *bytes)
+{
+	return _LTOH16_UA((const uint8 *)bytes);
+}
+
+/*
+ * Load 32-bit value from unaligned little-endian byte array.
+ */
+static INLINE uint32
+ltoh32_ua(const void *bytes)
+{
+	return _LTOH32_UA((const uint8 *)bytes);
+}
+
+/*
+ * Load 64-bit value from unaligned little-endian byte array.
+ */
+static INLINE uint64
+ltoh64_ua(const void *bytes)
+{
+	return _LTOH64_UA((const uint8 *)bytes);
+}
+
+/*
+ * Load 16-bit value from unaligned big-(network-)endian byte array.
+ */
+static INLINE uint16
+ntoh16_ua(const void *bytes)
+{
+	return _NTOH16_UA((const uint8 *)bytes);
+}
+
+/*
+ * Load 32-bit value from unaligned big-(network-)endian byte array.
+ */
+static INLINE uint32
+ntoh32_ua(const void *bytes)
+{
+	return _NTOH32_UA((const uint8 *)bytes);
+}
+
+/*
+ * Load 64-bit value from unaligned big-(network-)endian byte array.
+ */
+static INLINE uint64
+ntoh64_ua(const void *bytes)
+{
+	return _NTOH64_UA((const uint8 *)bytes);
+}
+
+#endif /* !__GNUC__ */
+#endif /* !_BCMENDIAN_H_ */
diff --git a/wl/src/include/bcmiov.h b/wl/src/include/bcmiov.h
new file mode 100644
index 0000000..b6e77d5
--- /dev/null
+++ b/wl/src/include/bcmiov.h
@@ -0,0 +1,350 @@
+/*
+ * bcmiov.h
+ * Common iovar handling/parsing support - batching, parsing, sub-cmd dispatch etc.
+ * To be used in firmware and host apps or dhd - reducing code size,
+ * duplication, and maintenance overhead.
+ *
+ * Copyright (C) 2017, Broadcom. 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/Proprietary:>>
+ *
+ * $Id$
+ */
+
+
+#ifndef _bcmiov_h_
+#define _bcmiov_h_
+
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <wlioctl.h>
+#ifdef BCMDRIVER
+#include <osl.h>
+#else
+#include <stddef.h>  /* For size_t */
+#endif /* BCMDRIVER */
+
+/* Forward declarations */
+typedef uint16 bcm_iov_cmd_id_t;
+typedef uint16 bcm_iov_cmd_flags_t;
+typedef uint16 bcm_iov_cmd_iovf_t;
+typedef struct bcm_iov_cmd_info bcm_iov_cmd_info_t;
+typedef struct bcm_iov_cmd_digest bcm_iov_cmd_digest_t;
+typedef struct bcm_iov_cmd_tlv_info bcm_iov_cmd_tlv_info_t;
+typedef struct bcm_iov_buf bcm_iov_buf_t;
+typedef struct bcm_iov_batch_buf bcm_iov_batch_buf_t;
+typedef struct bcm_iov_parse_context bcm_iov_parse_context_t;
+typedef struct bcm_iov_sub_cmd_context bcm_iov_sub_cmd_context_t;
+
+typedef void* (*bcm_iov_malloc_t)(void* alloc_ctx, size_t len);
+typedef void (*bcm_iov_free_t)(void* alloc_ctx, void *buf, size_t len);
+
+typedef uint8 bcm_iov_tlp_data_type_t;
+typedef struct bcm_iov_tlp bcm_iov_tlp_t;
+typedef struct bcm_iov_tlp_node bcm_iov_tlp_node_t;
+typedef struct bcm_iov_batch_subcmd bcm_iov_batch_subcmd_t;
+
+/*
+ * iov validation handler - All the common checks that are required
+ * for processing of iovars for any given command.
+ */
+typedef int (*bcm_iov_cmd_validate_t)(const bcm_iov_cmd_digest_t *dig,
+	uint32 actionid, const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen);
+
+/* iov get handler - process subcommand specific input and return output.
+ * input and output may overlap, so the callee needs to check if
+ * that is supported. For xtlv data a tlv digest is provided to make
+ * parsing simpler. Output tlvs may be packed into output buffer using
+ * bcm xtlv support. olen is input/output parameter. On input contains
+ * max available obuf length and callee must fill the correct length
+ * to represent the length of output returned.
+ */
+typedef int (*bcm_iov_cmd_get_t)(const bcm_iov_cmd_digest_t *dig,
+	const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen);
+
+/* iov set handler - process subcommand specific input and return output
+ * input and output may overlap, so the callee needs to check if
+ * that is supported. olen is input/output parameter. On input contains
+ * max available obuf length and callee must fill the correct length
+ * to represent the length of output returned.
+ */
+typedef int (*bcm_iov_cmd_set_t)(const bcm_iov_cmd_digest_t *dig,
+	const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen);
+
+/* iov (sub-cmd) batch - a vector of commands. count can be zero
+ * to support a version query. Each command is a tlv - whose data
+ * portion may have an optional return status, followed by a fixed
+ * length data header, optionally followed by tlvs.
+ *    cmd = type|length|<status|options>[header][tlvs]
+ */
+
+/*
+ * Batch sub-commands have status length included in the
+ * response length packed in TLV.
+ */
+#define BCM_IOV_STATUS_LEN sizeof(uint32)
+
+/* batch version is indicated by setting high bit. */
+#define BCM_IOV_BATCH_MASK 0x8000
+
+/*
+ * Batched commands will have the following memory layout
+ * +--------+---------+-----+-------+
+ * |version |count    | pad |sub-cmd|
+ * +--------+---------+-----+-------+
+ * version >= 0x8000
+ * count = number of sub-commands encoded in the iov buf
+ * sub-cmd one or more sub-commands for processing
+ * Where sub-cmd is padded byte buffer with memory layout as follows
+ * +--------+---------+-----------------------+-------------+------
+ * |cmd-id  |length   |IN(options) OUT(status)|command data |......
+ * +--------+---------+-----------------------+-------------+------
+ * cmd-id =sub-command ID
+ * length = length of this sub-command
+ * IN(options) = On input processing options/flags for this command
+ * OUT(status) on output processing status for this command
+ * command data = encapsulated IOVAR data as a single structure or packed TLVs for each
+ * individual sub-command.
+ */
+struct bcm_iov_batch_buf {
+	uint16 version;
+	uint8 count;
+	uint8 pad; /* Align sub-commands on 32 bit boundary */
+	bcm_xtlv_t cmds[1];
+};
+
+/* non-batched command version = major|minor w/ major <= 127 */
+struct bcm_iov_buf {
+	uint16 version;
+	uint16 len;
+	bcm_iov_cmd_id_t id;
+	uint16 data[1]; /* 32 bit alignment may be repurposed by the command */
+	/* command specific data follows */
+};
+
+struct bcm_iov_batch_subcmd {
+	uint16 id;
+	uint16 len;
+	union {
+		uint32 options;
+		uint32 status;
+	} u;
+	uint8 data[1];
+};
+
+/* iov options flags */
+enum {
+	BCM_IOV_CMD_OPT_ALIGN_NONE = 0x0000,
+	BCM_IOV_CMD_OPT_ALIGN32 = 0x0001,
+	BCM_IOV_CMD_OPT_TERMINATE_SUB_CMDS = 0x0002
+};
+
+/* iov command flags */
+enum {
+	BCM_IOV_CMD_FLAG_NONE = 0,
+	BCM_IOV_CMD_FLAG_STATUS_PRESENT = (1 << 0), /* status present at data start - output only */
+	BCM_IOV_CMD_FLAG_XTLV_DATA = (1 << 1),  /* data is a set of xtlvs */
+	BCM_IOV_CMD_FLAG_HDR_IN_LEN = (1 << 2), /* length starts at version - non-bacthed only */
+	BCM_IOV_CMD_FLAG_NOPAD = (1 << 3) /* No padding needed after iov_buf */
+};
+
+/* information about the command, xtlv options and xtlvs_off are meaningful
+ * only if XTLV_DATA cmd flag is selected
+ */
+struct bcm_iov_cmd_info {
+    bcm_iov_cmd_id_t		cmd;		/* the (sub)command - module specific */
+    bcm_iov_cmd_flags_t		flags;
+    bcm_iov_cmd_iovf_t		iovf;		/* IOV flags - same as for normal iovars */
+    bcm_xtlv_opts_t		xtlv_opts;
+	bcm_iov_cmd_validate_t	validate_h;	/* command validation handler */
+    bcm_iov_cmd_get_t		get_h;
+    bcm_iov_cmd_set_t		set_h;
+	uint16			xtlvs_off;	/* offset to beginning of xtlvs in cmd data */
+	uint16			min_len_set;
+	uint16			max_len_set;
+	uint16			min_len_get;
+	uint16			max_len_get;
+};
+
+/* tlv digest to support parsing of xtlvs for commands w/ tlv data; the tlv
+ * digest is available in the handler for the command. The count and order in
+ * which tlvs appear in the digest are exactly the same as the order of tlvs
+ * passed in the registration for the command. Unknown tlvs are ignored.
+ * If registered tlvs are missing datap will be NULL. common iov rocessing
+ * acquires an input digest to process input buffer. The handler is responsible
+ * for constructing an output digest and use packing functions to generate
+ * the output buffer. The handler may use the input digest as output digest once
+ * the tlv data is extracted and used. Multiple tlv support involves allocation of
+ * tlp nodes, except the first, as required,
+ */
+
+/* tlp data type indicates if the data is not used/invalid, input or output */
+enum {
+	BCM_IOV_TLP_NODE_INVALID = 0,
+	BCM_IOV_TLP_NODE_IN = 1,
+	BCM_IOV_TLP_NODE_OUT = 2
+};
+
+struct bcm_iov_tlp {
+	uint16 type;
+	uint16 len;
+	uint16 nodeix;	/* node index */
+};
+
+/* tlp data for a given tlv - multiple tlvs of same type chained */
+struct bcm_iov_tlp_node {
+	uint8 *next;	/* multiple tlv support */
+	bcm_iov_tlp_data_type_t type;
+	uint8 *data;	/* pointer to data in buffer or state */
+};
+
+struct bcm_iov_cmd_digest {
+	uint32 version;		/* Version */
+	void *cmd_ctx;
+	struct wlc_bsscfg *bsscfg;
+	const bcm_iov_cmd_info_t *cmd_info;
+	uint16 max_tlps;	/* number of tlps allocated */
+	uint16 max_nodes;	/* number of nods allocated */
+	uint16 num_tlps;	/* number of tlps valid */
+	uint16 num_nodes;	/* number of nods valid */
+	uint16 tlps_off;	/* offset to tlps */
+	uint16 nodes_off;	/* offset to nodes */
+	/*
+	 * bcm_iov_tlp_t tlps[max_tlps];
+	 * bcm_iov_tlp_node_t nodes[max_nodes]
+	*/
+};
+
+/* get length callback - default length is min_len taken from digest */
+typedef size_t (*bcm_iov_xtlv_get_len_t)(const bcm_iov_cmd_digest_t *dig,
+	const bcm_iov_cmd_tlv_info_t *tlv_info);
+
+/* pack to buffer data callback. under some conditions it might
+ * not be a straight copy and can refer to context(ual) information and
+ * endian conversions...
+ */
+typedef void (*bcm_iov_xtlv_pack_t)(const bcm_iov_cmd_digest_t *dig,
+	const bcm_iov_cmd_tlv_info_t *tlv_info,
+	uint8 *out_buf, const uint8 *in_data, size_t len);
+
+struct bcm_iov_cmd_tlv_info {
+	uint16 id;
+	uint16 min_len; /* inclusive */
+	uint16 max_len; /* inclusive */
+	bcm_iov_xtlv_get_len_t get_len;
+	bcm_iov_xtlv_pack_t pack;
+};
+
+/*
+ * module private parse context. Default version type len is uint16
+ */
+enum {
+	BCM_IOV_PARSE_CMD_NONE = 0
+};
+typedef uint32 parse_context_opts_t;
+
+/* get digest callback */
+typedef int (*bcm_iov_get_digest_t)(void *cmd_ctx, bcm_iov_cmd_digest_t **dig);
+
+typedef struct bcm_iov_parse_config {
+	parse_context_opts_t options; /* to handle different ver lengths */
+	bcm_iov_malloc_t alloc_fn;
+	bcm_iov_free_t free_fn;
+	bcm_iov_get_digest_t dig_fn;
+	int max_regs;
+	void *alloc_ctx;
+} bcm_iov_parse_config_t;
+
+/* API */
+
+/* All calls return an integer status code BCME_* unless otherwise indicated */
+
+/* return length of allocation for 'num_cmds' commands. data_len
+ * includes length of data for all the commands excluding the headers
+ */
+size_t bcm_iov_get_alloc_len(int num_cmds, size_t data_len);
+
+/* create parsing context using allocator provided; max_regs provides
+ * the number of allowed registrations for commands using the context
+ * sub-components of a module may register their own commands indepdently
+ * using the parsing context. If digest callback is NULL or returns NULL,
+ * the (input) digest is allocated using the provided allocators and released on
+ * completion of processing.
+ */
+int bcm_iov_create_parse_context(const bcm_iov_parse_config_t *parse_cfg,
+	bcm_iov_parse_context_t **parse_ctx);
+
+/* free the parsing context; ctx is set to NULL on exit */
+int bcm_iov_free_parse_context(bcm_iov_parse_context_t **ctx, bcm_iov_free_t free_fn);
+
+/* Return the command context for the module */
+void *bcm_iov_get_cmd_ctx_info(bcm_iov_parse_context_t *parse_ctx);
+
+/* register a command info vector along with supported tlvs. Each command
+ * may support a subset of tlvs
+ */
+int bcm_iov_register_commands(bcm_iov_parse_context_t *parse_ctx, void *cmd_ctx,
+	const bcm_iov_cmd_info_t *info, size_t num_cmds,
+	const bcm_iov_cmd_tlv_info_t *tlv_info, size_t num_tlvs);
+
+/* pack the xtlvs provided in the digest. may returns BCME_BUFTOOSHORT, but the
+ * out_len is set to required length in that case.
+ */
+int bcm_iov_pack_xtlvs(const bcm_iov_cmd_digest_t *dig,  bcm_xtlv_opts_t xtlv_opts,
+	uint8 *out_buf, size_t out_size, size_t *out_len);
+
+#ifdef BCMDRIVER
+/* wlc modules register their iovar(s) using the parsing context w/ wlc layer
+ * during attach.
+ */
+struct wlc_if;
+struct wlc_info;
+extern struct wlc_bsscfg *bcm_iov_bsscfg_find_from_wlcif(struct wlc_info *wlc,
+	struct wlc_if *wlcif);
+int bcm_iov_doiovar(void *parse_ctx, uint32 id, void *params, uint params_len,
+    void *arg, uint arg_len, uint vsize, struct wlc_if *intf);
+#endif /* BCMDRIVER */
+
+/* parsing context helpers */
+
+/* get the maximum number of tlvs - can be used to allocate digest for all
+ * commands. the digest can be shared. Negative values are BCM_*, >=0, the
+ * number of tlvs
+ */
+int  bcm_iov_parse_get_max_tlvs(const bcm_iov_parse_context_t *ctx);
+
+/* common packing support */
+
+/* pack a buffer of uint8s - memcpy wrapper */
+int bcm_iov_pack_buf(const bcm_iov_cmd_digest_t *dig, uint8 *buf,
+	const uint8 *data, size_t len);
+
+#define bcm_iov_packv_u8 bcm_iov_pack_buf
+
+/*
+ * pack a buffer with uint16s - serialized in LE order, data points to uint16
+ * length is not checked.
+ */
+int bcm_iov_packv_u16(const bcm_iov_cmd_digest_t *dig, uint8 *buf,
+	const uint16 *data, int n);
+
+/*
+ * pack a buffer with uint32s - serialized in LE order - data points to uint32
+ * length is not checked.
+ */
+int bcm_iov_packv_u32(const bcm_iov_cmd_digest_t *dig, uint8 *buf,
+	const uint32 *data, int n);
+
+#endif /* _bcmiov_h_ */
diff --git a/wl/src/include/bcmnvram.h b/wl/src/include/bcmnvram.h
new file mode 100644
index 0000000..b6d0101
--- /dev/null
+++ b/wl/src/include/bcmnvram.h
@@ -0,0 +1,329 @@
+/*
+ * NVRAM variable manipulation
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmnvram.h 655606 2016-08-22 17:16:11Z $
+ */
+
+#ifndef _bcmnvram_h_
+#define _bcmnvram_h_
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+#include <typedefs.h>
+#include <bcmdefs.h>
+
+struct nvram_header {
+	uint32 magic;
+	uint32 len;
+	uint32 crc_ver_init;	/* 0:7 crc, 8:15 ver, 16:31 sdram_init */
+	uint32 config_refresh;	/* 0:15 sdram_config, 16:31 sdram_refresh */
+	uint32 config_ncdl;	/* ncdl values for memc */
+};
+
+struct nvram_tuple {
+	char *name;
+	char *value;
+	struct nvram_tuple *next;
+};
+
+/*
+ * Get default value for an NVRAM variable
+ */
+extern char *nvram_default_get(const char *name);
+/*
+ * validate/restore all per-interface related variables
+ */
+extern void nvram_validate_all(char *prefix, bool restore);
+
+/*
+ * restore specific per-interface variable
+ */
+extern void nvram_restore_var(char *prefix, char *name);
+
+/*
+ * Initialize NVRAM access. May be unnecessary or undefined on certain
+ * platforms.
+ */
+extern int nvram_init(void *sih);
+extern int nvram_deinit(void *sih);
+
+
+extern int nvram_file_read(char **nvramp, int *nvraml);
+
+/*
+ * Append a chunk of nvram variables to the global list
+ */
+extern int nvram_append(void *si, char *vars, uint varsz);
+
+extern void nvram_get_global_vars(char **varlst, uint *varsz);
+
+
+/*
+ * Check for reset button press for restoring factory defaults.
+ */
+extern int nvram_reset(void *sih);
+
+/*
+ * Disable NVRAM access. May be unnecessary or undefined on certain
+ * platforms.
+ */
+extern void nvram_exit(void *sih);
+
+/*
+ * Get the value of an NVRAM variable. The pointer returned may be
+ * invalid after a set.
+ * @param	name	name of variable to get
+ * @return	value of variable or NULL if undefined
+ */
+extern char * nvram_get(const char *name);
+
+/*
+ * Get the value of an NVRAM variable. The pointer returned may be
+ * invalid after a set.
+ * @param	name	name of variable to get
+ * @param	bit	bit value to get
+ * @return	value of variable or NULL if undefined
+ */
+extern char * nvram_get_bitflag(const char *name, const int bit);
+
+/*
+ * Read the reset GPIO value from the nvram and set the GPIO
+ * as input
+ */
+extern int BCMINITFN(nvram_resetgpio_init)(void *sih);
+
+/*
+ * Get the value of an NVRAM variable.
+ * @param	name	name of variable to get
+ * @return	value of variable or NUL if undefined
+ */
+static INLINE char *
+nvram_safe_get(const char *name)
+{
+	char *p = nvram_get(name);
+	return p ? p : "";
+}
+
+/*
+ * Match an NVRAM variable.
+ * @param	name	name of variable to match
+ * @param	match	value to compare against value of variable
+ * @return	TRUE if variable is defined and its value is string equal
+ *		to match or FALSE otherwise
+ */
+static INLINE int
+nvram_match(const char *name, const char *match)
+{
+	const char *value = nvram_get(name);
+
+	/* In nvramstubs.c builds, nvram_get() is defined as returning zero,
+	* so the return line below never executes the strcmp(),
+	* resulting in 'match' being an unused parameter.
+	* Make a ref to 'match' to quiet the compiler warning.
+	*/
+
+	BCM_REFERENCE(match);
+
+	return (value && !strcmp(value, match));
+}
+
+/*
+ * Match an NVRAM variable.
+ * @param	name	name of variable to match
+ * @param	bit	bit value to get
+ * @param	match	value to compare against value of variable
+ * @return	TRUE if variable is defined and its value is string equal
+ *		to match or FALSE otherwise
+ */
+static INLINE int
+nvram_match_bitflag(const char *name, const int bit, const char *match)
+{
+	const char *value = nvram_get_bitflag(name, bit);
+	BCM_REFERENCE(match);
+	return (value && !strcmp(value, match));
+}
+
+/*
+ * Inversely match an NVRAM variable.
+ * @param	name	name of variable to match
+ * @param	match	value to compare against value of variable
+ * @return	TRUE if variable is defined and its value is not string
+ *		equal to invmatch or FALSE otherwise
+ */
+static INLINE int
+nvram_invmatch(const char *name, const char *invmatch)
+{
+	const char *value = nvram_get(name);
+
+	/* In nvramstubs.c builds, nvram_get() is defined as returning zero,
+	* so the return line below never executes the strcmp(),
+	* resulting in 'invmatch' being an unused parameter.
+	* Make a ref to 'invmatch' to quiet the compiler warning.
+	*/
+
+	BCM_REFERENCE(invmatch);
+
+	return (value && strcmp(value, invmatch));
+}
+
+/*
+ * Set the value of an NVRAM variable. The name and value strings are
+ * copied into private storage. Pointers to previously set values
+ * may become invalid. The new value may be immediately
+ * retrieved but will not be permanently stored until a commit.
+ * @param	name	name of variable to set
+ * @param	value	value of variable
+ * @return	0 on success and errno on failure
+ */
+extern int nvram_set(const char *name, const char *value);
+
+/*
+ * Set the value of an NVRAM variable. The name and value strings are
+ * copied into private storage. Pointers to previously set values
+ * may become invalid. The new value may be immediately
+ * retrieved but will not be permanently stored until a commit.
+ * @param	name	name of variable to set
+ * @param	bit	bit value to set
+ * @param	value	value of variable
+ * @return	0 on success and errno on failure
+ */
+extern int nvram_set_bitflag(const char *name, const int bit, const int value);
+/*
+ * Unset an NVRAM variable. Pointers to previously set values
+ * remain valid until a set.
+ * @param	name	name of variable to unset
+ * @return	0 on success and errno on failure
+ * NOTE: use nvram_commit to commit this change to flash.
+ */
+extern int nvram_unset(const char *name);
+
+/*
+ * Commit NVRAM variables to permanent storage. All pointers to values
+ * may be invalid after a commit.
+ * NVRAM values are undefined after a commit.
+ * @param   nvram_corrupt    true to corrupt nvram, false otherwise.
+ * @return	0 on success and errno on failure
+ */
+extern int nvram_commit_internal(bool nvram_corrupt);
+
+/*
+ * Commit NVRAM variables to permanent storage. All pointers to values
+ * may be invalid after a commit.
+ * NVRAM values are undefined after a commit.
+ * @return	0 on success and errno on failure
+ */
+extern int nvram_commit(void);
+
+/*
+ * Get all NVRAM variables (format name=value\0 ... \0\0).
+ * @param	buf	buffer to store variables
+ * @param	count	size of buffer in bytes
+ * @return	0 on success and errno on failure
+ */
+extern int nvram_getall(char *nvram_buf, int count);
+
+/*
+ * returns the crc value of the nvram
+ * @param	nvh	nvram header pointer
+ */
+uint8 nvram_calc_crc(struct nvram_header * nvh);
+
+extern int nvram_space;
+#endif /* _LANGUAGE_ASSEMBLY */
+
+/* The NVRAM version number stored as an NVRAM variable */
+#define NVRAM_SOFTWARE_VERSION	"1"
+
+#define NVRAM_MAGIC		0x48534C46	/* 'FLSH' */
+#define NVRAM_CLEAR_MAGIC	0x0
+#define NVRAM_INVALID_MAGIC	0xFFFFFFFF
+#define NVRAM_VERSION		1
+#define NVRAM_HEADER_SIZE	20
+/* This definition is for precommit staging, and will be removed */
+#define NVRAM_SPACE		0x8000
+/* For CFE builds this gets passed in thru the makefile */
+#ifndef MAX_NVRAM_SPACE
+#define MAX_NVRAM_SPACE		0x10000
+#endif
+#define DEF_NVRAM_SPACE		0x8000
+#define ROM_ENVRAM_SPACE	0x1000
+#define NVRAM_LZMA_MAGIC	0x4c5a4d41	/* 'LZMA' */
+
+#define NVRAM_MAX_VALUE_LEN 255
+#define NVRAM_MAX_PARAM_LEN 64
+
+#define NVRAM_CRC_START_POSITION	9 /* magic, len, crc8 to be skipped */
+#define NVRAM_CRC_VER_MASK	0xffffff00 /* for crc_ver_init */
+
+/* Offsets to embedded nvram area */
+#define NVRAM_START_COMPRESSED	0x400
+#define NVRAM_START		0x1000
+
+#define BCM_JUMBO_NVRAM_DELIMIT '\n'
+#define BCM_JUMBO_START "Broadcom Jumbo Nvram file"
+
+#if !defined(BCMDONGLEHOST) && defined(BCMTRXV2)
+extern char *_vars;
+extern uint _varsz;
+#endif  /* !defined(BCMDONGLEHOST) && defined(BCMTRXV2) */
+
+#if (defined(FAILSAFE_UPGRADE) || defined(CONFIG_FAILSAFE_UPGRADE) || \
+	defined(__CONFIG_FAILSAFE_UPGRADE_SUPPORT__))
+#define IMAGE_SIZE "image_size"
+#define BOOTPARTITION "bootpartition"
+#define IMAGE_BOOT BOOTPARTITION
+#define PARTIALBOOTS "partialboots"
+#define MAXPARTIALBOOTS "maxpartialboots"
+#define IMAGE_1ST_FLASH_TRX "flash0.trx"
+#define IMAGE_1ST_FLASH_OS "flash0.os"
+#define IMAGE_2ND_FLASH_TRX "flash0.trx2"
+#define IMAGE_2ND_FLASH_OS "flash0.os2"
+#define IMAGE_FIRST_OFFSET "image_first_offset"
+#define IMAGE_SECOND_OFFSET "image_second_offset"
+#define LINUX_FIRST "linux"
+#define LINUX_SECOND "linux2"
+#endif
+
+#if (defined(DUAL_IMAGE) || defined(CONFIG_DUAL_IMAGE) || \
+	defined(__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__))
+/* Shared by all: CFE, Linux Kernel, and Ap */
+#define IMAGE_BOOT "image_boot"
+#define BOOTPARTITION IMAGE_BOOT
+/* CFE variables */
+#define IMAGE_1ST_FLASH_TRX "flash0.trx"
+#define IMAGE_1ST_FLASH_OS "flash0.os"
+#define IMAGE_2ND_FLASH_TRX "flash0.trx2"
+#define IMAGE_2ND_FLASH_OS "flash0.os2"
+#define IMAGE_SIZE "image_size"
+
+/* CFE and Linux Kernel shared variables */
+#define IMAGE_FIRST_OFFSET "image_first_offset"
+#define IMAGE_SECOND_OFFSET "image_second_offset"
+
+/* Linux application variables */
+#define LINUX_FIRST "linux"
+#define LINUX_SECOND "linux2"
+#define POLICY_TOGGLE "toggle"
+#define LINUX_PART_TO_FLASH "linux_to_flash"
+#define LINUX_FLASH_POLICY "linux_flash_policy"
+
+#endif /* defined(DUAL_IMAGE||CONFIG_DUAL_IMAGE)||__CONFIG_DUAL_IMAGE_FLASH_SUPPORT__ */
+
+#endif /* _bcmnvram_h_ */
diff --git a/wl/src/include/bcmsrom_fmt.h b/wl/src/include/bcmsrom_fmt.h
new file mode 100644
index 0000000..47a5073
--- /dev/null
+++ b/wl/src/include/bcmsrom_fmt.h
@@ -0,0 +1,969 @@
+/*
+ * SROM format definition.
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmsrom_fmt.h 657898 2016-09-03 00:25:48Z $
+ */
+
+#ifndef	_bcmsrom_fmt_h_
+#define	_bcmsrom_fmt_h_
+
+#define SROM_MAXREV		15	/* max revision supported by driver */
+
+/* Maximum srom: 16 Kilobits == 2048 bytes */
+
+#define	SROM_MAX		2048
+#define SROM_MAXW		594
+
+#ifdef LARGE_NVRAM_MAXSZ
+#define VARS_MAX		LARGE_NVRAM_MAXSZ
+#else
+#if defined(BCMROMBUILD) || defined(DONGLEBUILD)
+#define VARS_MAX		4096
+#else
+#define LARGE_NVRAM_MAXSZ	8192
+#define VARS_MAX		LARGE_NVRAM_MAXSZ
+#endif /* BCMROMBUILD || DONGLEBUILD */
+#endif /* LARGE_NVRAM_MAXSZ */
+
+/* PCI fields */
+#define PCI_F0DEVID		48
+
+
+#define	SROM_WORDS		64
+
+#define SROM3_SWRGN_OFF		28	/* s/w region offset in words */
+
+#define	SROM_SSID		2
+#define	SROM_SVID		3
+
+#define	SROM_WL1LHMAXP		29
+
+#define	SROM_WL1LPAB0		30
+#define	SROM_WL1LPAB1		31
+#define	SROM_WL1LPAB2		32
+
+#define	SROM_WL1HPAB0		33
+#define	SROM_WL1HPAB1		34
+#define	SROM_WL1HPAB2		35
+
+#define	SROM_MACHI_IL0		36
+#define	SROM_MACMID_IL0		37
+#define	SROM_MACLO_IL0		38
+#define	SROM_MACHI_ET0		39
+#define	SROM_MACMID_ET0		40
+#define	SROM_MACLO_ET0		41
+#define	SROM_MACHI_ET1		42
+#define	SROM_MACMID_ET1		43
+#define	SROM_MACLO_ET1		44
+#define	SROM3_MACHI		37
+#define	SROM3_MACMID		38
+#define	SROM3_MACLO		39
+
+#define	SROM_BXARSSI2G		40
+#define	SROM_BXARSSI5G		41
+
+#define	SROM_TRI52G		42
+#define	SROM_TRI5GHL		43
+
+#define	SROM_RXPO52G		45
+
+#define	SROM2_ENETPHY		45
+
+#define	SROM_AABREV		46
+/* Fields in AABREV */
+#define	SROM_BR_MASK		0x00ff
+#define	SROM_CC_MASK		0x0f00
+#define	SROM_CC_SHIFT		8
+#define	SROM_AA0_MASK		0x3000
+#define	SROM_AA0_SHIFT		12
+#define	SROM_AA1_MASK		0xc000
+#define	SROM_AA1_SHIFT		14
+
+#define	SROM_WL0PAB0		47
+#define	SROM_WL0PAB1		48
+#define	SROM_WL0PAB2		49
+
+#define	SROM_LEDBH10		50
+#define	SROM_LEDBH32		51
+
+#define	SROM_WL10MAXP		52
+
+#define	SROM_WL1PAB0		53
+#define	SROM_WL1PAB1		54
+#define	SROM_WL1PAB2		55
+
+#define	SROM_ITT		56
+
+#define	SROM_BFL		57
+#define	SROM_BFL2		28
+#define	SROM3_BFL2		61
+
+#define	SROM_AG10		58
+
+#define	SROM_CCODE		59
+
+#define	SROM_OPO		60
+
+#define	SROM3_LEDDC		62
+
+#define	SROM_CRCREV		63
+
+/* SROM Rev 4: Reallocate the software part of the srom to accomodate
+ * MIMO features. It assumes up to two PCIE functions and 440 bytes
+ * of useable srom i.e. the useable storage in chips with OTP that
+ * implements hardware redundancy.
+ */
+
+#define	SROM4_WORDS		220
+
+#define	SROM4_SIGN		32
+#define	SROM4_SIGNATURE		0x5372
+
+#define	SROM4_BREV		33
+
+#define	SROM4_BFL0		34
+#define	SROM4_BFL1		35
+#define	SROM4_BFL2		36
+#define	SROM4_BFL3		37
+#define	SROM5_BFL0		37
+#define	SROM5_BFL1		38
+#define	SROM5_BFL2		39
+#define	SROM5_BFL3		40
+
+#define	SROM4_MACHI		38
+#define	SROM4_MACMID		39
+#define	SROM4_MACLO		40
+#define	SROM5_MACHI		41
+#define	SROM5_MACMID		42
+#define	SROM5_MACLO		43
+
+#define	SROM4_CCODE		41
+#define	SROM4_REGREV		42
+#define	SROM5_CCODE		34
+#define	SROM5_REGREV		35
+
+#define	SROM4_LEDBH10		43
+#define	SROM4_LEDBH32		44
+#define	SROM5_LEDBH10		59
+#define	SROM5_LEDBH32		60
+
+#define	SROM4_LEDDC		45
+#define	SROM5_LEDDC		45
+
+#define	SROM4_AA		46
+#define	SROM4_AA2G_MASK		0x00ff
+#define	SROM4_AA2G_SHIFT	0
+#define	SROM4_AA5G_MASK		0xff00
+#define	SROM4_AA5G_SHIFT	8
+
+#define	SROM4_AG10		47
+#define	SROM4_AG32		48
+
+#define	SROM4_TXPID2G		49
+#define	SROM4_TXPID5G		51
+#define	SROM4_TXPID5GL		53
+#define	SROM4_TXPID5GH		55
+
+#define SROM4_TXRXC		61
+#define SROM4_TXCHAIN_MASK	0x000f
+#define SROM4_TXCHAIN_SHIFT	0
+#define SROM4_RXCHAIN_MASK	0x00f0
+#define SROM4_RXCHAIN_SHIFT	4
+#define SROM4_SWITCH_MASK	0xff00
+#define SROM4_SWITCH_SHIFT	8
+
+
+/* Per-path fields */
+#define	MAX_PATH_SROM		4
+#define	SROM4_PATH0		64
+#define	SROM4_PATH1		87
+#define	SROM4_PATH2		110
+#define	SROM4_PATH3		133
+
+#define	SROM4_2G_ITT_MAXP	0
+#define	SROM4_2G_PA		1
+#define	SROM4_5G_ITT_MAXP	5
+#define	SROM4_5GLH_MAXP		6
+#define	SROM4_5G_PA		7
+#define	SROM4_5GL_PA		11
+#define	SROM4_5GH_PA		15
+
+/* Fields in the ITT_MAXP and 5GLH_MAXP words */
+#define	B2G_MAXP_MASK		0xff
+#define	B2G_ITT_SHIFT		8
+#define	B5G_MAXP_MASK		0xff
+#define	B5G_ITT_SHIFT		8
+#define	B5GH_MAXP_MASK		0xff
+#define	B5GL_MAXP_SHIFT		8
+
+/* All the miriad power offsets */
+#define	SROM4_2G_CCKPO		156
+#define	SROM4_2G_OFDMPO		157
+#define	SROM4_5G_OFDMPO		159
+#define	SROM4_5GL_OFDMPO	161
+#define	SROM4_5GH_OFDMPO	163
+#define	SROM4_2G_MCSPO		165
+#define	SROM4_5G_MCSPO		173
+#define	SROM4_5GL_MCSPO		181
+#define	SROM4_5GH_MCSPO		189
+#define	SROM4_CDDPO		197
+#define	SROM4_STBCPO		198
+#define	SROM4_BW40PO		199
+#define	SROM4_BWDUPPO		200
+
+#define	SROM4_CRCREV		219
+
+
+/* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6.
+ * This is acombined srom for both MIMO and SISO boards, usable in
+ * the .130 4Kilobit OTP with hardware redundancy.
+ */
+
+#define	SROM8_SIGN		64
+
+#define	SROM8_BREV		65
+
+#define	SROM8_BFL0		66
+#define	SROM8_BFL1		67
+#define	SROM8_BFL2		68
+#define	SROM8_BFL3		69
+
+#define	SROM8_MACHI		70
+#define	SROM8_MACMID		71
+#define	SROM8_MACLO		72
+
+#define	SROM8_CCODE		73
+#define	SROM8_REGREV		74
+
+#define	SROM8_LEDBH10		75
+#define	SROM8_LEDBH32		76
+
+#define	SROM8_LEDDC		77
+
+#define	SROM8_AA		78
+
+#define	SROM8_AG10		79
+#define	SROM8_AG32		80
+
+#define	SROM8_TXRXC		81
+
+#define	SROM8_BXARSSI2G		82
+#define	SROM8_BXARSSI5G		83
+#define	SROM8_TRI52G		84
+#define	SROM8_TRI5GHL		85
+#define	SROM8_RXPO52G		86
+
+#define SROM8_FEM2G		87
+#define SROM8_FEM5G		88
+#define SROM8_FEM_ANTSWLUT_MASK		0xf800
+#define SROM8_FEM_ANTSWLUT_SHIFT	11
+#define SROM8_FEM_TR_ISO_MASK		0x0700
+#define SROM8_FEM_TR_ISO_SHIFT		8
+#define SROM8_FEM_PDET_RANGE_MASK	0x00f8
+#define SROM8_FEM_PDET_RANGE_SHIFT	3
+#define SROM8_FEM_EXTPA_GAIN_MASK	0x0006
+#define SROM8_FEM_EXTPA_GAIN_SHIFT	1
+#define SROM8_FEM_TSSIPOS_MASK		0x0001
+#define SROM8_FEM_TSSIPOS_SHIFT		0
+
+#define SROM8_THERMAL		89
+
+/* Temp sense related entries */
+#define SROM8_MPWR_RAWTS		90
+#define SROM8_TS_SLP_OPT_CORRX	91
+/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
+#define SROM8_FOC_HWIQ_IQSWP	92
+
+#define SROM8_EXTLNAGAIN        93
+
+/* Temperature delta for PHY calibration */
+#define SROM8_PHYCAL_TEMPDELTA	94
+
+/* Measured power 1 & 2, 0-13 bits at offset 95, MSB 2 bits are unused for now. */
+#define SROM8_MPWR_1_AND_2	95
+
+
+/* Per-path offsets & fields */
+#define	SROM8_PATH0		96
+#define	SROM8_PATH1		112
+#define	SROM8_PATH2		128
+#define	SROM8_PATH3		144
+
+#define	SROM8_2G_ITT_MAXP	0
+#define	SROM8_2G_PA		1
+#define	SROM8_5G_ITT_MAXP	4
+#define	SROM8_5GLH_MAXP		5
+#define	SROM8_5G_PA		6
+#define	SROM8_5GL_PA		9
+#define	SROM8_5GH_PA		12
+
+/* All the miriad power offsets */
+#define	SROM8_2G_CCKPO		160
+
+#define	SROM8_2G_OFDMPO		161
+#define	SROM8_5G_OFDMPO		163
+#define	SROM8_5GL_OFDMPO	165
+#define	SROM8_5GH_OFDMPO	167
+
+#define	SROM8_2G_MCSPO		169
+#define	SROM8_5G_MCSPO		177
+#define	SROM8_5GL_MCSPO		185
+#define	SROM8_5GH_MCSPO		193
+
+#define	SROM8_CDDPO		201
+#define	SROM8_STBCPO		202
+#define	SROM8_BW40PO		203
+#define	SROM8_BWDUPPO		204
+
+/* SISO PA parameters are in the path0 spaces */
+#define	SROM8_SISO		96
+
+/* Legacy names for SISO PA paramters */
+#define	SROM8_W0_ITTMAXP	(SROM8_SISO + SROM8_2G_ITT_MAXP)
+#define	SROM8_W0_PAB0		(SROM8_SISO + SROM8_2G_PA)
+#define	SROM8_W0_PAB1		(SROM8_SISO + SROM8_2G_PA + 1)
+#define	SROM8_W0_PAB2		(SROM8_SISO + SROM8_2G_PA + 2)
+#define	SROM8_W1_ITTMAXP	(SROM8_SISO + SROM8_5G_ITT_MAXP)
+#define	SROM8_W1_MAXP_LCHC	(SROM8_SISO + SROM8_5GLH_MAXP)
+#define	SROM8_W1_PAB0		(SROM8_SISO + SROM8_5G_PA)
+#define	SROM8_W1_PAB1		(SROM8_SISO + SROM8_5G_PA + 1)
+#define	SROM8_W1_PAB2		(SROM8_SISO + SROM8_5G_PA + 2)
+#define	SROM8_W1_PAB0_LC	(SROM8_SISO + SROM8_5GL_PA)
+#define	SROM8_W1_PAB1_LC	(SROM8_SISO + SROM8_5GL_PA + 1)
+#define	SROM8_W1_PAB2_LC	(SROM8_SISO + SROM8_5GL_PA + 2)
+#define	SROM8_W1_PAB0_HC	(SROM8_SISO + SROM8_5GH_PA)
+#define	SROM8_W1_PAB1_HC	(SROM8_SISO + SROM8_5GH_PA + 1)
+#define	SROM8_W1_PAB2_HC	(SROM8_SISO + SROM8_5GH_PA + 2)
+
+#define	SROM8_CRCREV		219
+
+/* SROM REV 9 */
+#define SROM9_2GPO_CCKBW20	160
+#define SROM9_2GPO_CCKBW20UL	161
+#define SROM9_2GPO_LOFDMBW20	162
+#define SROM9_2GPO_LOFDMBW20UL	164
+
+#define SROM9_5GLPO_LOFDMBW20	166
+#define SROM9_5GLPO_LOFDMBW20UL	168
+#define SROM9_5GMPO_LOFDMBW20	170
+#define SROM9_5GMPO_LOFDMBW20UL	172
+#define SROM9_5GHPO_LOFDMBW20	174
+#define SROM9_5GHPO_LOFDMBW20UL	176
+
+#define SROM9_2GPO_MCSBW20	178
+#define SROM9_2GPO_MCSBW20UL	180
+#define SROM9_2GPO_MCSBW40	182
+
+#define SROM9_5GLPO_MCSBW20	184
+#define SROM9_5GLPO_MCSBW20UL	186
+#define SROM9_5GLPO_MCSBW40	188
+#define SROM9_5GMPO_MCSBW20	190
+#define SROM9_5GMPO_MCSBW20UL	192
+#define SROM9_5GMPO_MCSBW40	194
+#define SROM9_5GHPO_MCSBW20	196
+#define SROM9_5GHPO_MCSBW20UL	198
+#define SROM9_5GHPO_MCSBW40	200
+
+#define SROM9_PO_MCS32		202
+#define SROM9_PO_LOFDM40DUP	203
+#define SROM9_EU_EDCRSTH	204
+#define SROM10_EU_EDCRSTH	204
+#define SROM8_RXGAINERR_2G	205
+#define SROM8_RXGAINERR_5GL	206
+#define SROM8_RXGAINERR_5GM	207
+#define SROM8_RXGAINERR_5GH	208
+#define SROM8_RXGAINERR_5GU	209
+#define SROM8_SUBBAND_PPR	210
+#define SROM8_PCIEINGRESS_WAR	211
+#define SROM8_EU_EDCRSTH	212
+#define SROM9_SAR		212
+
+#define SROM8_NOISELVL_2G	213
+#define SROM8_NOISELVL_5GL	214
+#define SROM8_NOISELVL_5GM	215
+#define SROM8_NOISELVL_5GH	216
+#define SROM8_NOISELVL_5GU	217
+#define SROM8_NOISECALOFFSET	218
+
+#define SROM9_REV_CRC		219
+
+#define SROM10_CCKPWROFFSET	218
+#define SROM10_SIGN		219
+#define SROM10_SWCTRLMAP_2G	220
+#define SROM10_CRCREV		229
+
+#define	SROM10_WORDS		230
+#define	SROM10_SIGNATURE	SROM4_SIGNATURE
+
+
+/* SROM REV 11 */
+#define SROM11_BREV			65
+
+#define SROM11_BFL0			66
+#define SROM11_BFL1			67
+#define SROM11_BFL2			68
+#define SROM11_BFL3			69
+#define SROM11_BFL4			70
+#define SROM11_BFL5			71
+
+#define SROM11_MACHI			72
+#define SROM11_MACMID			73
+#define SROM11_MACLO			74
+
+#define SROM11_CCODE			75
+#define SROM11_REGREV			76
+
+#define SROM11_LEDBH10			77
+#define SROM11_LEDBH32			78
+
+#define SROM11_LEDDC			79
+
+#define SROM11_AA			80
+
+#define SROM11_AGBG10			81
+#define SROM11_AGBG2A0			82
+#define SROM11_AGA21			83
+
+#define SROM11_TXRXC			84
+
+#define SROM11_FEM_CFG1			85
+#define SROM11_FEM_CFG2			86
+
+/* Masks and offsets for FEM_CFG */
+#define SROM11_FEMCTRL_MASK		0xf800
+#define SROM11_FEMCTRL_SHIFT		11
+#define SROM11_PAPDCAP_MASK		0x0400
+#define SROM11_PAPDCAP_SHIFT		10
+#define SROM11_TWORANGETSSI_MASK	0x0200
+#define SROM11_TWORANGETSSI_SHIFT	9
+#define SROM11_PDGAIN_MASK		0x01f0
+#define SROM11_PDGAIN_SHIFT		4
+#define SROM11_EPAGAIN_MASK		0x000e
+#define SROM11_EPAGAIN_SHIFT		1
+#define SROM11_TSSIPOSSLOPE_MASK	0x0001
+#define SROM11_TSSIPOSSLOPE_SHIFT	0
+#define SROM11_GAINCTRLSPH_MASK		0xf800
+#define SROM11_GAINCTRLSPH_SHIFT	11
+
+#define SROM11_THERMAL			87
+#define SROM11_MPWR_RAWTS		88
+#define SROM11_TS_SLP_OPT_CORRX		89
+#define SROM11_XTAL_FREQ		90
+#define SROM11_5GB0_4080_W0_A1          91
+#define SROM11_PHYCAL_TEMPDELTA  	92
+#define SROM11_MPWR_1_AND_2 		93
+#define SROM11_5GB0_4080_W1_A1          94
+#define SROM11_TSSIFLOOR_2G 		95
+#define SROM11_TSSIFLOOR_5GL 		96
+#define SROM11_TSSIFLOOR_5GM 		97
+#define SROM11_TSSIFLOOR_5GH 		98
+#define SROM11_TSSIFLOOR_5GU 		99
+
+/* Masks and offsets for Thermal parameters */
+#define SROM11_TEMPS_PERIOD_MASK	0xf0
+#define SROM11_TEMPS_PERIOD_SHIFT	4
+#define SROM11_TEMPS_HYSTERESIS_MASK	0x0f
+#define SROM11_TEMPS_HYSTERESIS_SHIFT	0
+#define SROM11_TEMPCORRX_MASK		0xfc
+#define SROM11_TEMPCORRX_SHIFT		2
+#define SROM11_TEMPSENSE_OPTION_MASK	0x3
+#define SROM11_TEMPSENSE_OPTION_SHIFT	0
+
+#define SROM11_PDOFF_2G_40M_A0_MASK     0x000f
+#define SROM11_PDOFF_2G_40M_A0_SHIFT    0
+#define SROM11_PDOFF_2G_40M_A1_MASK     0x00f0
+#define SROM11_PDOFF_2G_40M_A1_SHIFT    4
+#define SROM11_PDOFF_2G_40M_A2_MASK     0x0f00
+#define SROM11_PDOFF_2G_40M_A2_SHIFT    8
+#define SROM11_PDOFF_2G_40M_VALID_MASK  0x8000
+#define SROM11_PDOFF_2G_40M_VALID_SHIFT 15
+
+#define SROM11_PDOFF_2G_40M     	100
+#define SROM11_PDOFF_40M_A0		101
+#define SROM11_PDOFF_40M_A1		102
+#define SROM11_PDOFF_40M_A2		103
+#define SROM11_5GB0_4080_W2_A1          103
+#define SROM11_PDOFF_80M_A0		104
+#define SROM11_PDOFF_80M_A1		105
+#define SROM11_PDOFF_80M_A2		106
+#define SROM11_5GB1_4080_W0_A1          106
+
+#define SROM11_SUBBAND5GVER 		107
+
+/* Per-path fields and offset */
+#define	MAX_PATH_SROM_11		3
+#define SROM11_PATH0			108
+#define SROM11_PATH1			128
+#define SROM11_PATH2			148
+
+#define	SROM11_2G_MAXP			0
+#define SROM11_5GB1_4080_PA             0
+#define	SROM11_2G_PA			1
+#define SROM11_5GB2_4080_PA             2
+#define	SROM11_RXGAINS1			4
+#define	SROM11_RXGAINS			5
+#define SROM11_5GB3_4080_PA             5
+#define	SROM11_5GB1B0_MAXP		6
+#define	SROM11_5GB3B2_MAXP		7
+#define	SROM11_5GB0_PA			8
+#define	SROM11_5GB1_PA			11
+#define	SROM11_5GB2_PA			14
+#define	SROM11_5GB3_PA			17
+
+/* Masks and offsets for rxgains */
+#define SROM11_RXGAINS5GTRELNABYPA_MASK		0x8000
+#define SROM11_RXGAINS5GTRELNABYPA_SHIFT	15
+#define SROM11_RXGAINS5GTRISOA_MASK		0x7800
+#define SROM11_RXGAINS5GTRISOA_SHIFT		11
+#define SROM11_RXGAINS5GELNAGAINA_MASK		0x0700
+#define SROM11_RXGAINS5GELNAGAINA_SHIFT		8
+#define SROM11_RXGAINS2GTRELNABYPA_MASK		0x0080
+#define SROM11_RXGAINS2GTRELNABYPA_SHIFT	7
+#define SROM11_RXGAINS2GTRISOA_MASK		0x0078
+#define SROM11_RXGAINS2GTRISOA_SHIFT		3
+#define SROM11_RXGAINS2GELNAGAINA_MASK		0x0007
+#define SROM11_RXGAINS2GELNAGAINA_SHIFT		0
+#define SROM11_RXGAINS5GHTRELNABYPA_MASK	0x8000
+#define SROM11_RXGAINS5GHTRELNABYPA_SHIFT	15
+#define SROM11_RXGAINS5GHTRISOA_MASK		0x7800
+#define SROM11_RXGAINS5GHTRISOA_SHIFT		11
+#define SROM11_RXGAINS5GHELNAGAINA_MASK		0x0700
+#define SROM11_RXGAINS5GHELNAGAINA_SHIFT	8
+#define SROM11_RXGAINS5GMTRELNABYPA_MASK	0x0080
+#define SROM11_RXGAINS5GMTRELNABYPA_SHIFT	7
+#define SROM11_RXGAINS5GMTRISOA_MASK		0x0078
+#define SROM11_RXGAINS5GMTRISOA_SHIFT		3
+#define SROM11_RXGAINS5GMELNAGAINA_MASK		0x0007
+#define SROM11_RXGAINS5GMELNAGAINA_SHIFT	0
+
+/* Power per rate */
+#define SROM11_CCKBW202GPO		168
+#define SROM11_CCKBW20UL2GPO		169
+#define SROM11_MCSBW202GPO		170
+#define SROM11_MCSBW202GPO_1		171
+#define SROM11_MCSBW402GPO		172
+#define SROM11_MCSBW402GPO_1		173
+#define SROM11_DOT11AGOFDMHRBW202GPO	174
+#define SROM11_OFDMLRBW202GPO		175
+
+#define SROM11_MCSBW205GLPO 		176
+#define SROM11_MCSBW205GLPO_1		177
+#define SROM11_MCSBW405GLPO 		178
+#define SROM11_MCSBW405GLPO_1		179
+#define SROM11_MCSBW805GLPO 		180
+#define SROM11_MCSBW805GLPO_1		181
+#define SROM11_RPCAL_2G			182
+#define SROM11_RPCAL_5GL		183
+#define SROM11_MCSBW205GMPO 		184
+#define SROM11_MCSBW205GMPO_1		185
+#define SROM11_MCSBW405GMPO 		186
+#define SROM11_MCSBW405GMPO_1		187
+#define SROM11_MCSBW805GMPO 		188
+#define SROM11_MCSBW805GMPO_1		189
+#define SROM11_RPCAL_5GM		190
+#define SROM11_RPCAL_5GH		191
+#define SROM11_MCSBW205GHPO 		192
+#define SROM11_MCSBW205GHPO_1		193
+#define SROM11_MCSBW405GHPO 		194
+#define SROM11_MCSBW405GHPO_1		195
+#define SROM11_MCSBW805GHPO 		196
+#define SROM11_MCSBW805GHPO_1		197
+#define SROM11_RPCAL_5GU		198
+#define SROM11_PDOFF_2G_CCK	        199
+#define SROM11_MCSLR5GLPO		200
+#define SROM11_MCSLR5GMPO		201
+#define SROM11_MCSLR5GHPO		202
+
+#define SROM11_SB20IN40HRPO		203
+#define SROM11_SB20IN80AND160HR5GLPO 	204
+#define SROM11_SB40AND80HR5GLPO		205
+#define SROM11_SB20IN80AND160HR5GMPO 	206
+#define SROM11_SB40AND80HR5GMPO		207
+#define SROM11_SB20IN80AND160HR5GHPO 	208
+#define SROM11_SB40AND80HR5GHPO		209
+#define SROM11_SB20IN40LRPO 		210
+#define SROM11_SB20IN80AND160LR5GLPO	211
+#define SROM11_SB40AND80LR5GLPO		212
+#define SROM11_TXIDXCAP2G               212
+#define SROM11_SB20IN80AND160LR5GMPO	213
+#define SROM11_SB40AND80LR5GMPO		214
+#define SROM11_TXIDXCAP5G               214
+#define SROM11_SB20IN80AND160LR5GHPO	215
+#define SROM11_SB40AND80LR5GHPO		216
+
+#define SROM11_DOT11AGDUPHRPO 		217
+#define SROM11_DOT11AGDUPLRPO		218
+
+/* MISC */
+#define SROM11_PCIEINGRESS_WAR		220
+#define SROM11_SAR			221
+
+#define SROM11_NOISELVL_2G		222
+#define SROM11_NOISELVL_5GL 		223
+#define SROM11_NOISELVL_5GM 		224
+#define SROM11_NOISELVL_5GH 		225
+#define SROM11_NOISELVL_5GU 		226
+
+#define SROM11_RXGAINERR_2G		227
+#define SROM11_RXGAINERR_5GL		228
+#define SROM11_RXGAINERR_5GM		229
+#define SROM11_RXGAINERR_5GH		230
+#define SROM11_RXGAINERR_5GU		231
+
+#define SROM11_EU_EDCRSTH	        232
+#define SROM12_EU_EDCRSTH	        232
+
+#define SROM11_SIGN 			64
+#define SROM11_CRCREV 			233
+
+#define	SROM11_WORDS				234
+#define	SROM11_SIGNATURE		0x0634
+
+
+/* SROM REV 12 */
+#define SROM12_SIGN                     64
+#define SROM12_WORDS			512
+#define SROM12_SIGNATURE		0x8888
+#define SROM12_CRCREV			511
+
+#define SROM12_BFL6				486
+#define SROM12_BFL7				487
+
+#define SROM12_MCSBW205GX1PO		234
+#define SROM12_MCSBW205GX1PO_1		235
+#define SROM12_MCSBW405GX1PO		236
+#define SROM12_MCSBW405GX1PO_1		237
+#define SROM12_MCSBW805GX1PO		238
+#define SROM12_MCSBW805GX1PO_1		239
+#define SROM12_MCSLR5GX1PO			240
+#define SROM12_SB40AND80LR5GX1PO		241
+#define SROM12_SB20IN80AND160LR5GX1PO	242
+#define SROM12_SB20IN80AND160HR5GX1PO	243
+#define SROM12_SB40AND80HR5GX1PO		244
+
+#define SROM12_MCSBW205GX2PO		245
+#define SROM12_MCSBW205GX2PO_1		246
+#define SROM12_MCSBW405GX2PO		247
+#define SROM12_MCSBW405GX2PO_1		248
+#define SROM12_MCSBW805GX2PO		249
+#define SROM12_MCSBW805GX2PO_1		250
+#define SROM12_MCSLR5GX2PO			251
+#define SROM12_SB40AND80LR5GX2PO	252
+#define SROM12_SB20IN80AND160LR5GX2PO	253
+#define SROM12_SB20IN80AND160HR5GX2PO	254
+#define SROM12_SB40AND80HR5GX2PO		255
+
+/* MISC */
+#define	SROM12_RXGAINS10			483
+#define	SROM12_RXGAINS11			484
+#define	SROM12_RXGAINS12			485
+
+/* Per-path fields and offset */
+#define	MAX_PATH_SROM_12			3
+#define SROM12_PATH0				256
+#define SROM12_PATH1				328
+#define SROM12_PATH2				400
+
+#define	SROM12_5GB42G_MAXP				0
+#define SROM12_2GB0_PA					1
+#define SROM12_2GB0_PA_W0				1
+#define SROM12_2GB0_PA_W1				2
+#define SROM12_2GB0_PA_W2				3
+#define SROM12_2GB0_PA_W3				4
+
+#define	SROM12_RXGAINS					5
+#define	SROM12_5GB1B0_MAXP				6
+#define	SROM12_5GB3B2_MAXP				7
+
+#define SROM12_5GB0_PA					8
+#define SROM12_5GB0_PA_W0				8
+#define SROM12_5GB0_PA_W1				9
+#define SROM12_5GB0_PA_W2				10
+#define SROM12_5GB0_PA_W3				11
+
+#define SROM12_5GB1_PA					12
+#define SROM12_5GB1_PA_W0				12
+#define SROM12_5GB1_PA_W1				13
+#define SROM12_5GB1_PA_W2				14
+#define SROM12_5GB1_PA_W3				15
+
+#define SROM12_5GB2_PA					16
+#define SROM12_5GB2_PA_W0				16
+#define SROM12_5GB2_PA_W1				17
+#define SROM12_5GB2_PA_W2				18
+#define SROM12_5GB2_PA_W3				19
+
+#define SROM12_5GB3_PA					20
+#define SROM12_5GB3_PA_W0				20
+#define SROM12_5GB3_PA_W1				21
+#define SROM12_5GB3_PA_W2				22
+#define SROM12_5GB3_PA_W3				23
+
+#define SROM12_5GB4_PA					24
+#define SROM12_5GB4_PA_W0				24
+#define SROM12_5GB4_PA_W1				25
+#define SROM12_5GB4_PA_W2				26
+#define SROM12_5GB4_PA_W3				27
+
+#define SROM12_2G40B0_PA				28
+#define SROM12_2G40B0_PA_W0				28
+#define SROM12_2G40B0_PA_W1				29
+#define SROM12_2G40B0_PA_W2				30
+#define SROM12_2G40B0_PA_W3				31
+
+#define SROM12_5G40B0_PA				32
+#define SROM12_5G40B0_PA_W0				32
+#define SROM12_5G40B0_PA_W1				33
+#define SROM12_5G40B0_PA_W2				34
+#define SROM12_5G40B0_PA_W3				35
+
+#define SROM12_5G40B1_PA				36
+#define SROM12_5G40B1_PA_W0				36
+#define SROM12_5G40B1_PA_W1				37
+#define SROM12_5G40B1_PA_W2				38
+#define SROM12_5G40B1_PA_W3				39
+
+#define SROM12_5G40B2_PA				40
+#define SROM12_5G40B2_PA_W0				40
+#define SROM12_5G40B2_PA_W1				41
+#define SROM12_5G40B2_PA_W2				42
+#define SROM12_5G40B2_PA_W3				43
+
+#define SROM12_5G40B3_PA				44
+#define SROM12_5G40B3_PA_W0				44
+#define SROM12_5G40B3_PA_W1				45
+#define SROM12_5G40B3_PA_W2				46
+#define SROM12_5G40B3_PA_W3				47
+
+#define SROM12_5G40B4_PA				48
+#define SROM12_5G40B4_PA_W0				48
+#define SROM12_5G40B4_PA_W1				49
+#define SROM12_5G40B4_PA_W2				50
+#define SROM12_5G40B4_PA_W3				51
+
+#define SROM12_5G80B0_PA				52
+#define SROM12_5G80B0_PA_W0				52
+#define SROM12_5G80B0_PA_W1				53
+#define SROM12_5G80B0_PA_W2				54
+#define SROM12_5G80B0_PA_W3				55
+
+#define SROM12_5G80B1_PA				56
+#define SROM12_5G80B1_PA_W0				56
+#define SROM12_5G80B1_PA_W1				57
+#define SROM12_5G80B1_PA_W2				58
+#define SROM12_5G80B1_PA_W3				59
+
+#define SROM12_5G80B2_PA				60
+#define SROM12_5G80B2_PA_W0				60
+#define SROM12_5G80B2_PA_W1				61
+#define SROM12_5G80B2_PA_W2				62
+#define SROM12_5G80B2_PA_W3				63
+
+#define SROM12_5G80B3_PA				64
+#define SROM12_5G80B3_PA_W0				64
+#define SROM12_5G80B3_PA_W1				65
+#define SROM12_5G80B3_PA_W2				66
+#define SROM12_5G80B3_PA_W3				67
+
+#define SROM12_5G80B4_PA				68
+#define SROM12_5G80B4_PA_W0				68
+#define SROM12_5G80B4_PA_W1				69
+#define SROM12_5G80B4_PA_W2				70
+#define SROM12_5G80B4_PA_W3				71
+
+/* PD offset */
+#define SROM12_PDOFF_2G_CCK				472
+
+#define SROM12_PDOFF_20in40M_5G_B0		473
+#define SROM12_PDOFF_20in40M_5G_B1		474
+#define SROM12_PDOFF_20in40M_5G_B2		475
+#define SROM12_PDOFF_20in40M_5G_B3		476
+#define SROM12_PDOFF_20in40M_5G_B4		477
+
+#define SROM12_PDOFF_40in80M_5G_B0		478
+#define SROM12_PDOFF_40in80M_5G_B1		479
+#define SROM12_PDOFF_40in80M_5G_B2		480
+#define SROM12_PDOFF_40in80M_5G_B3		481
+#define SROM12_PDOFF_40in80M_5G_B4		482
+
+#define SROM12_PDOFF_20in80M_5G_B0		488
+#define SROM12_PDOFF_20in80M_5G_B1		489
+#define SROM12_PDOFF_20in80M_5G_B2		490
+#define SROM12_PDOFF_20in80M_5G_B3		491
+#define SROM12_PDOFF_20in80M_5G_B4		492
+
+#define SROM12_GPDN_L				91  /* GPIO pull down bits [15:0]  */
+#define SROM12_GPDN_H				233 /* GPIO pull down bits [31:16] */
+
+#define SROM13_SIGN                     64
+#define SROM13_WORDS                    590
+#define SROM13_SIGNATURE                0x4d55
+#define SROM13_CRCREV                   589
+
+
+/* Per-path fields and offset */
+#define MAX_PATH_SROM_13                        4
+#define SROM13_PATH0                            256
+#define SROM13_PATH1                            328
+#define SROM13_PATH2                            400
+#define SROM13_PATH3                            512
+#define SROM13_RXGAINS                         5
+
+#define SROM13_XTALFREQ                 90
+
+#define SROM13_PDOFFSET20IN40M2G        94
+#define SROM13_PDOFFSET20IN40M2GCORE3   95
+#define SROM13_SB20IN40HRLRPOX          96
+
+#define SROM13_RXGAINS1CORE3            97
+
+#define SROM13_PDOFFSET20IN40M5GCORE3   98
+#define SROM13_PDOFFSET20IN40M5GCORE3_1 99
+
+#define SROM13_ANTGAIN_BANDBGA          100
+
+#define SROM13_PDOFFSET40IN80M5GCORE3   105
+#define SROM13_PDOFFSET40IN80M5GCORE3_1 106
+
+/* power per rate */
+#define SROM13_MCS1024QAM2GPO           108
+#define SROM13_MCS1024QAM5GLPO          109
+#define SROM13_MCS1024QAM5GLPO_1        110
+#define SROM13_MCS1024QAM5GMPO          111
+#define SROM13_MCS1024QAM5GMPO_1        112
+#define SROM13_MCS1024QAM5GHPO          113
+#define SROM13_MCS1024QAM5GHPO_1        114
+#define SROM13_MCS1024QAM5GX1PO         115
+#define SROM13_MCS1024QAM5GX1PO_1       116
+#define SROM13_MCS1024QAM5GX2PO         117
+#define SROM13_MCS1024QAM5GX2PO_1       118
+
+#define SROM13_MCSBW1605GLPO            119
+#define SROM13_MCSBW1605GLPO_1          120
+#define SROM13_MCSBW1605GMPO            121
+#define SROM13_MCSBW1605GMPO_1          122
+#define SROM13_MCSBW1605GHPO            123
+#define SROM13_MCSBW1605GHPO_1          124
+
+#define SROM13_MCSBW1605GX1PO           125
+#define SROM13_MCSBW1605GX1PO_1         126
+#define SROM13_MCSBW1605GX2PO           127
+#define SROM13_MCSBW1605GX2PO_1         128
+
+#define SROM13_ULBPPROFFS5GB0		129
+#define SROM13_ULBPPROFFS5GB1           130
+#define SROM13_ULBPPROFFS5GB2           131
+#define SROM13_ULBPPROFFS5GB3           132
+#define SROM13_ULBPPROFFS5GB4           133
+#define SROM13_ULBPPROFFS2G		134
+
+#define SROM13_MCS8POEXP                135
+#define SROM13_MCS8POEXP_1              136
+#define SROM13_MCS9POEXP                137
+#define SROM13_MCS9POEXP_1              138
+#define SROM13_MCS10POEXP               139
+#define SROM13_MCS10POEXP_1             140
+#define SROM13_MCS11POEXP               141
+#define SROM13_MCS11POEXP_1             142
+#define SROM13_ULBPDOFFS5GB0A0		143
+#define SROM13_ULBPDOFFS5GB0A1          144
+#define SROM13_ULBPDOFFS5GB0A2          145
+#define SROM13_ULBPDOFFS5GB0A3          146
+#define SROM13_ULBPDOFFS5GB1A0          147
+#define SROM13_ULBPDOFFS5GB1A1          148
+#define SROM13_ULBPDOFFS5GB1A2          149
+#define SROM13_ULBPDOFFS5GB1A3          150
+#define SROM13_ULBPDOFFS5GB2A0          151
+#define SROM13_ULBPDOFFS5GB2A1          152
+#define SROM13_ULBPDOFFS5GB2A2          153
+#define SROM13_ULBPDOFFS5GB2A3          154
+#define SROM13_ULBPDOFFS5GB3A0          155
+#define SROM13_ULBPDOFFS5GB3A1          156
+#define SROM13_ULBPDOFFS5GB3A2          157
+#define SROM13_ULBPDOFFS5GB3A3          158
+#define SROM13_ULBPDOFFS5GB4A0          159
+#define SROM13_ULBPDOFFS5GB4A1          160
+#define SROM13_ULBPDOFFS5GB4A2          161
+#define SROM13_ULBPDOFFS5GB4A3          162
+#define SROM13_ULBPDOFFS2GA0		163
+#define SROM13_ULBPDOFFS2GA1		164
+#define SROM13_ULBPDOFFS2GA2		165
+#define SROM13_ULBPDOFFS2GA3		166
+
+#define SROM13_RPCAL5GB4                199
+#define SROM13_RPCAL2GCORE3             101
+#define SROM13_RPCAL5GB01CORE3          102
+#define SROM13_RPCAL5GB23CORE3          103
+
+#define SROM13_SW_TXRX_MASK		104
+
+#define SROM13_EU_EDCRSTH               232
+
+#define SROM13_SWCTRLMAP4_CFG			493
+#define SROM13_SWCTRLMAP4_TX2G_FEM3TO0		494
+#define SROM13_SWCTRLMAP4_RX2G_FEM3TO0		495
+#define SROM13_SWCTRLMAP4_RXBYP2G_FEM3TO0	496
+#define SROM13_SWCTRLMAP4_MISC2G_FEM3TO0	497
+#define SROM13_SWCTRLMAP4_TX5G_FEM3TO0		498
+#define SROM13_SWCTRLMAP4_RX5G_FEM3TO0		499
+#define SROM13_SWCTRLMAP4_RXBYP5G_FEM3TO0	500
+#define SROM13_SWCTRLMAP4_MISC5G_FEM3TO0	501
+#define SROM13_SWCTRLMAP4_TX2G_FEM7TO4		502
+#define SROM13_SWCTRLMAP4_RX2G_FEM7TO4		503
+#define SROM13_SWCTRLMAP4_RXBYP2G_FEM7TO4	504
+#define SROM13_SWCTRLMAP4_MISC2G_FEM7TO4	505
+#define SROM13_SWCTRLMAP4_TX5G_FEM7TO4		506
+#define SROM13_SWCTRLMAP4_RX5G_FEM7TO4		507
+#define SROM13_SWCTRLMAP4_RXBYP5G_FEM7TO4	508
+#define SROM13_SWCTRLMAP4_MISC5G_FEM7TO4	509
+
+#define SROM13_PDOFFSET20IN80M5GCORE3   510
+#define SROM13_PDOFFSET20IN80M5GCORE3_1 511
+
+#define SROM13_NOISELVLCORE3            584
+#define SROM13_NOISELVLCORE3_1          585
+#define SROM13_RXGAINERRCORE3           586
+#define SROM13_RXGAINERRCORE3_1         587
+
+#define SROM13_PDOFF_2G_CCK_20M		167
+
+#define SROM15_CAL_OFFSET_LOC	68
+#define MAX_IOCTL_TXCHUNK_SIZE	1500
+#define SROM15_MAX_CAL_SIZE	1662
+#define SROM15_SIGNATURE	0x110c
+#define SROM15_WORDS	1024
+#define SROM15_MACHI	65
+
+#define SROM16_SIGN			128
+#define SROM16_WORDS			1024
+#define SROM16_SIGNATURE		0x4357
+#define SROM16_CRCREV			1023
+
+#define SROM16_CAL_DATA_OFFSET		288
+
+typedef struct {
+	uint8 tssipos;		/* TSSI positive slope, 1: positive, 0: negative */
+	uint8 extpagain;	/* Ext PA gain-type: full-gain: 0, pa-lite: 1, no_pa: 2 */
+	uint8 pdetrange;	/* support 32 combinations of different Pdet dynamic ranges */
+	uint8 triso;		/* TR switch isolation */
+	uint8 antswctrllut;	/* antswctrl lookup table configuration: 32 possible choices */
+} srom_fem_t;
+
+#endif	/* _bcmsrom_fmt_h_ */
diff --git a/wl/src/include/bcmsrom_tbl.h b/wl/src/include/bcmsrom_tbl.h
new file mode 100644
index 0000000..df02f4c
--- /dev/null
+++ b/wl/src/include/bcmsrom_tbl.h
@@ -0,0 +1,1435 @@
+/*
+ * Table that encodes the srom formats for PCI/PCIe NICs.
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmsrom_tbl.h 650789 2016-07-22 12:29:31Z $
+ */
+
+#ifndef	_bcmsrom_tbl_h_
+#define	_bcmsrom_tbl_h_
+
+#include "sbpcmcia.h"
+#include "wlioctl.h"
+#include <bcmsrom_fmt.h>
+
+typedef struct {
+	const char *name;
+	uint32	revmask;
+	uint32	flags;
+	uint16	off;
+	uint16	mask;
+} sromvar_t;
+
+#define SRFL_MORE	1		/* value continues as described by the next entry */
+#define	SRFL_NOFFS	2		/* value bits can't be all one's */
+#define	SRFL_PRHEX	4		/* value is in hexdecimal format */
+#define	SRFL_PRSIGN	8		/* value is in signed decimal format */
+#define	SRFL_CCODE	0x10		/* value is in country code format */
+#define	SRFL_ETHADDR	0x20		/* value is an Ethernet address */
+#define SRFL_LEDDC	0x40		/* value is an LED duty cycle */
+#define SRFL_NOVAR	0x80		/* do not generate a nvram param, entry is for mfgc */
+#define SRFL_ARRAY	0x100		/* value is in an array. All elements EXCEPT FOR THE LAST
+					 * ONE in the array should have this flag set.
+					 */
+
+#if defined(DSLCPE) && defined(DSLCPE_WOMBO)
+#define	SRFL_PCI	0x10000000		/* value is an PCI specific */
+#define SRFL_PCIE	0x20000000		/* value is an PCIE specific */
+
+#define SROM_DEVID_PCI	4
+#endif /* defined(DSLCPE) && defined(DSLCPE_WOMBO) */
+
+#define SROM_DEVID_PCIE	48
+
+/**
+ * Assumptions:
+ * - Ethernet address spans across 3 consecutive words
+ *
+ * Table rules:
+ * - Add multiple entries next to each other if a value spans across multiple words
+ *   (even multiple fields in the same word) with each entry except the last having
+ *   it's SRFL_MORE bit set.
+ * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
+ *   bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
+ * - The last entry's name field must be NULL to indicate the end of the table. Other
+ *   entries must have non-NULL name.
+ */
+#if !defined(SROM15_MEMOPT)
+static const sromvar_t BCMATTACHDATA(pci_sromvars)[] = {
+/*	name		revmask		flags		off			mask */
+#if defined(DSLCPE) && defined(DSLCPE_WOMBO)
+	{"devid",	0xfffffffe,	SRFL_PRHEX|SRFL_PCI, SROM_DEVID_PCI,	0xffff},
+	{"devid",	0xffffff00,	SRFL_PRHEX|SRFL_PCIE, SROM_DEVID_PCIE,	0xffff},
+#elif defined(CABLECPE)
+	{"devid",	0xffffff00,	SRFL_PRHEX,	PCI_F0DEVID,		0xffff},
+#elif defined(BCMPCIEDEV) && defined(BCMPCIEDEV_ENABLED)
+	{"devid",	0xffffff00,	SRFL_PRHEX, SROM_DEVID_PCIE,		0xffff},
+#else
+	{"devid",	0xffffff00,	SRFL_PRHEX|SRFL_NOVAR,	PCI_F0DEVID,	0xffff},
+#endif /* defined(DSLCPE) && defined(DSLCPE_WOMBO) */
+	{"boardrev",	0x0000000e,	SRFL_PRHEX,	SROM_AABREV,		SROM_BR_MASK},
+	{"boardrev",	0x000000f0,	SRFL_PRHEX,	SROM4_BREV,		0xffff},
+	{"boardrev",	0xffffff00,	SRFL_PRHEX,	SROM8_BREV,		0xffff},
+	{"boardflags",	0x00000002,	SRFL_PRHEX,	SROM_BFL,		0xffff},
+	{"boardflags",	0x00000004,	SRFL_PRHEX|SRFL_MORE,	SROM_BFL,	0xffff},
+	{"",		0,		0,		SROM_BFL2,		0xffff},
+	{"boardflags",	0x00000008,	SRFL_PRHEX|SRFL_MORE,	SROM_BFL,	0xffff},
+	{"",		0,		0,		SROM3_BFL2,		0xffff},
+	{"boardflags",	0x00000010,	SRFL_PRHEX|SRFL_MORE,	SROM4_BFL0,	0xffff},
+	{"",		0,		0,		SROM4_BFL1,		0xffff},
+	{"boardflags",	0x000000e0,	SRFL_PRHEX|SRFL_MORE,	SROM5_BFL0,	0xffff},
+	{"",		0,		0,		SROM5_BFL1,		0xffff},
+	{"boardflags",	0xffffff00,	SRFL_PRHEX|SRFL_MORE,	SROM8_BFL0,	0xffff},
+	{"",		0,		0,		SROM8_BFL1,		0xffff},
+	{"boardflags2", 0x00000010,	SRFL_PRHEX|SRFL_MORE,	SROM4_BFL2,	0xffff},
+	{"",		0,		0,		SROM4_BFL3,		0xffff},
+	{"boardflags2", 0x000000e0,	SRFL_PRHEX|SRFL_MORE,	SROM5_BFL2,	0xffff},
+	{"",		0,		0,		SROM5_BFL3,		0xffff},
+	{"boardflags2", 0xffffff00,	SRFL_PRHEX|SRFL_MORE,	SROM8_BFL2,	0xffff},
+	{"",		0,		0,		SROM8_BFL3,		0xffff},
+	{"boardtype",	0xfffffffc,	SRFL_PRHEX,	SROM_SSID,		0xffff},
+	{"subvid",	0xfffffffc,	SRFL_PRHEX,	SROM_SVID,		0xffff},
+	{"boardnum",	0x00000006,	0,		SROM_MACLO_IL0,		0xffff},
+	{"boardnum",	0x00000008,	0,		SROM3_MACLO,		0xffff},
+	{"boardnum",	0x00000010,	0,		SROM4_MACLO,		0xffff},
+	{"boardnum",	0x000000e0,	0,		SROM5_MACLO,		0xffff},
+	{"boardnum",	0x00000700,	0,		SROM8_MACLO,		0xffff},
+	{"cc",		0x00000002,	0,		SROM_AABREV,		SROM_CC_MASK},
+	{"regrev",	0x00000008,	0,		SROM_OPO,		0xff00},
+	{"regrev",	0x00000010,	0,		SROM4_REGREV,		0xffff},
+	{"regrev",	0x000000e0,	0,		SROM5_REGREV,		0xffff},
+	{"regrev",	0x00000700,	0,		SROM8_REGREV,		0xffff},
+	{"ledbh0",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH10,		0x00ff},
+	{"ledbh1",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH10,		0xff00},
+	{"ledbh2",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH32,		0x00ff},
+	{"ledbh3",	0x0000000e,	SRFL_NOFFS,	SROM_LEDBH32,		0xff00},
+	{"ledbh0",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH10,		0x00ff},
+	{"ledbh1",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH10,		0xff00},
+	{"ledbh2",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH32,		0x00ff},
+	{"ledbh3",	0x00000010,	SRFL_NOFFS,	SROM4_LEDBH32,		0xff00},
+	{"ledbh0",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH10,		0x00ff},
+	{"ledbh1",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH10,		0xff00},
+	{"ledbh2",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH32,		0x00ff},
+	{"ledbh3",	0x000000e0,	SRFL_NOFFS,	SROM5_LEDBH32,		0xff00},
+	{"ledbh0",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH10,		0x00ff},
+	{"ledbh1",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH10,		0xff00},
+	{"ledbh2",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH32,		0x00ff},
+	{"ledbh3",	0x00000700,	SRFL_NOFFS,	SROM8_LEDBH32,		0xff00},
+	{"pa0b0",	0x0000000e,	SRFL_PRHEX,	SROM_WL0PAB0,		0xffff},
+	{"pa0b1",	0x0000000e,	SRFL_PRHEX,	SROM_WL0PAB1,		0xffff},
+	{"pa0b2",	0x0000000e,	SRFL_PRHEX,	SROM_WL0PAB2,		0xffff},
+	{"pa0itssit",	0x0000000e,	0,		SROM_ITT,		0x00ff},
+	{"pa0maxpwr",	0x0000000e,	0,		SROM_WL10MAXP,		0x00ff},
+	{"pa0b0",	0x00000700,	SRFL_PRHEX,	SROM8_W0_PAB0,		0xffff},
+	{"pa0b1",	0x00000700,	SRFL_PRHEX,	SROM8_W0_PAB1,		0xffff},
+	{"pa0b2",	0x00000700,	SRFL_PRHEX,	SROM8_W0_PAB2,		0xffff},
+	{"pa0itssit",	0x00000700,	0,		SROM8_W0_ITTMAXP,	0xff00},
+	{"pa0maxpwr",	0x00000700,	0,		SROM8_W0_ITTMAXP,	0x00ff},
+	{"opo",		0x0000000c,	0,		SROM_OPO,		0x00ff},
+	{"opo",		0x00000700,	0,		SROM8_2G_OFDMPO,	0x00ff},
+	{"aa2g",	0x0000000e,	0,		SROM_AABREV,		SROM_AA0_MASK},
+	{"aa2g",	0x000000f0,	0,		SROM4_AA,		0x00ff},
+	{"aa2g",	0x00000700,	0,		SROM8_AA,		0x00ff},
+	{"aa5g",	0x0000000e,	0,		SROM_AABREV,		SROM_AA1_MASK},
+	{"aa5g",	0x000000f0,	0,		SROM4_AA,		0xff00},
+	{"aa5g",	0x00000700,	0,		SROM8_AA,		0xff00},
+	{"ag0",		0x0000000e,	0,		SROM_AG10,		0x00ff},
+	{"ag1",		0x0000000e,	0,		SROM_AG10,		0xff00},
+	{"ag0",		0x000000f0,	0,		SROM4_AG10,		0x00ff},
+	{"ag1",		0x000000f0,	0,		SROM4_AG10,		0xff00},
+	{"ag2",		0x000000f0,	0,		SROM4_AG32,		0x00ff},
+	{"ag3",		0x000000f0,	0,		SROM4_AG32,		0xff00},
+	{"ag0",		0x00000700,	0,		SROM8_AG10,		0x00ff},
+	{"ag1",		0x00000700,	0,		SROM8_AG10,		0xff00},
+	{"ag2",		0x00000700,	0,		SROM8_AG32,		0x00ff},
+	{"ag3",		0x00000700,	0,		SROM8_AG32,		0xff00},
+	{"pa1b0",	0x0000000e,	SRFL_PRHEX,	SROM_WL1PAB0,		0xffff},
+	{"pa1b1",	0x0000000e,	SRFL_PRHEX,	SROM_WL1PAB1,		0xffff},
+	{"pa1b2",	0x0000000e,	SRFL_PRHEX,	SROM_WL1PAB2,		0xffff},
+	{"pa1lob0",	0x0000000c,	SRFL_PRHEX,	SROM_WL1LPAB0,		0xffff},
+	{"pa1lob1",	0x0000000c,	SRFL_PRHEX,	SROM_WL1LPAB1,		0xffff},
+	{"pa1lob2",	0x0000000c,	SRFL_PRHEX,	SROM_WL1LPAB2,		0xffff},
+	{"pa1hib0",	0x0000000c,	SRFL_PRHEX,	SROM_WL1HPAB0,		0xffff},
+	{"pa1hib1",	0x0000000c,	SRFL_PRHEX,	SROM_WL1HPAB1,		0xffff},
+	{"pa1hib2",	0x0000000c,	SRFL_PRHEX,	SROM_WL1HPAB2,		0xffff},
+	{"pa1itssit",	0x0000000e,	0,		SROM_ITT,		0xff00},
+	{"pa1maxpwr",	0x0000000e,	0,		SROM_WL10MAXP,		0xff00},
+	{"pa1lomaxpwr",	0x0000000c,	0,		SROM_WL1LHMAXP,		0xff00},
+	{"pa1himaxpwr",	0x0000000c,	0,		SROM_WL1LHMAXP,		0x00ff},
+	{"pa1b0",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB0,		0xffff},
+	{"pa1b1",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB1,		0xffff},
+	{"pa1b2",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB2,		0xffff},
+	{"pa1lob0",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB0_LC,	0xffff},
+	{"pa1lob1",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB1_LC,	0xffff},
+	{"pa1lob2",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB2_LC,	0xffff},
+	{"pa1hib0",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB0_HC,	0xffff},
+	{"pa1hib1",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB1_HC,	0xffff},
+	{"pa1hib2",	0x00000700,	SRFL_PRHEX,	SROM8_W1_PAB2_HC,	0xffff},
+	{"pa1itssit",	0x00000700,	0,		SROM8_W1_ITTMAXP,	0xff00},
+	{"pa1maxpwr",	0x00000700,	0,		SROM8_W1_ITTMAXP,	0x00ff},
+	{"pa1lomaxpwr",	0x00000700,	0,		SROM8_W1_MAXP_LCHC,	0xff00},
+	{"pa1himaxpwr",	0x00000700,	0,		SROM8_W1_MAXP_LCHC,	0x00ff},
+	{"bxa2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x1800},
+	{"rssisav2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x0700},
+	{"rssismc2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x00f0},
+	{"rssismf2g",	0x00000008,	0,		SROM_BXARSSI2G,		0x000f},
+	{"bxa2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x1800},
+	{"rssisav2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x0700},
+	{"rssismc2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x00f0},
+	{"rssismf2g",	0x00000700,	0,		SROM8_BXARSSI2G,	0x000f},
+	{"bxa5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x1800},
+	{"rssisav5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x0700},
+	{"rssismc5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x00f0},
+	{"rssismf5g",	0x00000008,	0,		SROM_BXARSSI5G,		0x000f},
+	{"bxa5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x1800},
+	{"rssisav5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x0700},
+	{"rssismc5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x00f0},
+	{"rssismf5g",	0x00000700,	0,		SROM8_BXARSSI5G,	0x000f},
+	{"tri2g",	0x00000008,	0,		SROM_TRI52G,		0x00ff},
+	{"tri5g",	0x00000008,	0,		SROM_TRI52G,		0xff00},
+	{"tri5gl",	0x00000008,	0,		SROM_TRI5GHL,		0x00ff},
+	{"tri5gh",	0x00000008,	0,		SROM_TRI5GHL,		0xff00},
+	{"tri2g",	0x00000700,	0,		SROM8_TRI52G,		0x00ff},
+	{"tri5g",	0x00000700,	0,		SROM8_TRI52G,		0xff00},
+	{"tri5gl",	0x00000700,	0,		SROM8_TRI5GHL,		0x00ff},
+	{"tri5gh",	0x00000700,	0,		SROM8_TRI5GHL,		0xff00},
+	{"rxpo2g",	0x00000008,	SRFL_PRSIGN,	SROM_RXPO52G,		0x00ff},
+	{"rxpo5g",	0x00000008,	SRFL_PRSIGN,	SROM_RXPO52G,		0xff00},
+	{"rxpo2g",	0x00000700,	SRFL_PRSIGN,	SROM8_RXPO52G,		0x00ff},
+	{"rxpo5g",	0x00000700,	SRFL_PRSIGN,	SROM8_RXPO52G,		0xff00},
+	{"txchain",	0x000000f0,	SRFL_NOFFS,	SROM4_TXRXC,		SROM4_TXCHAIN_MASK},
+	{"rxchain",	0x000000f0,	SRFL_NOFFS,	SROM4_TXRXC,		SROM4_RXCHAIN_MASK},
+	{"antswitch",	0x000000f0,	SRFL_NOFFS,	SROM4_TXRXC,		SROM4_SWITCH_MASK},
+	{"txchain",	0x00000700,	SRFL_NOFFS,	SROM8_TXRXC,		SROM4_TXCHAIN_MASK},
+	{"rxchain",	0x00000700,	SRFL_NOFFS,	SROM8_TXRXC,		SROM4_RXCHAIN_MASK},
+	{"antswitch",	0x00000700,	SRFL_NOFFS,	SROM8_TXRXC,		SROM4_SWITCH_MASK},
+	{"tssipos2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_TSSIPOS_MASK},
+	{"extpagain2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_EXTPA_GAIN_MASK},
+	{"pdetrange2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_PDET_RANGE_MASK},
+	{"triso2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_TR_ISO_MASK},
+	{"antswctl2g",	0x00000700,	0,		SROM8_FEM2G,	SROM8_FEM_ANTSWLUT_MASK},
+	{"tssipos5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_TSSIPOS_MASK},
+	{"extpagain5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_EXTPA_GAIN_MASK},
+	{"pdetrange5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_PDET_RANGE_MASK},
+	{"triso5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_TR_ISO_MASK},
+	{"antswctl5g",	0x00000700,	0,		SROM8_FEM5G,	SROM8_FEM_ANTSWLUT_MASK},
+	{"txpid2ga0",	0x000000f0,	0,		SROM4_TXPID2G,		0x00ff},
+	{"txpid2ga1",	0x000000f0,	0,		SROM4_TXPID2G,		0xff00},
+	{"txpid2ga2",	0x000000f0,	0,		SROM4_TXPID2G + 1,	0x00ff},
+	{"txpid2ga3",	0x000000f0,	0,		SROM4_TXPID2G + 1,	0xff00},
+	{"txpid5ga0",	0x000000f0,	0,		SROM4_TXPID5G,		0x00ff},
+	{"txpid5ga1",	0x000000f0,	0,		SROM4_TXPID5G,		0xff00},
+	{"txpid5ga2",	0x000000f0,	0,		SROM4_TXPID5G + 1,	0x00ff},
+	{"txpid5ga3",	0x000000f0,	0,		SROM4_TXPID5G + 1,	0xff00},
+	{"txpid5gla0",	0x000000f0,	0,		SROM4_TXPID5GL,		0x00ff},
+	{"txpid5gla1",	0x000000f0,	0,		SROM4_TXPID5GL,		0xff00},
+	{"txpid5gla2",	0x000000f0,	0,		SROM4_TXPID5GL + 1,	0x00ff},
+	{"txpid5gla3",	0x000000f0,	0,		SROM4_TXPID5GL + 1,	0xff00},
+	{"txpid5gha0",	0x000000f0,	0,		SROM4_TXPID5GH,		0x00ff},
+	{"txpid5gha1",	0x000000f0,	0,		SROM4_TXPID5GH,		0xff00},
+	{"txpid5gha2",	0x000000f0,	0,		SROM4_TXPID5GH + 1,	0x00ff},
+	{"txpid5gha3",	0x000000f0,	0,		SROM4_TXPID5GH + 1,	0xff00},
+
+	{"ccode",	0x0000000f,	SRFL_CCODE,	SROM_CCODE,		0xffff},
+	{"ccode",	0x00000010,	SRFL_CCODE,	SROM4_CCODE,		0xffff},
+	{"ccode",	0x000000e0,	SRFL_CCODE,	SROM5_CCODE,		0xffff},
+	{"ccode",	0x00000700,	SRFL_CCODE,	SROM8_CCODE,		0xffff},
+	{"macaddr",	0x00000700,	SRFL_ETHADDR,	SROM8_MACHI,		0xffff},
+	{"macaddr",	0x000000e0,	SRFL_ETHADDR,	SROM5_MACHI,		0xffff},
+	{"macaddr",	0x00000010,	SRFL_ETHADDR,	SROM4_MACHI,		0xffff},
+	{"macaddr",	0x00000008,	SRFL_ETHADDR,	SROM3_MACHI,		0xffff},
+	{"il0macaddr",	0x00000007,	SRFL_ETHADDR,	SROM_MACHI_IL0,		0xffff},
+	{"et1macaddr",	0x00000007,	SRFL_ETHADDR,	SROM_MACHI_ET1,		0xffff},
+	{"leddc",	0x00000700,	SRFL_NOFFS|SRFL_LEDDC,	SROM8_LEDDC,	0xffff},
+	{"leddc",	0x000000e0,	SRFL_NOFFS|SRFL_LEDDC,	SROM5_LEDDC,	0xffff},
+	{"leddc",	0x00000010,	SRFL_NOFFS|SRFL_LEDDC,	SROM4_LEDDC,	0xffff},
+	{"leddc",	0x00000008,	SRFL_NOFFS|SRFL_LEDDC,	SROM3_LEDDC,	0xffff},
+
+	{"tempthresh",	0x00000700,	0,		SROM8_THERMAL,		0xff00},
+	{"tempoffset",	0x00000700,	0,		SROM8_THERMAL,		0x00ff},
+	{"rawtempsense", 0x00000700,	SRFL_PRHEX,	SROM8_MPWR_RAWTS,	0x01ff},
+	{"measpower",	0x00000700,	SRFL_PRHEX,	SROM8_MPWR_RAWTS,	0xfe00},
+	{"tempsense_slope",	0x00000700,	SRFL_PRHEX, 	SROM8_TS_SLP_OPT_CORRX,	0x00ff},
+	{"tempcorrx",	0x00000700,	SRFL_PRHEX, 	SROM8_TS_SLP_OPT_CORRX,	0xfc00},
+	{"tempsense_option",	0x00000700,	SRFL_PRHEX,	SROM8_TS_SLP_OPT_CORRX,	0x0300},
+	{"freqoffset_corr",	0x00000700,	SRFL_PRHEX,	SROM8_FOC_HWIQ_IQSWP,	0x000f},
+	{"iqcal_swp_dis",	0x00000700,	SRFL_PRHEX,	SROM8_FOC_HWIQ_IQSWP,	0x0010},
+	{"hw_iqcal_en",	0x00000700,	SRFL_PRHEX,	SROM8_FOC_HWIQ_IQSWP,	0x0020},
+	{"elna2g",      0x00000700,     0,              SROM8_EXTLNAGAIN,       0x00ff},
+	{"elna5g",      0x00000700,     0,              SROM8_EXTLNAGAIN,       0xff00},
+	{"phycal_tempdelta",	0x00000700,	0,	SROM8_PHYCAL_TEMPDELTA,	0x00ff},
+	{"temps_period",	0x00000700,	0,	SROM8_PHYCAL_TEMPDELTA,	0x0f00},
+	{"temps_hysteresis",	0x00000700,	0,	SROM8_PHYCAL_TEMPDELTA,	0xf000},
+	{"measpower1", 0x00000700,	SRFL_PRHEX, SROM8_MPWR_1_AND_2, 	0x007f},
+	{"measpower2",	0x00000700, 	SRFL_PRHEX, SROM8_MPWR_1_AND_2, 	0x3f80},
+
+	{"cck2gpo",	0x000000f0,	0,		SROM4_2G_CCKPO,		0xffff},
+	{"cck2gpo",	0x00000100,	0,		SROM8_2G_CCKPO,		0xffff},
+	{"ofdm2gpo",	0x000000f0,	SRFL_MORE,	SROM4_2G_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM4_2G_OFDMPO + 1,	0xffff},
+	{"ofdm5gpo",	0x000000f0,	SRFL_MORE,	SROM4_5G_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM4_5G_OFDMPO + 1,	0xffff},
+	{"ofdm5glpo",	0x000000f0,	SRFL_MORE,	SROM4_5GL_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM4_5GL_OFDMPO + 1,	0xffff},
+	{"ofdm5ghpo",	0x000000f0,	SRFL_MORE,	SROM4_5GH_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM4_5GH_OFDMPO + 1,	0xffff},
+	{"ofdm2gpo",	0x00000100,	SRFL_MORE,	SROM8_2G_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM8_2G_OFDMPO + 1,	0xffff},
+	{"ofdm5gpo",	0x00000100,	SRFL_MORE,	SROM8_5G_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM8_5G_OFDMPO + 1,	0xffff},
+	{"ofdm5glpo",	0x00000100,	SRFL_MORE,	SROM8_5GL_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM8_5GL_OFDMPO + 1,	0xffff},
+	{"ofdm5ghpo",	0x00000100,	SRFL_MORE,	SROM8_5GH_OFDMPO,	0xffff},
+	{"",		0,		0,		SROM8_5GH_OFDMPO + 1,	0xffff},
+	{"mcs2gpo0",	0x000000f0,	0,		SROM4_2G_MCSPO,		0xffff},
+	{"mcs2gpo1",	0x000000f0,	0,		SROM4_2G_MCSPO + 1,	0xffff},
+	{"mcs2gpo2",	0x000000f0,	0,		SROM4_2G_MCSPO + 2,	0xffff},
+	{"mcs2gpo3",	0x000000f0,	0,		SROM4_2G_MCSPO + 3,	0xffff},
+	{"mcs2gpo4",	0x000000f0,	0,		SROM4_2G_MCSPO + 4,	0xffff},
+	{"mcs2gpo5",	0x000000f0,	0,		SROM4_2G_MCSPO + 5,	0xffff},
+	{"mcs2gpo6",	0x000000f0,	0,		SROM4_2G_MCSPO + 6,	0xffff},
+	{"mcs2gpo7",	0x000000f0,	0,		SROM4_2G_MCSPO + 7,	0xffff},
+	{"mcs5gpo0",	0x000000f0,	0,		SROM4_5G_MCSPO,		0xffff},
+	{"mcs5gpo1",	0x000000f0,	0,		SROM4_5G_MCSPO + 1,	0xffff},
+	{"mcs5gpo2",	0x000000f0,	0,		SROM4_5G_MCSPO + 2,	0xffff},
+	{"mcs5gpo3",	0x000000f0,	0,		SROM4_5G_MCSPO + 3,	0xffff},
+	{"mcs5gpo4",	0x000000f0,	0,		SROM4_5G_MCSPO + 4,	0xffff},
+	{"mcs5gpo5",	0x000000f0,	0,		SROM4_5G_MCSPO + 5,	0xffff},
+	{"mcs5gpo6",	0x000000f0,	0,		SROM4_5G_MCSPO + 6,	0xffff},
+	{"mcs5gpo7",	0x000000f0,	0,		SROM4_5G_MCSPO + 7,	0xffff},
+	{"mcs5glpo0",	0x000000f0,	0,		SROM4_5GL_MCSPO,	0xffff},
+	{"mcs5glpo1",	0x000000f0,	0,		SROM4_5GL_MCSPO + 1,	0xffff},
+	{"mcs5glpo2",	0x000000f0,	0,		SROM4_5GL_MCSPO + 2,	0xffff},
+	{"mcs5glpo3",	0x000000f0,	0,		SROM4_5GL_MCSPO + 3,	0xffff},
+	{"mcs5glpo4",	0x000000f0,	0,		SROM4_5GL_MCSPO + 4,	0xffff},
+	{"mcs5glpo5",	0x000000f0,	0,		SROM4_5GL_MCSPO + 5,	0xffff},
+	{"mcs5glpo6",	0x000000f0,	0,		SROM4_5GL_MCSPO + 6,	0xffff},
+	{"mcs5glpo7",	0x000000f0,	0,		SROM4_5GL_MCSPO + 7,	0xffff},
+	{"mcs5ghpo0",	0x000000f0,	0,		SROM4_5GH_MCSPO,	0xffff},
+	{"mcs5ghpo1",	0x000000f0,	0,		SROM4_5GH_MCSPO + 1,	0xffff},
+	{"mcs5ghpo2",	0x000000f0,	0,		SROM4_5GH_MCSPO + 2,	0xffff},
+	{"mcs5ghpo3",	0x000000f0,	0,		SROM4_5GH_MCSPO + 3,	0xffff},
+	{"mcs5ghpo4",	0x000000f0,	0,		SROM4_5GH_MCSPO + 4,	0xffff},
+	{"mcs5ghpo5",	0x000000f0,	0,		SROM4_5GH_MCSPO + 5,	0xffff},
+	{"mcs5ghpo6",	0x000000f0,	0,		SROM4_5GH_MCSPO + 6,	0xffff},
+	{"mcs5ghpo7",	0x000000f0,	0,		SROM4_5GH_MCSPO + 7,	0xffff},
+	{"mcs2gpo0",	0x00000100,	0,		SROM8_2G_MCSPO,		0xffff},
+	{"mcs2gpo1",	0x00000100,	0,		SROM8_2G_MCSPO + 1,	0xffff},
+	{"mcs2gpo2",	0x00000100,	0,		SROM8_2G_MCSPO + 2,	0xffff},
+	{"mcs2gpo3",	0x00000100,	0,		SROM8_2G_MCSPO + 3,	0xffff},
+	{"mcs2gpo4",	0x00000100,	0,		SROM8_2G_MCSPO + 4,	0xffff},
+	{"mcs2gpo5",	0x00000100,	0,		SROM8_2G_MCSPO + 5,	0xffff},
+	{"mcs2gpo6",	0x00000100,	0,		SROM8_2G_MCSPO + 6,	0xffff},
+	{"mcs2gpo7",	0x00000100,	0,		SROM8_2G_MCSPO + 7,	0xffff},
+	{"mcs5gpo0",	0x00000100,	0,		SROM8_5G_MCSPO,		0xffff},
+	{"mcs5gpo1",	0x00000100,	0,		SROM8_5G_MCSPO + 1,	0xffff},
+	{"mcs5gpo2",	0x00000100,	0,		SROM8_5G_MCSPO + 2,	0xffff},
+	{"mcs5gpo3",	0x00000100,	0,		SROM8_5G_MCSPO + 3,	0xffff},
+	{"mcs5gpo4",	0x00000100,	0,		SROM8_5G_MCSPO + 4,	0xffff},
+	{"mcs5gpo5",	0x00000100,	0,		SROM8_5G_MCSPO + 5,	0xffff},
+	{"mcs5gpo6",	0x00000100,	0,		SROM8_5G_MCSPO + 6,	0xffff},
+	{"mcs5gpo7",	0x00000100,	0,		SROM8_5G_MCSPO + 7,	0xffff},
+	{"mcs5glpo0",	0x00000100,	0,		SROM8_5GL_MCSPO,	0xffff},
+	{"mcs5glpo1",	0x00000100,	0,		SROM8_5GL_MCSPO + 1,	0xffff},
+	{"mcs5glpo2",	0x00000100,	0,		SROM8_5GL_MCSPO + 2,	0xffff},
+	{"mcs5glpo3",	0x00000100,	0,		SROM8_5GL_MCSPO + 3,	0xffff},
+	{"mcs5glpo4",	0x00000100,	0,		SROM8_5GL_MCSPO + 4,	0xffff},
+	{"mcs5glpo5",	0x00000100,	0,		SROM8_5GL_MCSPO + 5,	0xffff},
+	{"mcs5glpo6",	0x00000100,	0,		SROM8_5GL_MCSPO + 6,	0xffff},
+	{"mcs5glpo7",	0x00000100,	0,		SROM8_5GL_MCSPO + 7,	0xffff},
+	{"mcs5ghpo0",	0x00000100,	0,		SROM8_5GH_MCSPO,	0xffff},
+	{"mcs5ghpo1",	0x00000100,	0,		SROM8_5GH_MCSPO + 1,	0xffff},
+	{"mcs5ghpo2",	0x00000100,	0,		SROM8_5GH_MCSPO + 2,	0xffff},
+	{"mcs5ghpo3",	0x00000100,	0,		SROM8_5GH_MCSPO + 3,	0xffff},
+	{"mcs5ghpo4",	0x00000100,	0,		SROM8_5GH_MCSPO + 4,	0xffff},
+	{"mcs5ghpo5",	0x00000100,	0,		SROM8_5GH_MCSPO + 5,	0xffff},
+	{"mcs5ghpo6",	0x00000100,	0,		SROM8_5GH_MCSPO + 6,	0xffff},
+	{"mcs5ghpo7",	0x00000100,	0,		SROM8_5GH_MCSPO + 7,	0xffff},
+	{"cddpo",	0x000000f0,	0,		SROM4_CDDPO,		0xffff},
+	{"stbcpo",	0x000000f0,	0,		SROM4_STBCPO,		0xffff},
+	{"bw40po",	0x000000f0,	0,		SROM4_BW40PO,		0xffff},
+	{"bwduppo",	0x000000f0,	0,		SROM4_BWDUPPO,		0xffff},
+	{"cddpo",	0x00000100,	0,		SROM8_CDDPO,		0xffff},
+	{"stbcpo",	0x00000100,	0,		SROM8_STBCPO,		0xffff},
+	{"bw40po",	0x00000100,	0,		SROM8_BW40PO,		0xffff},
+	{"bwduppo",	0x00000100,	0,		SROM8_BWDUPPO,		0xffff},
+
+	/* power per rate from sromrev 9 */
+	{"cckbw202gpo",		0x00000600,	0,	SROM9_2GPO_CCKBW20,		0xffff},
+	{"cckbw20ul2gpo",	0x00000600,	0,	SROM9_2GPO_CCKBW20UL,		0xffff},
+	{"legofdmbw202gpo",	0x00000600,	SRFL_MORE, SROM9_2GPO_LOFDMBW20,	0xffff},
+	{"",			0,		0,	SROM9_2GPO_LOFDMBW20 + 1,	0xffff},
+	{"legofdmbw20ul2gpo",	0x00000600,	SRFL_MORE, SROM9_2GPO_LOFDMBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_2GPO_LOFDMBW20UL + 1,	0xffff},
+	{"legofdmbw205glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_LOFDMBW20,	0xffff},
+	{"",			0,		0,	SROM9_5GLPO_LOFDMBW20 + 1,	0xffff},
+	{"legofdmbw20ul5glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GLPO_LOFDMBW20UL + 1,	0xffff},
+	{"legofdmbw205gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_LOFDMBW20,	0xffff},
+	{"",			0,		0,	SROM9_5GMPO_LOFDMBW20 + 1,	0xffff},
+	{"legofdmbw20ul5gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GMPO_LOFDMBW20UL + 1,	0xffff},
+	{"legofdmbw205ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_LOFDMBW20,	0xffff},
+	{"",			0,		0,	SROM9_5GHPO_LOFDMBW20 + 1,	0xffff},
+	{"legofdmbw20ul5ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GHPO_LOFDMBW20UL + 1,	0xffff},
+	{"mcsbw202gpo",		0x00000600,	SRFL_MORE, SROM9_2GPO_MCSBW20,		0xffff},
+	{"",			0,		0,	SROM9_2GPO_MCSBW20 + 1,		0xffff},
+	{"mcsbw20ul2gpo",      	0x00000600,	SRFL_MORE, SROM9_2GPO_MCSBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_2GPO_MCSBW20UL + 1,	0xffff},
+	{"mcsbw402gpo",		0x00000600,	SRFL_MORE, SROM9_2GPO_MCSBW40,		0xffff},
+	{"",			0,		0,	SROM9_2GPO_MCSBW40 + 1,		0xffff},
+	{"mcsbw205glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_MCSBW20,		0xffff},
+	{"",			0,		0,	SROM9_5GLPO_MCSBW20 + 1,	0xffff},
+	{"mcsbw20ul5glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_MCSBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GLPO_MCSBW20UL + 1,	0xffff},
+	{"mcsbw405glpo",	0x00000600,	SRFL_MORE, SROM9_5GLPO_MCSBW40,		0xffff},
+	{"",			0,		0,	SROM9_5GLPO_MCSBW40 + 1,	0xffff},
+	{"mcsbw205gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_MCSBW20,		0xffff},
+	{"",			0,		0,	SROM9_5GMPO_MCSBW20 + 1,	0xffff},
+	{"mcsbw20ul5gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_MCSBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GMPO_MCSBW20UL + 1,	0xffff},
+	{"mcsbw405gmpo",	0x00000600,	SRFL_MORE, SROM9_5GMPO_MCSBW40,		0xffff},
+	{"",			0,		0,	SROM9_5GMPO_MCSBW40 + 1,	0xffff},
+	{"mcsbw205ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_MCSBW20,		0xffff},
+	{"",			0,		0,	SROM9_5GHPO_MCSBW20 + 1,	0xffff},
+	{"mcsbw20ul5ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_MCSBW20UL,	0xffff},
+	{"",			0,		0,	SROM9_5GHPO_MCSBW20UL + 1,	0xffff},
+	{"mcsbw405ghpo",	0x00000600,	SRFL_MORE, SROM9_5GHPO_MCSBW40,		0xffff},
+	{"",			0,		0,	SROM9_5GHPO_MCSBW40 + 1,	0xffff},
+	{"mcs32po",		0x00000600,	0,	SROM9_PO_MCS32,			0xffff},
+	{"legofdm40duppo",	0x00000600,	0,	SROM9_PO_LOFDM40DUP,	0xffff},
+	{"pcieingress_war",	0x00000700,	0,	SROM8_PCIEINGRESS_WAR,	0xf},
+	{"eu_edthresh2g",	0x00000100,	0,	SROM8_EU_EDCRSTH,		0x00ff},
+	{"eu_edthresh5g",	0x00000100,	0,	SROM8_EU_EDCRSTH,		0xff00},
+	{"eu_edthresh2g",	0x00000200,	0,	SROM9_EU_EDCRSTH,		0x00ff},
+	{"eu_edthresh5g",	0x00000200,	0,	SROM9_EU_EDCRSTH,		0xff00},
+	{"rxgainerr2ga0",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0x003f},
+	{"rxgainerr2ga0",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0x003f},
+	{"rxgainerr2ga1",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0x07c0},
+	{"rxgainerr2ga2",	0x00000700,	0,	SROM8_RXGAINERR_2G,		0xf800},
+	{"rxgainerr5gla0",	0x00000700,	0,	SROM8_RXGAINERR_5GL,	0x003f},
+	{"rxgainerr5gla1",	0x00000700,	0,	SROM8_RXGAINERR_5GL,	0x07c0},
+	{"rxgainerr5gla2",	0x00000700,	0,	SROM8_RXGAINERR_5GL,	0xf800},
+	{"rxgainerr5gma0",	0x00000700,	0,	SROM8_RXGAINERR_5GM,	0x003f},
+	{"rxgainerr5gma1",	0x00000700,	0,	SROM8_RXGAINERR_5GM,	0x07c0},
+	{"rxgainerr5gma2",	0x00000700,	0,	SROM8_RXGAINERR_5GM,	0xf800},
+	{"rxgainerr5gha0",	0x00000700,	0,	SROM8_RXGAINERR_5GH,	0x003f},
+	{"rxgainerr5gha1",	0x00000700,	0,	SROM8_RXGAINERR_5GH,	0x07c0},
+	{"rxgainerr5gha2",	0x00000700,	0,	SROM8_RXGAINERR_5GH,	0xf800},
+	{"rxgainerr5gua0",	0x00000700,	0,	SROM8_RXGAINERR_5GU,	0x003f},
+	{"rxgainerr5gua1",	0x00000700,	0,	SROM8_RXGAINERR_5GU,	0x07c0},
+	{"rxgainerr5gua2",	0x00000700,	0,	SROM8_RXGAINERR_5GU,	0xf800},
+	{"sar2g",       	0x00000600,	0,	SROM9_SAR,          	0x00ff},
+	{"sar5g",           0x00000600,	0,	SROM9_SAR,	            0xff00},
+	{"noiselvl2ga0",	0x00000700,	0,	SROM8_NOISELVL_2G,		0x001f},
+	{"noiselvl2ga1",	0x00000700,	0,	SROM8_NOISELVL_2G,		0x03e0},
+	{"noiselvl2ga2",	0x00000700,	0,	SROM8_NOISELVL_2G,		0x7c00},
+	{"noiselvl5gla0",	0x00000700,	0,	SROM8_NOISELVL_5GL,		0x001f},
+	{"noiselvl5gla1",	0x00000700,	0,	SROM8_NOISELVL_5GL,		0x03e0},
+	{"noiselvl5gla2",	0x00000700,	0,	SROM8_NOISELVL_5GL,		0x7c00},
+	{"noiselvl5gma0",	0x00000700,	0,	SROM8_NOISELVL_5GM,		0x001f},
+	{"noiselvl5gma1",	0x00000700,	0,	SROM8_NOISELVL_5GM,		0x03e0},
+	{"noiselvl5gma2",	0x00000700,	0,	SROM8_NOISELVL_5GM,		0x7c00},
+	{"noiselvl5gha0",	0x00000700,	0,	SROM8_NOISELVL_5GH,		0x001f},
+	{"noiselvl5gha1",	0x00000700,	0,	SROM8_NOISELVL_5GH,		0x03e0},
+	{"noiselvl5gha2",	0x00000700,	0,	SROM8_NOISELVL_5GH,		0x7c00},
+	{"noiselvl5gua0",	0x00000700,	0,	SROM8_NOISELVL_5GU,		0x001f},
+	{"noiselvl5gua1",	0x00000700,	0,	SROM8_NOISELVL_5GU,		0x03e0},
+	{"noiselvl5gua2",	0x00000700,	0,	SROM8_NOISELVL_5GU,		0x7c00},
+	{"noisecaloffset",	0x00000300,	0,	SROM8_NOISECALOFFSET,		0x00ff},
+	{"noisecaloffset5g",	0x00000300,	0,	SROM8_NOISECALOFFSET,		0xff00},
+	{"subband5gver",	0x00000700,	0,	SROM8_SUBBAND_PPR,		0x7},
+
+	{"cckPwrOffset",	0x00000400,	0,	SROM10_CCKPWROFFSET,		0xffff},
+	{"eu_edthresh2g",	0x00000400,	0,	SROM10_EU_EDCRSTH,		0x00ff},
+	{"eu_edthresh5g",	0x00000400,	0,	SROM10_EU_EDCRSTH,		0xff00},
+	/* swctrlmap_2g array, note that the last element doesn't have SRFL_ARRAY flag set */
+	{"swctrlmap_2g", 0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G, 0xffff},
+	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 1,			0xffff},
+	{"",	0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 2, 	0xffff},
+	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 3,			0xffff},
+	{"",	0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 4,	0xffff},
+	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 5,			0xffff},
+	{"",	0x00000400, SRFL_MORE|SRFL_PRHEX|SRFL_ARRAY, SROM10_SWCTRLMAP_2G + 6,	0xffff},
+	{"",	0x00000400, SRFL_ARRAY,	SROM10_SWCTRLMAP_2G + 7,			0xffff},
+	{"",	0x00000400, SRFL_PRHEX,	SROM10_SWCTRLMAP_2G + 8,			0xffff},
+
+	/* sromrev 11 */
+	{"boardflags3",	0xfffff800,	SRFL_PRHEX|SRFL_MORE,	SROM11_BFL4,	0xffff},
+	{"",		0,		0,			SROM11_BFL5,	0xffff},
+	{"boardnum",	0xfffff800,	0,			SROM11_MACLO,	0xffff},
+	{"macaddr",	0xfffff800,	SRFL_ETHADDR,		SROM11_MACHI,	0xffff},
+	{"ccode",	0xfffff800,	SRFL_CCODE,		SROM11_CCODE,	0xffff},
+	{"regrev",	0xfffff800,	0,			SROM11_REGREV,	0xffff},
+	{"ledbh0",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH10,	0x00ff},
+	{"ledbh1",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH10,	0xff00},
+	{"ledbh2",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH32,	0x00ff},
+	{"ledbh3",	0xfffff800,	SRFL_NOFFS,		SROM11_LEDBH32,	0xff00},
+	{"leddc",	0xfffff800,	SRFL_NOFFS|SRFL_LEDDC,	SROM11_LEDDC,	0xffff},
+	{"aa2g",	0xfffff800,	0,			SROM11_AA,	0x00ff},
+	{"aa5g",	0xfffff800,	0,			SROM11_AA,	0xff00},
+	{"agbg0",	0xfffff800,	0,			SROM11_AGBG10,  0xff00},
+	{"agbg1",	0xfffff800,	0,			SROM11_AGBG10,	0x00ff},
+	{"agbg2",	0xfffff800,	0,			SROM11_AGBG2A0,	0xff00},
+	{"aga0",	0xfffff800,	0,			SROM11_AGBG2A0,	0x00ff},
+	{"aga1",	0xfffff800,	0,			SROM11_AGA21,   0xff00},
+	{"aga2",	0xfffff800,	0,			SROM11_AGA21,	0x00ff},
+	{"txchain",	0xfffff800,	SRFL_NOFFS,	SROM11_TXRXC,	SROM4_TXCHAIN_MASK},
+	{"rxchain",	0xfffff800,	SRFL_NOFFS,	SROM11_TXRXC,	SROM4_RXCHAIN_MASK},
+	{"antswitch",	0xfffff800,	SRFL_NOFFS,	SROM11_TXRXC,	SROM4_SWITCH_MASK},
+
+	{"tssiposslope2g",	0xfffff800,	0,		SROM11_FEM_CFG1, 	0x0001},
+	{"epagain2g",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0x000e},
+	{"pdgain2g",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0x01f0},
+	{"tworangetssi2g",	0xfffff800,	0,		SROM11_FEM_CFG1, 	0x0200},
+	{"papdcap2g",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0x0400},
+	{"femctrl",		0xfffff800,	0,		SROM11_FEM_CFG1, 	0xf800},
+
+	{"tssiposslope5g",	0xfffff800,	0,		SROM11_FEM_CFG2, 	0x0001},
+	{"epagain5g",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0x000e},
+	{"pdgain5g",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0x01f0},
+	{"tworangetssi5g",	0xfffff800,	0,		SROM11_FEM_CFG2, 	0x0200},
+	{"papdcap5g",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0x0400},
+	{"gainctrlsph",		0xfffff800,	0,		SROM11_FEM_CFG2, 	0xf800},
+
+	{"tempthresh",		0xfffff800,	0,		SROM11_THERMAL,		0xff00},
+	{"tempoffset",		0xfffff800,	0,		SROM11_THERMAL,		0x00ff},
+	{"rawtempsense", 	0xfffff800,	SRFL_PRHEX,	SROM11_MPWR_RAWTS,	0x01ff},
+	{"measpower",		0xfffff800,	SRFL_PRHEX,	SROM11_MPWR_RAWTS,	0xfe00},
+	{"tempsense_slope",	0xfffff800,	SRFL_PRHEX, 	SROM11_TS_SLP_OPT_CORRX, 0x00ff},
+	{"tempcorrx",		0xfffff800,	SRFL_PRHEX, 	SROM11_TS_SLP_OPT_CORRX, 0xfc00},
+	{"tempsense_option",	0xfffff800,	SRFL_PRHEX,	SROM11_TS_SLP_OPT_CORRX, 0x0300},
+	{"xtalfreq",		0xfffff800,	0,		SROM11_XTAL_FREQ, 	0xffff},
+	{"txpwrbckof",	0x00000800,	SRFL_PRHEX,	SROM11_PATH0 + SROM11_2G_MAXP,	0xff00},
+	/* Special PA Params for 4350 5G Band, 40/80 MHz BW Ant #1 */
+	{"pa5gbw4080a1", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W0_A1, 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W1_A1,                 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_4080_W2_A1,                 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_4080_W0_A1,                 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_4080_PA,     0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_4080_PA + 1, 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA,     0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA + 1, 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_4080_PA + 2, 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_4080_PA,     0xffff},
+	{"", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_4080_PA + 1, 0xffff},
+	{"", 0xfffff800, SRFL_PRHEX,              SROM11_PATH2 + SROM11_5GB3_4080_PA + 2, 0xffff},
+	{"phycal_tempdelta",	0xfffff800,	0,		SROM11_PHYCAL_TEMPDELTA, 0x00ff},
+	{"temps_period",	0xfffff800,	0,		SROM11_PHYCAL_TEMPDELTA, 0x0f00},
+	{"temps_hysteresis",	0xfffff800,	0,		SROM11_PHYCAL_TEMPDELTA, 0xf000},
+	{"measpower1", 		0xfffff800,	SRFL_PRHEX,	SROM11_MPWR_1_AND_2, 	0x007f},
+	{"measpower2",		0xfffff800, 	SRFL_PRHEX,	SROM11_MPWR_1_AND_2, 	0x3f80},
+	{"tssifloor2g",		0xfffff800,	SRFL_PRHEX,	SROM11_TSSIFLOOR_2G,	0x03ff},
+	{"tssifloor5g",	0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GL,	0x03ff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GM,	0x03ff},
+	{"",		0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_TSSIFLOOR_5GH,	0x03ff},
+	{"",		0xfffff800,	SRFL_PRHEX,		SROM11_TSSIFLOOR_5GU,	0x03ff},
+	{"pdoffset2g40ma0",     0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x000f},
+	{"pdoffset2g40ma1",     0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x00f0},
+	{"pdoffset2g40ma2",     0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x0f00},
+	{"pdoffset2g40mvalid",  0xfffff800, 0,      SROM11_PDOFF_2G_40M,    0x8000},
+	{"pdoffset40ma0",      	0xfffff800,	0,		SROM11_PDOFF_40M_A0,   	0xffff},
+	{"pdoffset40ma1",      	0xfffff800,	0,		SROM11_PDOFF_40M_A1,   	0xffff},
+	{"pdoffset40ma2",      	0xfffff800,	0,		SROM11_PDOFF_40M_A2,   	0xffff},
+	{"pdoffset80ma0",      	0xfffff800,	0,		SROM11_PDOFF_80M_A0,   	0xffff},
+	{"pdoffset80ma1",      	0xfffff800,	0,		SROM11_PDOFF_80M_A1,   	0xffff},
+	{"pdoffset80ma2",      	0xfffff800,	0,		SROM11_PDOFF_80M_A2,   	0xffff},
+
+	{"subband5gver",	0xfffff800, 	SRFL_PRHEX,	SROM11_SUBBAND5GVER, 	0xffff},
+	{"paparambwver",	0xfffff800, 	0,		SROM11_MCSLR5GLPO, 	0xf000},
+	{"rx5ggainwar",         0xfffff800,     0,              SROM11_MCSLR5GMPO,      0x2000},
+	/* Special PA Params for 4350 5G Band, 40/80 MHz BW Ant #0 */
+	{"pa5gbw4080a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 +SROM11_5GB0_PA, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH2 + SROM11_5GB3_PA + 2, 0xffff},
+	/* Special PA Params for 4335 5G Band, 40 MHz BW */
+	{"pa5gbw40a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB0_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB1_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB2_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB3_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_5GB3_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH1 + SROM11_5GB3_PA + 2, 0xffff},
+	/* Special PA Params for 4335 5G Band, 80 MHz BW */
+	{"pa5gbw80a0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB0_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB1_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB2_PA + 2, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA,     0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH2 + SROM11_5GB3_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH2 + SROM11_5GB3_PA + 2, 0xffff},
+	/* Special PA Params for 4335 2G Band, CCK */
+	{"pa2gccka0", 0xfffff800, SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_2G_PA, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_PATH1 + SROM11_2G_PA + 1, 0xffff},
+	{"", 0xfffff800,	SRFL_PRHEX,              SROM11_PATH1 + SROM11_2G_PA + 2, 0xffff},
+
+	/* power per rate */
+	{"cckbw202gpo",		0xfffff800,	0,		SROM11_CCKBW202GPO, 	0xffff},
+	{"cckbw20ul2gpo",	0xfffff800,	0,		SROM11_CCKBW20UL2GPO, 	0xffff},
+	{"mcsbw202gpo",		0xfffff800,	SRFL_MORE,	SROM11_MCSBW202GPO,   	0xffff},
+	{"",            	0xfffff800, 	0,          	SROM11_MCSBW202GPO_1, 	0xffff},
+	{"mcsbw402gpo",		0xfffff800,	SRFL_MORE,	SROM11_MCSBW402GPO,   	0xffff},
+	{"",            	0xfffff800, 	0,   		SROM11_MCSBW402GPO_1, 	0xffff},
+	{"dot11agofdmhrbw202gpo", 0xfffff800, 	0, 	SROM11_DOT11AGOFDMHRBW202GPO, 	0xffff},
+	{"ofdmlrbw202gpo",	0xfffff800, 	0, 		SROM11_OFDMLRBW202GPO,	0xffff},
+	{"mcsbw205glpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW205GLPO, 	0xffff},
+	{"",           		0xfffff800, 	0,   		SROM11_MCSBW205GLPO_1, 	0xffff},
+	{"mcsbw405glpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW405GLPO, 	0xffff},
+	{"",           		0xfffff800, 	0,     		SROM11_MCSBW405GLPO_1, 	0xffff},
+	{"mcsbw805glpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW805GLPO, 	0xffff},
+	{"",           		0xfffff800, 	0,    		SROM11_MCSBW805GLPO_1, 	0xffff},
+	{"mcsbw205gmpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW205GMPO, 	0xffff},
+	{"",           		0xfffff800, 	0,     		SROM11_MCSBW205GMPO_1, 	0xffff},
+	{"mcsbw405gmpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW405GMPO, 	0xffff},
+	{"",           		0xfffff800, 	0,     		SROM11_MCSBW405GMPO_1, 	0xffff},
+	{"mcsbw805gmpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW805GMPO, 	0xffff},
+	{"",           		0xfffff800, 	0,   		SROM11_MCSBW805GMPO_1, 	0xffff},
+	{"mcsbw205ghpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW205GHPO, 	0xffff},
+	{"",           		0xfffff800, 	0,  		SROM11_MCSBW205GHPO_1, 	0xffff},
+	{"mcsbw405ghpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW405GHPO, 	0xffff},
+	{"",           		0xfffff800, 	0,   		SROM11_MCSBW405GHPO_1, 	0xffff},
+	{"mcsbw805ghpo",	0xfffff800,	SRFL_MORE,	SROM11_MCSBW805GHPO, 	0xffff},
+	{"",           		0xfffff800, 	0,    		SROM11_MCSBW805GHPO_1, 	0xffff},
+	{"mcslr5glpo",		0xfffff800,	0,		SROM11_MCSLR5GLPO, 	0x0fff},
+	{"mcslr5gmpo",		0xfffff800,	0,		SROM11_MCSLR5GMPO, 	0xffff},
+	{"mcslr5ghpo",		0xfffff800,	0,		SROM11_MCSLR5GHPO, 	0xffff},
+	{"sb20in40hrpo", 	0xfffff800,	0,	SROM11_SB20IN40HRPO,		0xffff},
+	{"sb20in80and160hr5glpo", 0xfffff800, 	0, 	SROM11_SB20IN80AND160HR5GLPO, 	0xffff},
+	{"sb40and80hr5glpo",	  0xfffff800, 	0,	SROM11_SB40AND80HR5GLPO,	0xffff},
+	{"sb20in80and160hr5gmpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160HR5GMPO, 	0xffff},
+	{"sb40and80hr5gmpo",	  0xfffff800, 	0,	SROM11_SB40AND80HR5GMPO,	0xffff},
+	{"sb20in80and160hr5ghpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160HR5GHPO, 	0xffff},
+	{"sb40and80hr5ghpo",	  0xfffff800, 	0,	SROM11_SB40AND80HR5GHPO,	0xffff},
+	{"sb20in40lrpo",	  0xfffff800, 	0,	SROM11_SB20IN40LRPO,		0xffff},
+	{"sb20in80and160lr5glpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160LR5GLPO, 	0xffff},
+	{"sb40and80lr5glpo",	  0xfffff800, 	0,	SROM11_SB40AND80LR5GLPO,	0xffff},
+	{"sb20in80and160lr5gmpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160LR5GMPO, 	0xffff},
+	{"sb40and80lr5gmpo",	  0xfffff800, 	0,	SROM11_SB40AND80LR5GMPO,	0xffff},
+	{"sb20in80and160lr5ghpo", 0xfffff800, 	0,	SROM11_SB20IN80AND160LR5GHPO, 	0xffff},
+	{"sb40and80lr5ghpo",	  0xfffff800, 	0,	SROM11_SB40AND80LR5GHPO,	0xffff},
+	{"dot11agduphrpo",	  0xfffff800, 	0,	SROM11_DOT11AGDUPHRPO,		0xffff},
+	{"dot11agduplrpo",	  0xfffff800, 	0,	SROM11_DOT11AGDUPLRPO,		0xffff},
+
+	/* Misc */
+	{"sar2g",       	0xfffff800,	0,	SROM11_SAR,          	0x00ff},
+	{"sar5g",           	0xfffff800,	0,	SROM11_SAR,		0xff00},
+
+	{"noiselvl2ga0",	0xfffff800,	0,		SROM11_NOISELVL_2G,	0x001f},
+	{"noiselvl2ga1",	0xfffff800,	0,		SROM11_NOISELVL_2G,	0x03e0},
+	{"noiselvl2ga2",	0xfffff800,	0,		SROM11_NOISELVL_2G,	0x7c00},
+	{"noiselvl5ga0",	0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GL,	0x001f},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GM,	0x001f},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GH,	0x001f},
+	{"",			0xfffff800,	0,		SROM11_NOISELVL_5GU,	0x001f},
+	{"noiselvl5ga1",	0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GL,	0x03e0},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GM,	0x03e0},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GH,	0x03e0},
+	{"",			0xfffff800,	0,		SROM11_NOISELVL_5GU,	0x03e0},
+	{"noiselvl5ga2",	0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GL,	0x7c00},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GM,	0x7c00},
+	{"",			0xfffff800,	SRFL_ARRAY,	SROM11_NOISELVL_5GH,	0x7c00},
+	{"",			0xfffff800,	0,		SROM11_NOISELVL_5GU,	0x7c00},
+	{"eu_edthresh2g",	0x00000800,	0,	        SROM11_EU_EDCRSTH,	0x00ff},
+	{"eu_edthresh5g",	0x00000800,	0,	        SROM11_EU_EDCRSTH,	0xff00},
+
+	{"rxgainerr2ga0", 	0xfffff800, 	0,    		SROM11_RXGAINERR_2G,    0x003f},
+	{"rxgainerr2ga1", 	0xfffff800, 	0,    		SROM11_RXGAINERR_2G,    0x07c0},
+	{"rxgainerr2ga2", 	0xfffff800, 	0,    		SROM11_RXGAINERR_2G,    0xf800},
+	{"rxgainerr5ga0",      	0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GL,   0x003f},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GM,   0x003f},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GH,   0x003f},
+	{"",      		0xfffff800, 	0,    		SROM11_RXGAINERR_5GU,   0x003f},
+	{"rxgainerr5ga1",      	0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GL,   0x07c0},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GM,   0x07c0},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GH,   0x07c0},
+	{"",      		0xfffff800, 	0,    		SROM11_RXGAINERR_5GU,   0x07c0},
+	{"rxgainerr5ga2",      	0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GL,   0xf800},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GM,   0xf800},
+	{"",      		0xfffff800, 	SRFL_ARRAY,    	SROM11_RXGAINERR_5GH,   0xf800},
+	{"",      		0xfffff800, 	0,    		SROM11_RXGAINERR_5GU,   0xf800},
+	{"rpcal2g",      	0xfffff800, 	0,		SROM11_RPCAL_2G,        0xffff},
+	{"rpcal5gb0",      	0xfffff800, 	0,		SROM11_RPCAL_5GL,       0xffff},
+	{"rpcal5gb1",      	0xfffff800, 	0,		SROM11_RPCAL_5GM,       0xffff},
+	{"rpcal5gb2",      	0xfffff800, 	0,		SROM11_RPCAL_5GH,       0xffff},
+	{"rpcal5gb3",      	0xfffff800, 	0,		SROM11_RPCAL_5GU,       0xffff},
+	{"txidxcap2g",      	0xfffff800, 	0,		SROM11_TXIDXCAP2G,      0x0ff0},
+	{"txidxcap5g",      	0xfffff800, 	0,		SROM11_TXIDXCAP5G,      0x0ff0},
+	{"pdoffsetcckma0",      0xfffff800,     0,              SROM11_PDOFF_2G_CCK,    0x000f},
+	{"pdoffsetcckma1",      0xfffff800,     0,              SROM11_PDOFF_2G_CCK,    0x00f0},
+	{"pdoffsetcckma2",      0xfffff800,     0,              SROM11_PDOFF_2G_CCK,    0x0f00},
+
+	/* sromrev 12 */
+	{"boardflags4",		0xfffff000,	SRFL_PRHEX|SRFL_MORE,	SROM12_BFL6,	0xffff},
+	{"",	0,	0,			SROM12_BFL7,	0xffff},
+	{"pdoffsetcck",		0xfffff000,	0,      SROM12_PDOFF_2G_CCK,       0xffff},
+	{"pdoffset20in40m5gb0",	0xfffff000,	0,      SROM12_PDOFF_20in40M_5G_B0,    0xffff},
+	{"pdoffset20in40m5gb1", 0xfffff000,	0,      SROM12_PDOFF_20in40M_5G_B1,    0xffff},
+	{"pdoffset20in40m5gb2", 0xfffff000,	0,      SROM12_PDOFF_20in40M_5G_B2,    0xffff},
+	{"pdoffset20in40m5gb3", 0xfffff000,	0,      SROM12_PDOFF_20in40M_5G_B3,    0xffff},
+	{"pdoffset20in40m5gb4", 0xfffff000,	0,      SROM12_PDOFF_20in40M_5G_B4,    0xffff},
+	{"pdoffset40in80m5gb0", 0xfffff000,	0,      SROM12_PDOFF_40in80M_5G_B0,    0xffff},
+	{"pdoffset40in80m5gb1", 0xfffff000,	0,      SROM12_PDOFF_40in80M_5G_B1,    0xffff},
+	{"pdoffset40in80m5gb2", 0xfffff000,	0,      SROM12_PDOFF_40in80M_5G_B2,    0xffff},
+	{"pdoffset40in80m5gb3", 0xfffff000,	0,      SROM12_PDOFF_40in80M_5G_B3,    0xffff},
+	{"pdoffset40in80m5gb4", 0xfffff000,	0,      SROM12_PDOFF_40in80M_5G_B4,    0xffff},
+	{"pdoffset20in80m5gb0", 0xfffff000,	0,      SROM12_PDOFF_20in80M_5G_B0,    0xffff},
+	{"pdoffset20in80m5gb1", 0xfffff000,	0,      SROM12_PDOFF_20in80M_5G_B1,    0xffff},
+	{"pdoffset20in80m5gb2", 0xfffff000,	0,      SROM12_PDOFF_20in80M_5G_B2,    0xffff},
+	{"pdoffset20in80m5gb3", 0xfffff000,	0,      SROM12_PDOFF_20in80M_5G_B3,    0xffff},
+	{"pdoffset20in80m5gb4", 0xfffff000,	0,      SROM12_PDOFF_20in80M_5G_B4,    0xffff},
+
+	/* power per rate */
+	{"mcsbw205gx1po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW205GX1PO,   0xffff},
+	{"",                    0xfffff000,     0,              SROM12_MCSBW205GX1PO_1, 0xffff},
+	{"mcsbw405gx1po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW405GX1PO,   0xffff},
+	{"",                    0xfffff000,     0,              SROM12_MCSBW405GX1PO_1, 0xffff},
+	{"mcsbw805gx1po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW805GX1PO,   0xffff},
+	{"",                    0xfffff000,     0,              SROM12_MCSBW805GX1PO_1, 0xffff},
+	{"mcsbw205gx2po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW205GX2PO,   0xffff},
+	{"",                    0xfffff000,     0,              SROM12_MCSBW205GX2PO_1, 0xffff},
+	{"mcsbw405gx2po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW405GX2PO,   0xffff},
+	{"",                    0xfffff000,     0,              SROM12_MCSBW405GX2PO_1, 0xffff},
+	{"mcsbw805gx2po",       0xfffff000,     SRFL_MORE,      SROM12_MCSBW805GX2PO,   0xffff},
+	{"",                    0xfffff000,     0,              SROM12_MCSBW805GX2PO_1, 0xffff},
+
+	{"sb20in80and160hr5gx1po", 0xfffff000,  0,      SROM12_SB20IN80AND160HR5GX1PO,  0xffff},
+	{"sb40and80hr5gx1po",     0xfffff000,   0,      SROM12_SB40AND80HR5GX1PO,       0xffff},
+	{"sb20in80and160lr5gx1po", 0xfffff000,  0,      SROM12_SB20IN80AND160LR5GX1PO,  0xffff},
+	{"sb40and80hr5gx1po",     0xfffff000,   0,      SROM12_SB40AND80HR5GX1PO,       0xffff},
+	{"sb20in80and160hr5gx2po", 0xfffff000,  0,      SROM12_SB20IN80AND160HR5GX2PO,  0xffff},
+	{"sb40and80hr5gx2po",     0xfffff000,   0,      SROM12_SB40AND80HR5GX2PO,       0xffff},
+	{"sb20in80and160lr5gx2po", 0xfffff000,  0,      SROM12_SB20IN80AND160LR5GX2PO,  0xffff},
+	{"sb40and80hr5gx2po",     0xfffff000,   0,      SROM12_SB40AND80HR5GX2PO,       0xffff},
+
+	{"rxgains5gmelnagaina0",	0xfffff000,	0,       SROM12_RXGAINS10,	0x0007},
+	{"rxgains5gmelnagaina1",	0xfffff000,	0,       SROM12_RXGAINS11,	0x0007},
+	{"rxgains5gmelnagaina2",	0xfffff000,	0,       SROM12_RXGAINS12,	0x0007},
+	{"rxgains5gmtrisoa0",	0xfffff000,	0,       SROM12_RXGAINS10,	0x0078},
+	{"rxgains5gmtrisoa1",	0xfffff000,	0,       SROM12_RXGAINS11,	0x0078},
+	{"rxgains5gmtrisoa2",	0xfffff000,	0,       SROM12_RXGAINS12,	0x0078},
+	{"rxgains5gmtrelnabypa0", 0xfffff000,	0,       SROM12_RXGAINS10,	0x0080},
+	{"rxgains5gmtrelnabypa1", 0xfffff000,	0,       SROM12_RXGAINS11,	0x0080},
+	{"rxgains5gmtrelnabypa2", 0xfffff000,	0,       SROM12_RXGAINS12,	0x0080},
+	{"rxgains5ghelnagaina0",	0xfffff000,	0,       SROM12_RXGAINS10,	0x0700},
+	{"rxgains5ghelnagaina1",	0xfffff000,	0,       SROM12_RXGAINS11,	0x0700},
+	{"rxgains5ghelnagaina2",	0xfffff000,	0,       SROM12_RXGAINS12,	0x0700},
+	{"rxgains5ghtrisoa0",	0xfffff000,	0,	 SROM12_RXGAINS10,	0x7800},
+	{"rxgains5ghtrisoa1",	0xfffff000,	0,	 SROM12_RXGAINS11,	0x7800},
+	{"rxgains5ghtrisoa2",	0xfffff000,	0,	 SROM12_RXGAINS12,	0x7800},
+	{"rxgains5ghtrelnabypa0", 0xfffff000,	0,	 SROM12_RXGAINS10,	0x8000},
+	{"rxgains5ghtrelnabypa1", 0xfffff000,	0,	 SROM12_RXGAINS11,	0x8000},
+	{"rxgains5ghtrelnabypa2", 0xfffff000,	0,	 SROM12_RXGAINS12,	0x8000},
+	{"eu_edthresh2g",	0x00001000,	0,       SROM12_EU_EDCRSTH,	0x00ff},
+	{"eu_edthresh5g",	0x00001000,	0,       SROM12_EU_EDCRSTH,	0xff00},
+
+	{"gpdn",		0xfffff000,	SRFL_PRHEX|SRFL_MORE,	SROM12_GPDN_L,	0xffff},
+	{"",			0,		0,			SROM12_GPDN_H,	0xffff},
+
+	{"rpcal2gcore3",        0xffffe000, 	0,	SROM13_RPCAL2GCORE3,            0x00ff},
+	{"rpcal5gb0core3",      0xffffe000, 	0,	SROM13_RPCAL5GB01CORE3,         0x00ff},
+	{"rpcal5gb1core3",      0xffffe000, 	0,	SROM13_RPCAL5GB01CORE3,         0xff00},
+	{"rpcal5gb2core3",      0xffffe000, 	0,	SROM13_RPCAL5GB23CORE3,         0x00ff},
+	{"rpcal5gb3core3",      0xffffe000, 	0,	SROM13_RPCAL5GB23CORE3,         0xff00},
+
+	{"sw_txchain_mask",	0xffffe000,	0,	SROM13_SW_TXRX_MASK,	0x000f},
+	{"sw_rxchain_mask",	0xffffe000,	0,	SROM13_SW_TXRX_MASK,	0x00f0},
+
+	{"eu_edthresh2g",       0x00002000,     0,       SROM13_EU_EDCRSTH,     0x00ff},
+	{"eu_edthresh5g",       0x00002000,     0,       SROM13_EU_EDCRSTH,     0xff00},
+
+	{"agbg3",       0xffffe000,     0,              SROM13_ANTGAIN_BANDBGA, 0xff00},
+	{"aga3",        0xffffe000,     0,              SROM13_ANTGAIN_BANDBGA, 0x00ff},
+	{"noiselvl2ga3",        0xffffe000,     0,              SROM13_NOISELVLCORE3,   0x001f},
+	{"noiselvl5ga3",        0xffffe000,     SRFL_ARRAY,     SROM13_NOISELVLCORE3,   0x03e0},
+	{"",                    0xffffe000,     SRFL_ARRAY,     SROM13_NOISELVLCORE3,   0x7c00},
+	{"",                    0xffffe000,     SRFL_ARRAY,     SROM13_NOISELVLCORE3_1, 0x001f},
+	{"",                    0xffffe000,     0,              SROM13_NOISELVLCORE3_1, 0x03e0},
+	{"rxgainerr2ga3",       0xffffe000,     0,              SROM13_RXGAINERRCORE3,  0x001f},
+	{"rxgainerr5ga3",       0xffffe000,     SRFL_ARRAY,     SROM13_RXGAINERRCORE3,  0x03e0},
+	{"",                    0xffffe000,     SRFL_ARRAY,     SROM13_RXGAINERRCORE3,  0x7c00},
+	{"",                    0xffffe000,     SRFL_ARRAY,     SROM13_RXGAINERRCORE3_1, 0x001f},
+	{"",                    0xffffe000,     0,              SROM13_RXGAINERRCORE3_1, 0x03e0},
+	{"rxgains5gmelnagaina3",        0xffffe000,     0,       SROM13_RXGAINS1CORE3,  0x0007},
+	{"rxgains5gmtrisoa3",   0xffffe000,     0,       SROM13_RXGAINS1CORE3,  0x0078},
+	{"rxgains5gmtrelnabypa3", 0xffffe000,   0,       SROM13_RXGAINS1CORE3,  0x0080},
+	{"rxgains5ghelnagaina3",        0xffffe000,     0,       SROM13_RXGAINS1CORE3,  0x0700},
+	{"rxgains5ghtrisoa3",   0xffffe000,     0,       SROM13_RXGAINS1CORE3,  0x7800},
+	{"rxgains5ghtrelnabypa3", 0xffffe000,   0,       SROM13_RXGAINS1CORE3,  0x8000},
+
+	/* pdoffset */
+	{"pdoffset20in40m5gcore3",   0xffffe000, 0,     SROM13_PDOFFSET20IN40M5GCORE3,   0xffff},
+	{"pdoffset20in40m5gcore3_1", 0xffffe000, 0,     SROM13_PDOFFSET20IN40M5GCORE3_1, 0xffff},
+	{"pdoffset20in80m5gcore3",   0xffffe000, 0,     SROM13_PDOFFSET20IN80M5GCORE3,   0xffff},
+	{"pdoffset20in80m5gcore3_1", 0xffffe000, 0,     SROM13_PDOFFSET20IN80M5GCORE3_1, 0xffff},
+	{"pdoffset40in80m5gcore3",   0xffffe000, 0,     SROM13_PDOFFSET40IN80M5GCORE3,   0xffff},
+	{"pdoffset40in80m5gcore3_1", 0xffffe000, 0,     SROM13_PDOFFSET40IN80M5GCORE3_1, 0xffff},
+
+	{"pdoffset20in40m2g",        0xffffe000, 0,     SROM13_PDOFFSET20IN40M2G,        0xffff},
+	{"pdoffset20in40m2gcore3",   0xffffe000, 0,     SROM13_PDOFFSET20IN40M2GCORE3,   0xffff},
+	{"pdoffsetcck20m",           0xffffe000, 0,     SROM13_PDOFF_2G_CCK_20M,         0xffff},
+
+	/* power per rate */
+	{"mcs1024qam2gpo",      0xffffe000,     0,           SROM13_MCS1024QAM2GPO,     0xffff},
+	{"mcs1024qam5glpo",     0xffffe000,     SRFL_MORE,   SROM13_MCS1024QAM5GLPO,    0xffff},
+	{"",                    0xffffe000,     0,           SROM13_MCS1024QAM5GLPO_1,  0xffff},
+	{"mcs1024qam5gmpo",     0xffffe000,     SRFL_MORE,   SROM13_MCS1024QAM5GMPO,    0xffff},
+	{"",                    0xffffe000,     0,           SROM13_MCS1024QAM5GMPO_1,  0xffff},
+	{"mcs1024qam5ghpo",     0xffffe000,     SRFL_MORE,   SROM13_MCS1024QAM5GHPO,    0xffff},
+	{"",                    0xffffe000,     0,           SROM13_MCS1024QAM5GHPO_1,  0xffff},
+	{"mcs1024qam5gx1po",    0xffffe000,     SRFL_MORE,   SROM13_MCS1024QAM5GX1PO,   0xffff},
+	{"",                    0xffffe000,     0,           SROM13_MCS1024QAM5GX1PO_1, 0xffff},
+	{"mcs1024qam5gx2po",    0xffffe000,     SRFL_MORE,   SROM13_MCS1024QAM5GX2PO,   0xffff},
+	{"",                    0xffffe000,     0,           SROM13_MCS1024QAM5GX2PO_1, 0xffff},
+
+	{"mcsbw1605glpo",       0xffffe000,     SRFL_MORE,      SROM13_MCSBW1605GLPO,   0xffff},
+	{"",                    0xffffe000,     0,              SROM13_MCSBW1605GLPO_1, 0xffff},
+	{"mcsbw1605gmpo",       0xffffe000,     SRFL_MORE,      SROM13_MCSBW1605GMPO,   0xffff},
+	{"",                    0xffffe000,     0,              SROM13_MCSBW1605GMPO_1, 0xffff},
+	{"mcsbw1605ghpo",       0xffffe000,     SRFL_MORE,      SROM13_MCSBW1605GHPO,   0xffff},
+	{"",                    0xffffe000,     0,              SROM13_MCSBW1605GHPO_1, 0xffff},
+	{"mcsbw1605gx1po",      0xffffe000,     SRFL_MORE,      SROM13_MCSBW1605GX1PO,  0xffff},
+	{"",                    0xffffe000,     0,      SROM13_MCSBW1605GX1PO_1,        0xffff},
+	{"mcsbw1605gx2po",      0xffffe000,     SRFL_MORE,      SROM13_MCSBW1605GX2PO,  0xffff},
+	{"",                    0xffffe000,     0,      SROM13_MCSBW1605GX2PO_1,        0xffff},
+
+	{"ulbpproffs2g",        0xffffe000,     0,      SROM13_ULBPPROFFS2G,            0xffff},
+
+	{"mcs8poexp",           0xffffe000,     SRFL_MORE,    SROM13_MCS8POEXP,         0xffff},
+	{"",                    0xffffe000,     0,            SROM13_MCS8POEXP_1,       0xffff},
+	{"mcs9poexp",           0xffffe000,     SRFL_MORE,    SROM13_MCS9POEXP,         0xffff},
+	{"",                    0xffffe000,     0,            SROM13_MCS9POEXP_1,       0xffff},
+	{"mcs10poexp",          0xffffe000,     SRFL_MORE,    SROM13_MCS10POEXP,        0xffff},
+	{"",                    0xffffe000,     0,            SROM13_MCS10POEXP_1,      0xffff},
+	{"mcs11poexp",          0xffffe000,     SRFL_MORE,    SROM13_MCS11POEXP,        0xffff},
+	{"",                    0xffffe000,     0,            SROM13_MCS11POEXP_1,      0xffff},
+
+	{"ulbpdoffs5gb0a0",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB0A0,         0xffff},
+	{"ulbpdoffs5gb0a1",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB0A1,         0xffff},
+	{"ulbpdoffs5gb0a2",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB0A2,         0xffff},
+	{"ulbpdoffs5gb0a3",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB0A3,         0xffff},
+	{"ulbpdoffs5gb1a0",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB1A0,         0xffff},
+	{"ulbpdoffs5gb1a1",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB1A1,         0xffff},
+	{"ulbpdoffs5gb1a2",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB1A2,         0xffff},
+	{"ulbpdoffs5gb1a3",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB1A3,         0xffff},
+	{"ulbpdoffs5gb2a0",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB2A0,         0xffff},
+	{"ulbpdoffs5gb2a1",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB2A1,         0xffff},
+	{"ulbpdoffs5gb2a2",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB2A2,         0xffff},
+	{"ulbpdoffs5gb2a3",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB2A3,         0xffff},
+	{"ulbpdoffs5gb3a0",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB3A0,         0xffff},
+	{"ulbpdoffs5gb3a1",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB3A1,         0xffff},
+	{"ulbpdoffs5gb3a2",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB3A2,         0xffff},
+	{"ulbpdoffs5gb3a3",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB3A3,         0xffff},
+	{"ulbpdoffs5gb4a0",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB4A0,         0xffff},
+	{"ulbpdoffs5gb4a1",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB4A1,         0xffff},
+	{"ulbpdoffs5gb4a2",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB4A2,         0xffff},
+	{"ulbpdoffs5gb4a3",     0xffffe000,     0,      SROM13_ULBPDOFFS5GB4A3,         0xffff},
+	{"ulbpdoffs2ga0",       0xffffe000,     0,      SROM13_ULBPDOFFS2GA0,           0xffff},
+	{"ulbpdoffs2ga1",       0xffffe000,     0,      SROM13_ULBPDOFFS2GA1,           0xffff},
+	{"ulbpdoffs2ga2",       0xffffe000,     0,      SROM13_ULBPDOFFS2GA2,           0xffff},
+	{"ulbpdoffs2ga3",       0xffffe000,     0,      SROM13_ULBPDOFFS2GA3,           0xffff},
+
+	{"rpcal5gb4",           0xffffe000,     0,      SROM13_RPCAL5GB4,               0xffff},
+
+	{"sb20in40hrlrpox",     0xffffe000,     0,       SROM13_SB20IN40HRLRPOX,        0xffff},
+
+	{"swctrlmap4_cfg",      0xffffe000,     0,      SROM13_SWCTRLMAP4_CFG,          0xffff},
+	{"swctrlmap4_TX2g_fem3to0", 0xffffe000, 0,      SROM13_SWCTRLMAP4_TX2G_FEM3TO0, 0xffff},
+	{"swctrlmap4_RX2g_fem3to0", 0xffffe000, 0,      SROM13_SWCTRLMAP4_RX2G_FEM3TO0, 0xffff},
+	{"swctrlmap4_RXByp2g_fem3to0", 0xffffe000, 0, SROM13_SWCTRLMAP4_RXBYP2G_FEM3TO0, 0xffff},
+	{"swctrlmap4_misc2g_fem3to0", 0xffffe000, 0,  SROM13_SWCTRLMAP4_MISC2G_FEM3TO0, 0xffff},
+	{"swctrlmap4_TX5g_fem3to0", 0xffffe000, 0,      SROM13_SWCTRLMAP4_TX5G_FEM3TO0, 0xffff},
+	{"swctrlmap4_RX5g_fem3to0", 0xffffe000, 0,      SROM13_SWCTRLMAP4_RX5G_FEM3TO0, 0xffff},
+	{"swctrlmap4_RXByp5g_fem3to0", 0xffffe000, 0, SROM13_SWCTRLMAP4_RXBYP5G_FEM3TO0, 0xffff},
+	{"swctrlmap4_misc5g_fem3to0", 0xffffe000, 0,  SROM13_SWCTRLMAP4_MISC5G_FEM3TO0, 0xffff},
+	{"swctrlmap4_TX2g_fem7to4", 0xffffe000, 0,      SROM13_SWCTRLMAP4_TX2G_FEM7TO4, 0xffff},
+	{"swctrlmap4_RX2g_fem7to4", 0xffffe000, 0,      SROM13_SWCTRLMAP4_RX2G_FEM7TO4, 0xffff},
+	{"swctrlmap4_RXByp2g_fem7to4", 0xffffe000, 0, SROM13_SWCTRLMAP4_RXBYP2G_FEM7TO4, 0xffff},
+	{"swctrlmap4_misc2g_fem7to4", 0xffffe000, 0,  SROM13_SWCTRLMAP4_MISC2G_FEM7TO4, 0xffff},
+	{"swctrlmap4_TX5g_fem7to4", 0xffffe000, 0,      SROM13_SWCTRLMAP4_TX5G_FEM7TO4, 0xffff},
+	{"swctrlmap4_RX5g_fem7to4", 0xffffe000, 0,      SROM13_SWCTRLMAP4_RX5G_FEM7TO4, 0xffff},
+	{"swctrlmap4_RXByp5g_fem7to4", 0xffffe000, 0, SROM13_SWCTRLMAP4_RXBYP5G_FEM7TO4, 0xffff},
+	{"swctrlmap4_misc5g_fem7to4", 0xffffe000, 0,  SROM13_SWCTRLMAP4_MISC5G_FEM7TO4, 0xffff},
+	{NULL,		0,		0,		0,			0}
+};
+#endif /* !defined(SROM15_MEMOPT) */
+
+static const sromvar_t BCMATTACHDATA(pci_srom15vars)[] = {
+	{"macaddr",	0x00008000,	SRFL_ETHADDR,		SROM15_MACHI,	0xffff},
+	{"caldata_offset", 0x00008000, 0, SROM15_CAL_OFFSET_LOC, 0xffff},
+	{NULL,		0,		0,		0,			0}
+};
+
+static const sromvar_t perpath_pci_sromvars[] = {
+	{"maxp2ga",	0x000000f0,	0,		SROM4_2G_ITT_MAXP,	0x00ff},
+	{"itt2ga",	0x000000f0,	0,		SROM4_2G_ITT_MAXP,	0xff00},
+	{"itt5ga",	0x000000f0,	0,		SROM4_5G_ITT_MAXP,	0xff00},
+	{"pa2gw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA,		0xffff},
+	{"pa2gw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA + 1,	0xffff},
+	{"pa2gw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA + 2,	0xffff},
+	{"pa2gw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_2G_PA + 3,	0xffff},
+	{"maxp5ga",	0x000000f0,	0,		SROM4_5G_ITT_MAXP,	0x00ff},
+	{"maxp5gha",	0x000000f0,	0,		SROM4_5GLH_MAXP,	0x00ff},
+	{"maxp5gla",	0x000000f0,	0,		SROM4_5GLH_MAXP,	0xff00},
+	{"pa5gw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA,		0xffff},
+	{"pa5gw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA + 1,	0xffff},
+	{"pa5gw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA + 2,	0xffff},
+	{"pa5gw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_5G_PA + 3,	0xffff},
+	{"pa5glw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA,		0xffff},
+	{"pa5glw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA + 1,	0xffff},
+	{"pa5glw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA + 2,	0xffff},
+	{"pa5glw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GL_PA + 3,	0xffff},
+	{"pa5ghw0a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA,		0xffff},
+	{"pa5ghw1a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA + 1,	0xffff},
+	{"pa5ghw2a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA + 2,	0xffff},
+	{"pa5ghw3a",	0x000000f0,	SRFL_PRHEX,	SROM4_5GH_PA + 3,	0xffff},
+	{"maxp2ga",	0x00000700,	0,		SROM8_2G_ITT_MAXP,	0x00ff},
+	{"itt2ga",	0x00000700,	0,		SROM8_2G_ITT_MAXP,	0xff00},
+	{"itt5ga",	0x00000700,	0,		SROM8_5G_ITT_MAXP,	0xff00},
+	{"pa2gw0a",	0x00000700,	SRFL_PRHEX,	SROM8_2G_PA,		0xffff},
+	{"pa2gw1a",	0x00000700,	SRFL_PRHEX,	SROM8_2G_PA + 1,	0xffff},
+	{"pa2gw2a",	0x00000700,	SRFL_PRHEX,	SROM8_2G_PA + 2,	0xffff},
+	{"maxp5ga",	0x00000700,	0,		SROM8_5G_ITT_MAXP,	0x00ff},
+	{"maxp5gha",	0x00000700,	0,		SROM8_5GLH_MAXP,	0x00ff},
+	{"maxp5gla",	0x00000700,	0,		SROM8_5GLH_MAXP,	0xff00},
+	{"pa5gw0a",	0x00000700,	SRFL_PRHEX,	SROM8_5G_PA,		0xffff},
+	{"pa5gw1a",	0x00000700,	SRFL_PRHEX,	SROM8_5G_PA + 1,	0xffff},
+	{"pa5gw2a",	0x00000700,	SRFL_PRHEX,	SROM8_5G_PA + 2,	0xffff},
+	{"pa5glw0a",	0x00000700,	SRFL_PRHEX,	SROM8_5GL_PA,		0xffff},
+	{"pa5glw1a",	0x00000700,	SRFL_PRHEX,	SROM8_5GL_PA + 1,	0xffff},
+	{"pa5glw2a",	0x00000700,	SRFL_PRHEX,	SROM8_5GL_PA + 2,	0xffff},
+	{"pa5ghw0a",	0x00000700,	SRFL_PRHEX,	SROM8_5GH_PA,		0xffff},
+	{"pa5ghw1a",	0x00000700,	SRFL_PRHEX,	SROM8_5GH_PA + 1,	0xffff},
+	{"pa5ghw2a",	0x00000700,	SRFL_PRHEX,	SROM8_5GH_PA + 2,	0xffff},
+
+	/* sromrev 11 */
+	{"maxp2ga",	0xfffff800,	0,			 SROM11_2G_MAXP,	0x00ff},
+	{"pa2ga",	0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA,		0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_2G_PA + 1,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX,		 SROM11_2G_PA + 2,	0xffff},
+	{"rxgains5gmelnagaina",	0x00000800,	0,		 SROM11_RXGAINS1,	0x0007},
+	{"rxgains5gmtrisoa",	0x00000800,	0,		 SROM11_RXGAINS1,	0x0078},
+	{"rxgains5gmtrelnabypa", 0x00000800,	0,		 SROM11_RXGAINS1,	0x0080},
+	{"rxgains5ghelnagaina",	0x00000800,	0,		 SROM11_RXGAINS1,	0x0700},
+	{"rxgains5ghtrisoa",	0x00000800,	0,		 SROM11_RXGAINS1,	0x7800},
+	{"rxgains5ghtrelnabypa", 0x00000800,	0,		 SROM11_RXGAINS1,	0x8000},
+	{"rxgains2gelnagaina",	0x00000800,	0,		 SROM11_RXGAINS,	0x0007},
+	{"rxgains2gtrisoa",	0x00000800,	0,		 SROM11_RXGAINS,	0x0078},
+	{"rxgains2gtrelnabypa",	0x00000800,	0,		 SROM11_RXGAINS,	0x0080},
+	{"rxgains5gelnagaina",	0x00000800,	0,		 SROM11_RXGAINS,	0x0700},
+	{"rxgains5gtrisoa",	0x00000800,	0,		 SROM11_RXGAINS,	0x7800},
+	{"rxgains5gtrelnabypa",	0x00000800,	0,		 SROM11_RXGAINS,	0x8000},
+	{"maxp5ga",	0x00000800,	SRFL_ARRAY,		 SROM11_5GB1B0_MAXP,	0x00ff},
+	{"",		0x00000800,	SRFL_ARRAY,		 SROM11_5GB1B0_MAXP,	0xff00},
+	{"",		0x00000800,	SRFL_ARRAY,		 SROM11_5GB3B2_MAXP,	0x00ff},
+	{"",		0x00000800,	0,			 SROM11_5GB3B2_MAXP,	0xff00},
+	{"pa5ga",	0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 1,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB0_PA + 2,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 1,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB1_PA + 2,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 1,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB2_PA + 2,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX | SRFL_ARRAY, SROM11_5GB3_PA + 1,	0xffff},
+	{"",		0x00000800,	SRFL_PRHEX,		 SROM11_5GB3_PA + 2,	0xffff},
+
+	/* sromrev 12 */
+	{"maxp5gb4a",	0xfffff000,	0,		 SROM12_5GB42G_MAXP,	0x00ff00},
+	{"pa2ga",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,  SROM12_2GB0_PA_W0,	0x00ffff},
+	{"",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,	  SROM12_2GB0_PA_W1,	0x00ffff},
+	{"",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,	  SROM12_2GB0_PA_W2,	0x00ffff},
+	{"",	0xfffff000,	SRFL_PRHEX,		 SROM12_2GB0_PA_W3,	0x00ffff},
+
+	{"pa2g40a",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,  SROM12_2G40B0_PA_W0,	0x00ffff},
+	{"",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,	  SROM12_2G40B0_PA_W1,	0x00ffff},
+	{"",	0xfffff000,	SRFL_PRHEX | SRFL_ARRAY,	  SROM12_2G40B0_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX,		 SROM12_2G40B0_PA_W3,	0x00ffff},
+	{"maxp5gb0a",	0xfffff000, 0,	     SROM12_5GB1B0_MAXP,	0x00ff},
+	{"maxp5gb1a",	0xfffff000, 0,       SROM12_5GB1B0_MAXP,	0x00ff00},
+	{"maxp5gb2a",	0xfffff000, 0,	     SROM12_5GB3B2_MAXP,	0x00ff},
+	{"maxp5gb3a",	0xfffff000, 0,	     SROM12_5GB3B2_MAXP,	0x00ff00},
+
+	{"pa5ga",   0xfffff000, SRFL_PRHEX | SRFL_ARRAY,   SROM12_5GB0_PA_W0,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB0_PA_W1,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,         SROM12_5GB0_PA_W2,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB0_PA_W3,		0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB1_PA_W0,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB1_PA_W1,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB1_PA_W2,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB1_PA_W3,		0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB2_PA_W0,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB2_PA_W1,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB2_PA_W2,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB2_PA_W3,		0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB3_PA_W0,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB3_PA_W1,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,         SROM12_5GB3_PA_W2,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB3_PA_W3,		0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB4_PA_W0,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB4_PA_W1,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5GB4_PA_W2,		0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX,	                   SROM12_5GB4_PA_W3,		0x00ffff},
+
+	{"pa5g40a",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY, SROM12_5G40B0_PA_W0,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B0_PA_W1,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B0_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B0_PA_W3,	0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B1_PA_W0,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B1_PA_W1,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B1_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,         SROM12_5G40B1_PA_W3,	0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B2_PA_W0,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B2_PA_W1,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B2_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B2_PA_W3,	0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B3_PA_W0,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B3_PA_W1,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B3_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B3_PA_W3,	0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B4_PA_W0,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B4_PA_W1,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	     SROM12_5G40B4_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX,		             SROM12_5G40B4_PA_W3,	0x00ffff},
+
+	{"pa5g80a",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,	 SROM12_5G80B0_PA_W0,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B0_PA_W1,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B0_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B0_PA_W3,	0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B1_PA_W0,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B1_PA_W1,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B1_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B1_PA_W3,	0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B2_PA_W0,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B2_PA_W1,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B2_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B2_PA_W3,	0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B3_PA_W0,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B3_PA_W1,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B3_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B3_PA_W3,	0x00ffff},
+
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B4_PA_W0,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B4_PA_W1,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX | SRFL_ARRAY,		 SROM12_5G80B4_PA_W2,	0x00ffff},
+	{"",	0xfffff000, SRFL_PRHEX,		                 SROM12_5G80B4_PA_W3,	0x00ffff},
+	/* sromrev 13 */
+	{"rxgains2gelnagaina",   0xffffe000,     0,       SROM13_RXGAINS,  0x0007},
+	{"rxgains2gtrisoa",     0xffffe000,     0,       SROM13_RXGAINS,  0x0078},
+	{"rxgains2gtrelnabypa", 0xffffe000,     0,       SROM13_RXGAINS,  0x0080},
+	{"rxgains5gelnagaina",  0xffffe000,     0,       SROM13_RXGAINS,  0x0700},
+	{"rxgains5gtrisoa",     0xffffe000,     0,       SROM13_RXGAINS,  0x7800},
+	{"rxgains5gtrelnabypa", 0xffffe000,     0,       SROM13_RXGAINS,  0x8000},
+	{NULL,		0,		0,		0, 			0}
+};
+
+#if !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N))
+#define	PHY_TYPE_HT		7	/* HT-Phy value */
+#define	PHY_TYPE_N		4	/* N-Phy value */
+#endif /* !(defined(PHY_TYPE_HT) && defined(PHY_TYPE_N)) */
+#if !defined(PHY_TYPE_AC)
+#define	PHY_TYPE_AC		11	/* AC-Phy value */
+#endif /* !defined(PHY_TYPE_AC) */
+#if !defined(PHY_TYPE_LCN20)
+#define	PHY_TYPE_LCN20		12	/* LCN20-Phy value */
+#endif /* !defined(PHY_TYPE_LCN20) */
+#if !defined(PHY_TYPE_NULL)
+#define	PHY_TYPE_NULL		0xf	/* Invalid Phy value */
+#endif /* !defined(PHY_TYPE_NULL) */
+
+typedef struct {
+	uint16	phy_type;
+	uint16	bandrange;
+	uint16	chain;
+	const char *vars;
+} pavars_t;
+
+static const pavars_t pavars[] = {
+	/* HTPHY */
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G,  0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G,  1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_2G,  2, "pa2gw0a2 pa2gw1a2 pa2gw2a2"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND0, 2, "pa5glw0a2 pa5glw1a2 pa5glw2a2"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND1, 2, "pa5gw0a2 pa5gw1a2 pa5gw2a2"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND2, 2, "pa5ghw0a2 pa5ghw1a2 pa5ghw2a2"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 0, "pa5gw0a3 pa5gw1a3 pa5gw2a3"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 1,  "pa5glw0a3 pa5glw1a3 pa5glw2a3"},
+	{PHY_TYPE_HT, WL_CHAN_FREQ_RANGE_5G_BAND3, 2, "pa5ghw0a3 pa5ghw1a3 pa5ghw2a3"},
+	/* NPHY */
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,  0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,  1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND0, 0, "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND0, 1, "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND1, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND1, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND2, 0, "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5G_BAND2, 1, "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
+	/* ACPHY */
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  2, "pa2ga2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5ga2"},
+	/* LCN20PHY */
+	{PHY_TYPE_LCN20, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
+	{PHY_TYPE_NULL, 0, 0, ""}
+};
+
+
+static const pavars_t pavars_SROM12[] = {
+	/* ACPHY */
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  2, "pa2ga2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  0, "pa2g40a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  1, "pa2g40a1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  2, "pa2g40a2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  0, "pa5ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  1, "pa5ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  2, "pa5ga2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  0, "pa5g40a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  1, "pa5g40a1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  2, "pa5g40a2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  0, "pa5g80a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  1, "pa5g80a1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  2, "pa5g80a2"},
+	{PHY_TYPE_NULL, 0, 0, ""}
+};
+
+static const pavars_t pavars_SROM13[] = {
+	/* ACPHY */
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  2, "pa2ga2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  3, "pa2ga3"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  0, "pa2g40a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  1, "pa2g40a1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  2, "pa2g40a2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G_40,  3, "pa2g40a3"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  0, "pa5ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  1, "pa5ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  2, "pa5ga2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND,  3, "pa5ga3"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  0, "pa5g40a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  1, "pa5g40a1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  2, "pa5g40a2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_40,  3, "pa5g40a3"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  0, "pa5g80a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  1, "pa5g80a1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  2, "pa5g80a2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_5BAND_80,  3, "pa5g80a3"},
+	{PHY_TYPE_NULL, 0, 0, ""}
+};
+
+/* pavars table when paparambwver is 1 */
+static const pavars_t pavars_bwver_1[] = {
+	/* ACPHY */
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2gccka0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga2"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5gbw40a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5gbw80a0"},
+	{PHY_TYPE_NULL, 0, 0, ""}
+};
+
+/* pavars table when paparambwver is 2 */
+static const pavars_t pavars_bwver_2[] = {
+	/* ACPHY */
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5gbw4080a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  3, "pa5gbw4080a1"},
+	{PHY_TYPE_NULL, 0, 0, ""}
+};
+
+/* pavars table when paparambwver is 3 */
+static const pavars_t pavars_bwver_3[] = {
+	/* ACPHY */
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  0, "pa2ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  1, "pa2ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  2, "pa2gccka0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_2G,  3, "pa2gccka1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  0, "pa5ga0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  1, "pa5ga1"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  2, "pa5gbw4080a0"},
+	{PHY_TYPE_AC, WL_CHAN_FREQ_RANGE_5G_4BAND,  3, "pa5gbw4080a1"},
+	{PHY_TYPE_NULL, 0, 0, ""}
+};
+
+typedef struct {
+	uint16	phy_type;
+	uint16	bandrange;
+	const char *vars;
+} povars_t;
+
+static const povars_t povars[] = {
+	/* NPHY */
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,  "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 "
+	"mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 "
+	"mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 "
+	"mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 "
+	"mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"},
+	{PHY_TYPE_NULL, 0, ""}
+};
+
+typedef struct {
+	uint8	tag;		/* Broadcom subtag name */
+	uint32	revmask;	/* Supported cis_sromrev bitmask. Some of the parameters in
+				 * different tuples have the same name. Therefore, the MFGc tool
+				 * needs to know which tuple to generate when seeing these
+				 * parameters (given that we know sromrev from user input, like the
+				 * nvram file).
+				 */
+	uint8	len;		/* Length field of the tuple, note that it includes the
+				 * subtag name (1 byte): 1 + tuple content length
+				 */
+	const char *params;
+} cis_tuple_t;
+
+#define OTP_RAW		(0xff - 1)	/* Reserved tuple number for wrvar Raw input */
+#define OTP_VERS_1	(0xff - 2)	/* CISTPL_VERS_1 */
+#define OTP_MANFID	(0xff - 3)	/* CISTPL_MANFID */
+#define OTP_RAW1	(0xff - 4)	/* Like RAW, but comes first */
+
+/** this array is used by CIS creating/writing applications */
+static const cis_tuple_t cis_hnbuvars[] = {
+/*       tag			revmask   len  params */
+	{OTP_RAW1,		0xffffffff, 0, ""},	/* special case */
+	{OTP_VERS_1,	0xffffffff, 0, "smanf sproductname"},	/* special case (non BRCM tuple) */
+	{OTP_MANFID,	0xffffffff, 4, "2manfid 2prodid"},	/* special case (non BRCM tuple) */
+	/* Unified OTP: tupple to embed USB manfid inside SDIO CIS */
+	{HNBU_UMANFID,		0xffffffff, 8, "8usbmanfid"},
+	{HNBU_SROMREV,		0xffffffff, 2, "1sromrev"},
+	/* NOTE: subdevid is also written to boardtype.
+	 *       Need to write HNBU_BOARDTYPE to change it if it is different.
+	 */
+	{HNBU_CHIPID,		0xffffffff, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"},
+	{HNBU_BOARDREV,		0xffffffff, 3, "2boardrev"},
+	{HNBU_PAPARMS,		0xffffffff, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"},
+	{HNBU_AA,		0xffffffff, 3, "1aa2g 1aa5g"},
+	{HNBU_AA,		0xffffffff, 3, "1aa0 1aa1"}, /* backward compatibility */
+	{HNBU_AG,		0xffffffff, 5, "1ag0 1ag1 1ag2 1ag3"},
+	{HNBU_BOARDFLAGS,	0xffffffff, 21, "4boardflags 4boardflags2 4boardflags3 "
+	"4boardflags4 4boardflags5 "},
+	{HNBU_LEDS,		0xffffffff, 17, "1ledbh0 1ledbh1 1ledbh2 1ledbh3 1ledbh4 1ledbh5 "
+	"1ledbh6 1ledbh7 1ledbh8 1ledbh9 1ledbh10 1ledbh11 1ledbh12 1ledbh13 1ledbh14 1ledbh15"},
+	{HNBU_CCODE,		0xffffffff, 4, "2ccode 1cctl"},
+	{HNBU_CCKPO,		0xffffffff, 3, "2cckpo"},
+	{HNBU_OFDMPO,		0xffffffff, 5, "4ofdmpo"},
+	{HNBU_PAPARMS5G,	0xffffffff, 23, "2pa1b0 2pa1b1 2pa1b2 2pa1lob0 2pa1lob1 2pa1lob2 "
+	"2pa1hib0 2pa1hib1 2pa1hib2 1pa1itssit "
+	"1pa1maxpwr 1pa1lomaxpwr 1pa1himaxpwr"},
+	{HNBU_RDLID,		0xffffffff, 3, "2rdlid"},
+	{HNBU_RSSISMBXA2G, 0xffffffff, 3, "0rssismf2g 0rssismc2g "
+	"0rssisav2g 0bxa2g"}, /* special case */
+	{HNBU_RSSISMBXA5G, 0xffffffff, 3, "0rssismf5g 0rssismc5g "
+	"0rssisav5g 0bxa5g"}, /* special case */
+	{HNBU_XTALFREQ,		0xffffffff, 5, "4xtalfreq"},
+	{HNBU_TRI2G,		0xffffffff, 2, "1tri2g"},
+	{HNBU_TRI5G,		0xffffffff, 4, "1tri5gl 1tri5g 1tri5gh"},
+	{HNBU_RXPO2G,		0xffffffff, 2, "1rxpo2g"},
+	{HNBU_RXPO5G,		0xffffffff, 2, "1rxpo5g"},
+	{HNBU_BOARDNUM,		0xffffffff, 3, "2boardnum"},
+	{HNBU_MACADDR,		0xffffffff, 7, "6macaddr"},	/* special case */
+	{HNBU_RDLSN,		0xffffffff, 3, "2rdlsn"},
+	{HNBU_BOARDTYPE,	0xffffffff, 3, "2boardtype"},
+	{HNBU_LEDDC,		0xffffffff, 3, "2leddc"},
+	{HNBU_RDLRNDIS,		0xffffffff, 2, "1rdlndis"},
+	{HNBU_CHAINSWITCH,	0xffffffff, 5, "1txchain 1rxchain 2antswitch"},
+	{HNBU_REGREV,		0xffffffff, 3, "2regrev"},
+	{HNBU_FEM,		0x000007fe, 5, "0antswctl2g 0triso2g 0pdetrange2g 0extpagain2g "
+	"0tssipos2g 0antswctl5g 0triso5g 0pdetrange5g 0extpagain5g 0tssipos5g"}, /* special case */
+	{HNBU_PAPARMS_C0,	0x000007fe, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 "
+	"2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 2pa5gw1a0 2pa5gw2a0 "
+	"2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 2pa5ghw1a0 2pa5ghw2a0"},
+	{HNBU_PAPARMS_C1,	0x000007fe, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 "
+	"2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 2pa5gw1a1 2pa5gw2a1 "
+	"2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 2pa5ghw1a1 2pa5ghw2a1"},
+	{HNBU_PO_CCKOFDM,	0xffffffff, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo "
+	"4ofdm5ghpo"},
+	{HNBU_PO_MCS2G,		0xffffffff, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 "
+	"2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"},
+	{HNBU_PO_MCS5GM,	0xffffffff, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 "
+	"2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"},
+	{HNBU_PO_MCS5GLH,	0xffffffff, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 "
+	"2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 "
+	"2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 "
+	"2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"},
+	{HNBU_CCKFILTTYPE,	0xffffffff, 2, "1cckdigfilttype"},
+	{HNBU_PO_CDD,		0xffffffff, 3, "2cddpo"},
+	{HNBU_PO_STBC,		0xffffffff, 3, "2stbcpo"},
+	{HNBU_PO_40M,		0xffffffff, 3, "2bw40po"},
+	{HNBU_PO_40MDUP,	0xffffffff, 3, "2bwduppo"},
+	{HNBU_RDLRWU,		0xffffffff, 2, "1rdlrwu"},
+	{HNBU_WPS,		0xffffffff, 3, "1wpsgpio 1wpsled"},
+	{HNBU_USBFS,		0xffffffff, 2, "1usbfs"},
+	{HNBU_ELNA2G,           0xffffffff, 2, "1elna2g"},
+	{HNBU_ELNA5G,           0xffffffff, 2, "1elna5g"},
+	{HNBU_CUSTOM1,		0xffffffff, 5, "4customvar1"},
+	{OTP_RAW,		0xffffffff, 0, ""},	/* special case */
+	{HNBU_OFDMPO5G,		0xffffffff, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"},
+	{HNBU_USBEPNUM,		0xffffffff, 3, "2usbepnum"},
+	{HNBU_CCKBW202GPO,	0xffffffff, 7, "2cckbw202gpo 2cckbw20ul2gpo 2cckbw20in802gpo"},
+	{HNBU_LEGOFDMBW202GPO,	0xffffffff, 9, "4legofdmbw202gpo 4legofdmbw20ul2gpo"},
+	{HNBU_LEGOFDMBW205GPO,	0xffffffff, 25, "4legofdmbw205glpo 4legofdmbw20ul5glpo "
+	"4legofdmbw205gmpo 4legofdmbw20ul5gmpo 4legofdmbw205ghpo 4legofdmbw20ul5ghpo"},
+	{HNBU_MCS2GPO,	0xffffffff, 17,	"4mcsbw202gpo 4mcsbw20ul2gpo 4mcsbw402gpo 4mcsbw802gpo"},
+	{HNBU_MCS5GLPO,	0xffffffff, 13,	"4mcsbw205glpo 4mcsbw20ul5glpo 4mcsbw405glpo"},
+	{HNBU_MCS5GMPO,	0xffffffff, 13,	"4mcsbw205gmpo 4mcsbw20ul5gmpo 4mcsbw405gmpo"},
+	{HNBU_MCS5GHPO,	0xffffffff, 13,	"4mcsbw205ghpo 4mcsbw20ul5ghpo 4mcsbw405ghpo"},
+	{HNBU_MCS32PO,	0xffffffff, 3,	"2mcs32po"},
+	{HNBU_LEG40DUPPO,	0xffffffff, 3,	"2legofdm40duppo"},
+	{HNBU_TEMPTHRESH,	0xffffffff, 7,	"1tempthresh 0temps_period 0temps_hysteresis "
+	"1tempoffset 1tempsense_slope 0tempcorrx 0tempsense_option "
+	"1phycal_tempdelta"}, /* special case */
+	{HNBU_MUXENAB,		0xffffffff, 2,	"1muxenab"},
+	{HNBU_FEM_CFG,		0xfffff800, 5,	"0femctrl 0papdcap2g 0tworangetssi2g 0pdgain2g "
+	"0epagain2g 0tssiposslope2g 0gainctrlsph 0papdcap5g 0tworangetssi5g 0pdgain5g 0epagain5g "
+	"0tssiposslope5g"}, /* special case */
+	{HNBU_ACPA_C0,		0x00001800, 39,	"2subband5gver 2maxp2ga0 2*3pa2ga0 "
+	"1*4maxp5ga0 2*12pa5ga0"},
+	{HNBU_ACPA_C1,		0x00001800, 37,	"2maxp2ga1 2*3pa2ga1 1*4maxp5ga1 2*12pa5ga1"},
+	{HNBU_ACPA_C2,		0x00001800, 37,	"2maxp2ga2 2*3pa2ga2 1*4maxp5ga2 2*12pa5ga2"},
+	{HNBU_MEAS_PWR,		0xfffff800, 5,	"1measpower 1measpower1 1measpower2 2rawtempsense"},
+	{HNBU_PDOFF,		0xfffff800, 13,	"2pdoffset40ma0 2pdoffset40ma1 2pdoffset40ma2 "
+	"2pdoffset80ma0 2pdoffset80ma1 2pdoffset80ma2"},
+	{HNBU_ACPPR_2GPO,	0xfffff800, 13,	"2dot11agofdmhrbw202gpo 2ofdmlrbw202gpo "
+	"2sb20in40dot11agofdm2gpo 2sb20in80dot11agofdm2gpo 2sb20in40ofdmlrbw202gpo "
+	"2sb20in80ofdmlrbw202gpo"},
+	{HNBU_ACPPR_5GPO,	0xfffff800, 59,	"4mcsbw805glpo 4mcsbw1605glpo 4mcsbw805gmpo "
+	"4mcsbw1605gmpo 4mcsbw805ghpo 4mcsbw1605ghpo 2mcslr5glpo 2mcslr5gmpo 2mcslr5ghpo "
+	"4mcsbw80p805glpo 4mcsbw80p805gmpo 4mcsbw80p805ghpo 4mcsbw80p805gx1po 2mcslr5gx1po "
+	"2mcslr5g80p80po 4mcsbw805gx1po 4mcsbw1605gx1po"},
+	{HNBU_MCS5Gx1PO,	0xfffff800, 9,	"4mcsbw205gx1po 4mcsbw405gx1po"},
+	{HNBU_ACPPR_SBPO,	0xfffff800, 49,	"2sb20in40hrpo 2sb20in80and160hr5glpo "
+	"2sb40and80hr5glpo 2sb20in80and160hr5gmpo 2sb40and80hr5gmpo 2sb20in80and160hr5ghpo "
+	"2sb40and80hr5ghpo 2sb20in40lrpo 2sb20in80and160lr5glpo 2sb40and80lr5glpo "
+	"2sb20in80and160lr5gmpo 2sb40and80lr5gmpo 2sb20in80and160lr5ghpo 2sb40and80lr5ghpo "
+	"4dot11agduphrpo 4dot11agduplrpo 2sb20in40and80hrpo 2sb20in40and80lrpo "
+	"2sb20in80and160hr5gx1po 2sb20in80and160lr5gx1po 2sb40and80hr5gx1po 2sb40and80lr5gx1po "
+	},
+	{HNBU_ACPPR_SB8080_PO, 0xfffff800, 23, "2sb2040and80in80p80hr5glpo "
+	"2sb2040and80in80p80lr5glpo 2sb2040and80in80p80hr5gmpo "
+	"2sb2040and80in80p80lr5gmpo 2sb2040and80in80p80hr5ghpo 2sb2040and80in80p80lr5ghpo "
+	"2sb2040and80in80p80hr5gx1po 2sb2040and80in80p80lr5gx1po 2sb20in80p80hr5gpo "
+	"2sb20in80p80lr5gpo 2dot11agduppo"},
+	{HNBU_NOISELVL,		0xfffff800, 16, "1noiselvl2ga0 1noiselvl2ga1 1noiselvl2ga2 "
+	"1*4noiselvl5ga0 1*4noiselvl5ga1 1*4noiselvl5ga2"},
+	{HNBU_RXGAIN_ERR,	0xfffff800, 16, "1rxgainerr2ga0 1rxgainerr2ga1 1rxgainerr2ga2 "
+	"1*4rxgainerr5ga0 1*4rxgainerr5ga1 1*4rxgainerr5ga2"},
+	{HNBU_AGBGA,		0xfffff800, 7, "1agbg0 1agbg1 1agbg2 1aga0 1aga1 1aga2"},
+	{HNBU_USBDESC_COMPOSITE, 0xffffffff, 3, "2usbdesc_composite"},
+	{HNBU_UUID, 		0xffffffff, 17,	"16uuid"},
+	{HNBU_WOWLGPIO,		0xffffffff, 2,  "1wowl_gpio"},
+	{HNBU_ACRXGAINS_C0,	0xfffff800, 5, "0rxgains5gtrelnabypa0 0rxgains5gtrisoa0 "
+	"0rxgains5gelnagaina0 0rxgains2gtrelnabypa0 0rxgains2gtrisoa0 0rxgains2gelnagaina0 "
+	"0rxgains5ghtrelnabypa0 0rxgains5ghtrisoa0 0rxgains5ghelnagaina0 0rxgains5gmtrelnabypa0 "
+	"0rxgains5gmtrisoa0 0rxgains5gmelnagaina0"},	/* special case */
+	{HNBU_ACRXGAINS_C1,	0xfffff800, 5, "0rxgains5gtrelnabypa1 0rxgains5gtrisoa1 "
+	"0rxgains5gelnagaina1 0rxgains2gtrelnabypa1 0rxgains2gtrisoa1 0rxgains2gelnagaina1 "
+	"0rxgains5ghtrelnabypa1 0rxgains5ghtrisoa1 0rxgains5ghelnagaina1 0rxgains5gmtrelnabypa1 "
+	"0rxgains5gmtrisoa1 0rxgains5gmelnagaina1"},	/* special case */
+	{HNBU_ACRXGAINS_C2,	0xfffff800, 5, "0rxgains5gtrelnabypa2 0rxgains5gtrisoa2 "
+	"0rxgains5gelnagaina2 0rxgains2gtrelnabypa2 0rxgains2gtrisoa2 0rxgains2gelnagaina2 "
+	"0rxgains5ghtrelnabypa2 0rxgains5ghtrisoa2 0rxgains5ghelnagaina2 0rxgains5gmtrelnabypa2 "
+	"0rxgains5gmtrisoa2 0rxgains5gmelnagaina2"},	/* special case */
+	{HNBU_TXDUTY, 		0xfffff800, 9,	"2tx_duty_cycle_ofdm_40_5g "
+	"2tx_duty_cycle_thresh_40_5g 2tx_duty_cycle_ofdm_80_5g 2tx_duty_cycle_thresh_80_5g"},
+	{HNBU_PDOFF_2G,		0xfffff800, 3,	"0pdoffset2g40ma0 0pdoffset2g40ma1 "
+	"0pdoffset2g40ma2 0pdoffset2g40mvalid"},
+	{HNBU_ACPA_CCK_C0,	0xfffff800, 7,  "2*3pa2gccka0"},
+	{HNBU_ACPA_CCK_C1,	0xfffff800, 7,  "2*3pa2gccka1"},
+	{HNBU_ACPA_40,		0xfffff800, 25,	"2*12pa5gbw40a0"},
+	{HNBU_ACPA_80,		0xfffff800, 25,	"2*12pa5gbw80a0"},
+	{HNBU_ACPA_4080,	0xfffff800, 49,	"2*12pa5gbw4080a0 2*12pa5gbw4080a1"},
+	{HNBU_ACPA_4X4C0,	0xffffe000, 23, "1maxp2ga0 2*4pa2ga0 2*4pa2g40a0 "
+	"1maxp5gb0a0 1maxp5gb1a0 1maxp5gb2a0 1maxp5gb3a0 1maxp5gb4a0"},
+	{HNBU_ACPA_4X4C1,	0xffffe000, 23, "1maxp2ga1 2*4pa2ga1 2*4pa2g40a1 "
+	"1maxp5gb0a1 1maxp5gb1a1 1maxp5gb2a1 1maxp5gb3a1 1maxp5gb4a1"},
+	{HNBU_ACPA_4X4C2,	0xffffe000, 23, "1maxp2ga2 2*4pa2ga2 2*4pa2g40a2 "
+	"1maxp5gb0a2 1maxp5gb1a2 1maxp5gb2a2 1maxp5gb3a2 1maxp5gb4a2"},
+	{HNBU_ACPA_4X4C3,	0xffffe000, 23, "1maxp2ga3 2*4pa2ga3 2*4pa2g40a3 "
+	"1maxp5gb0a3 1maxp5gb1a3 1maxp5gb2a3 1maxp5gb3a3 1maxp5gb4a3"},
+	{HNBU_ACPA_BW20_4X4C0,	0xffffe000, 41, "2*20pa5ga0"},
+	{HNBU_ACPA_BW40_4X4C0,	0xffffe000, 41, "2*20pa5g40a0"},
+	{HNBU_ACPA_BW80_4X4C0,	0xffffe000, 41, "2*20pa5g80a0"},
+	{HNBU_ACPA_BW20_4X4C1,	0xffffe000, 41, "2*20pa5ga1"},
+	{HNBU_ACPA_BW40_4X4C1,	0xffffe000, 41, "2*20pa5g40a1"},
+	{HNBU_ACPA_BW80_4X4C1,	0xffffe000, 41, "2*20pa5g80a1"},
+	{HNBU_ACPA_BW20_4X4C2,	0xffffe000, 41, "2*20pa5ga2"},
+	{HNBU_ACPA_BW40_4X4C2,	0xffffe000, 41, "2*20pa5g40a2"},
+	{HNBU_ACPA_BW80_4X4C2,	0xffffe000, 41, "2*20pa5g80a2"},
+	{HNBU_ACPA_BW20_4X4C3,	0xffffe000, 41, "2*20pa5ga3"},
+	{HNBU_ACPA_BW40_4X4C3,	0xffffe000, 41, "2*20pa5g40a3"},
+	{HNBU_ACPA_BW80_4X4C3,	0xffffe000, 41, "2*20pa5g80a3"},
+	{HNBU_SUBBAND5GVER,	0xfffff800, 3,	"2subband5gver"},
+	{HNBU_PAPARAMBWVER,	0xfffff800, 2,	"1paparambwver"},
+	{HNBU_TXBFRPCALS,  0xfffff800, 11,
+	"2rpcal2g 2rpcal5gb0 2rpcal5gb1 2rpcal5gb2 2rpcal5gb3"}, /* txbf rpcalvars */
+	{HNBU_GPIO_PULL_DOWN,	0xffffffff, 5, "4gpdn"},
+	{HNBU_MACADDR2,		0xffffffff, 7, "6macaddr2"},	/* special case */
+	{0xFF,			0xffffffff, 0, ""}
+};
+
+#endif /* _bcmsrom_tbl_h_ */
diff --git a/wl/src/include/bcmtlv.h b/wl/src/include/bcmtlv.h
new file mode 100644
index 0000000..ed586f0
--- /dev/null
+++ b/wl/src/include/bcmtlv.h
@@ -0,0 +1,286 @@
+/*
+ * TLV and XTLV support
+ *
+ * Copyright (C) 2017, Broadcom. 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: $
+ */
+
+#ifndef	_bcmtlv_h_
+#define	_bcmtlv_h_
+
+#include <typedefs.h>
+#if defined(__FreeBSD__)
+#include <stdbool.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* begin tlvs - used in 802.11 IEs etc. */
+
+/* type(aka id)/length/value buffer triple */
+typedef struct bcm_tlv {
+	uint8	id;
+	uint8	len;
+	uint8	data[1];
+} bcm_tlv_t;
+
+/* size of tlv including data */
+#define BCM_TLV_SIZE(_tlv) ((_tlv) ? (OFFSETOF(bcm_tlv_t, data) + (_tlv)->len) : 0)
+
+/* get next tlv - no length checks */
+#define BCM_TLV_NEXT(_tlv) (bcm_tlv_t *)((uint8 *)(_tlv)+ BCM_TLV_SIZE(_tlv))
+
+/* tlv length is restricted to 1 byte */
+#define BCM_TLV_MAX_DATA_SIZE (255)
+
+/* tlv header - two bytes */
+#define BCM_TLV_HDR_SIZE (OFFSETOF(bcm_tlv_t, data))
+
+/* Check that bcm_tlv_t fits into the given buffer len */
+#define bcm_valid_tlv(elt, buflen) (\
+	 ((int)(buflen) >= (int)BCM_TLV_HDR_SIZE) && \
+	 ((int)(buflen) >= (int)(BCM_TLV_HDR_SIZE + (elt)->len)))
+
+/* find the next tlv */
+bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen);
+
+/* find the tlv for a given id */
+bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key);
+
+/*
+ * Traverse tlvs and return pointer to the first tlv that
+ * matches the key. Return NULL if not found or tlv len < min_bodylen
+ */
+bcm_tlv_t *bcm_parse_tlvs_min_bodylen(void *buf, int buflen, uint key, int min_bodylen);
+
+/* parse tlvs for dot11 - same as parse_tlvs but supports 802.11 id extension */
+bcm_tlv_t *bcm_parse_tlvs_dot11(void *buf, int buflen, uint key, bool id_ext);
+
+/* same as parse_tlvs, but stops when found id > key */
+bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key);
+
+/* find a tlv with DOT11_MNG_PROPR_ID as id, and the given oui and type */
+bcm_tlv_t *bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type,
+	int type_len);
+
+/* write tlv at dst and return next tlv ptr */
+uint8 *bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst);
+
+/* write tlv at dst if space permits and return next tlv ptr */
+uint8 *bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst,
+	int dst_maxlen);
+
+/* copy a tlv  and return next tlv ptr */
+uint8 *bcm_copy_tlv(const void *src, uint8 *dst);
+
+/* copy a tlv if space permits and return next tlv ptr */
+uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen);
+
+/* end tlvs */
+
+/* begin xtlv - used for iovars, nan attributes etc. */
+
+/* bcm type(id), length, value with w/16 bit id/len. The structure below
+ * is nominal, and is used to support variable length id and type. See
+ * xtlv options below.
+ */
+typedef struct bcm_xtlv {
+	uint16	id;
+	uint16	len;
+	uint8	data[1];
+} bcm_xtlv_t;
+
+/* xtlv options */
+#define BCM_XTLV_OPTION_NONE	0x0000
+#define BCM_XTLV_OPTION_ALIGN32	0x0001 /* 32bit alignment of type.len.data */
+#define BCM_XTLV_OPTION_IDU8	0x0002 /* shorter id */
+#define BCM_XTLV_OPTION_LENU8	0x0004 /* shorted length */
+typedef uint16 bcm_xtlv_opts_t;
+
+/* header size. depends on options. Macros names ending w/ _EX are where
+ * options are explcitly specified that may be less common. The ones
+ * without use default values that correspond to ...OPTION_NONE
+ */
+
+/* xtlv header size depends on options */
+#define BCM_XTLV_HDR_SIZE 4
+#define BCM_XTLV_HDR_SIZE_EX(_opts) bcm_xtlv_hdr_size(_opts)
+
+/* note: xtlv len only stores the value's length without padding */
+#define BCM_XTLV_LEN(_elt) ltoh16_ua(&(_elt)->len)
+#define BCM_XTLV_LEN_EX(_elt, _opts) bcm_xtlv_len(_elt, _opts)
+
+#define BCM_XTLV_ID(_elt) ltoh16_ua(&(_elt)->id)
+#define BCM_XTLV_ID_EX(_elt, _opts) bcm_xtlv_id(_elt, _opts)
+
+/* entire size of the XTLV including header, data, and optional padding */
+#define BCM_XTLV_SIZE(elt, opts) bcm_xtlv_size(elt, opts)
+#define BCM_XTLV_SIZE_EX(_elt, _opts) bcm_xtlv_size(_elt, _opts)
+
+/* max xtlv data size */
+#define BCM_XTLV_MAX_DATA_SIZE 65535
+#define BCM_XTLV_MAX_DATA_SIZE_EX(_opts) ((_opts & BCM_XTLV_OPTION_LENU8) ? \
+	255 : 65535)
+
+/* descriptor of xtlv data, packing(src) and unpacking(dst) support  */
+typedef struct {
+	uint16	type;
+	uint16	len;
+	void	*ptr; /* ptr to memory location */
+} xtlv_desc_t;
+
+/* xtlv buffer - packing/unpacking support */
+struct bcm_xtlvbuf {
+	bcm_xtlv_opts_t opts;
+	uint16 size;
+	uint8 *head; /* point to head of buffer */
+	uint8 *buf; /* current position of buffer */
+	/* allocated buffer may follow, but not necessarily */
+};
+typedef struct bcm_xtlvbuf bcm_xtlvbuf_t;
+
+/* valid xtlv ? */
+bool bcm_valid_xtlv(const bcm_xtlv_t *elt, int buf_len, bcm_xtlv_opts_t opts);
+
+/* return the next xtlv element, and update buffer len (remaining). Buffer length
+ * updated includes padding as specified by options
+ */
+bcm_xtlv_t *bcm_next_xtlv(bcm_xtlv_t *elt, int *buf_len, bcm_xtlv_opts_t opts);
+
+/* initialize an xtlv buffer. Use options specified for packing/unpacking using
+ * the buffer. Caller is responsible for allocating both buffers.
+ */
+int bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len,
+	bcm_xtlv_opts_t opts);
+
+/* length of data in the xtlv buffer */
+uint16 bcm_xtlv_buf_len(struct bcm_xtlvbuf *tbuf);
+
+/* remaining space in the xtlv buffer */
+uint16 bcm_xtlv_buf_rlen(struct bcm_xtlvbuf *tbuf);
+
+/* write ptr */
+uint8 *bcm_xtlv_buf(struct bcm_xtlvbuf *tbuf);
+
+/* head */
+uint8 *bcm_xtlv_head(struct bcm_xtlvbuf *tbuf);
+
+/* put a data buffer into xtlv */
+int bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n);
+
+/* put one or more u16 elts into xtlv */
+int bcm_xtlv_put16(bcm_xtlvbuf_t *tbuf, uint16 type, const uint16 *data, int n);
+
+/* put one or more u32 elts into xtlv */
+int bcm_xtlv_put32(bcm_xtlvbuf_t *tbuf, uint16 type, const uint32 *data, int n);
+
+/* put one or more u64 elts into xtlv */
+int bcm_xtlv_put64(bcm_xtlvbuf_t *tbuf, uint16 type, const uint64 *data, int n);
+
+/* note: there are no get equivalent of integer unpacking, becasuse bcmendian.h
+ * can be used directly using pointers returned in the buffer being processed.
+ */
+
+/* unpack a single xtlv entry, advances buffer and copies data to dst_data on match
+ * type and length match must be exact
+ */
+int bcm_unpack_xtlv_entry(uint8 **buf, uint16 expected_type, uint16 expected_len,
+	uint8 *dst_data, bcm_xtlv_opts_t opts);
+
+/* packs an xtlv into buffer, and advances buffer, decreements buffer length.
+ * buffer length is checked and must be >= size of xtlv - otherwise BCME_BADLEN
+ */
+int bcm_pack_xtlv_entry(uint8 **buf, uint16 *buflen, uint16 type, uint16 len,
+	const uint8 *src_data, bcm_xtlv_opts_t opts);
+
+/* accessors and lengths for element given options */
+int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
+int bcm_xtlv_hdr_size(bcm_xtlv_opts_t opts);
+int bcm_xtlv_len(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
+int bcm_xtlv_id(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
+int bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts);
+
+/* compute size needed for number of tlvs whose total data len is given */
+#define BCM_XTLV_SIZE_FOR_TLVS(_data_len, _num_tlvs, _opts) (\
+	bcm_xtlv_size_for_data(_data_len, _opts) + (\
+	(_num_tlvs) * BCM_XTLV_HDR_SIZE_EX(_opts)))
+
+/* unsafe copy xtlv */
+#define BCM_XTLV_BCOPY(_src, _dst, _opts) \
+	bcm_xtlv_bcopy(_src, _dst, BCM_XTLV_MAX_DATA_SIZE_EX(_opts), \
+		BCM_XTLV_MAX_DATA_SIZE_EX(_opts), _opts)
+
+/* copy xtlv - note: src->dst bcopy order - to be compatible w/ tlv version */
+bcm_xtlv_t* bcm_xtlv_bcopy(const bcm_xtlv_t *src, bcm_xtlv_t *dst,
+	int src_buf_len, int dst_buf_len, bcm_xtlv_opts_t opts);
+
+/* callback for unpacking xtlv from a buffer into context. */
+typedef int (bcm_xtlv_unpack_cbfn_t)(void *ctx, const uint8 *buf,
+	uint16 type, uint16 len);
+
+/* unpack a tlv buffer using buffer, options, and callback */
+int bcm_unpack_xtlv_buf(void *ctx, const uint8 *buf, uint16 buflen,
+	bcm_xtlv_opts_t opts, bcm_xtlv_unpack_cbfn_t *cbfn);
+
+/* unpack a set of tlvs from the buffer using provided xtlv descriptors */
+int bcm_unpack_xtlv_buf_to_mem(uint8 *buf, int *buflen, xtlv_desc_t *items,
+	bcm_xtlv_opts_t opts);
+
+/* pack a set of tlvs into buffer using provided xtlv descriptors */
+int bcm_pack_xtlv_buf_from_mem(uint8 **buf, uint16 *buflen,
+	const xtlv_desc_t *items, bcm_xtlv_opts_t opts);
+
+/* return data pointer and data length of a given id from xtlv buffer
+ * data_len may be NULL
+ */
+const uint8* bcm_get_data_from_xtlv_buf(const uint8 *tlv_buf, uint16 buflen,
+	uint16 id, uint16 *datalen, bcm_xtlv_opts_t opts);
+
+/* callback to return next tlv id and len to pack, if there is more tlvs to come and
+ * options e.g. alignment
+ */
+typedef bool (*bcm_pack_xtlv_next_info_cbfn_t)(void *ctx, uint16 *tlv_id, uint16 *tlv_len);
+
+/* callback to pack the tlv into length validated buffer */
+typedef void (*bcm_pack_xtlv_pack_next_cbfn_t)(void *ctx,
+	uint16 tlv_id, uint16 tlv_len, uint8* buf);
+
+/* pack a set of tlvs into buffer using get_next to interate */
+int bcm_pack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen,
+	bcm_xtlv_opts_t opts, bcm_pack_xtlv_next_info_cbfn_t get_next,
+	bcm_pack_xtlv_pack_next_cbfn_t pack_next, int *outlen);
+
+/* pack an xtlv. does not do any error checking. if data is not NULL
+ * data of given length is copied  to buffer (xtlv)
+ */
+void bcm_xtlv_pack_xtlv(bcm_xtlv_t *xtlv, uint16 type, uint16 len,
+	const uint8 *data, bcm_xtlv_opts_t opts);
+
+/* unpack an xtlv and return ptr to data, and data length */
+void bcm_xtlv_unpack_xtlv(const bcm_xtlv_t *xtlv, uint16 *type, uint16 *len,
+	const uint8 **data, bcm_xtlv_opts_t opts);
+
+/* end xtlvs */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif	/* _bcmtlv_h_ */
diff --git a/wl/src/include/bcmutils.h b/wl/src/include/bcmutils.h
new file mode 100644
index 0000000..a7bb049
--- /dev/null
+++ b/wl/src/include/bcmutils.h
@@ -0,0 +1,1330 @@
+/*
+ * Misc useful os-independent macros and functions.
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmutils.h 661946 2016-09-27 21:47:25Z $
+ */
+
+#ifndef	_bcmutils_h_
+#define	_bcmutils_h_
+
+#include <bcmtlv.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__FreeBSD__)
+#include <stdbool.h>
+#endif
+
+#define bcm_strncpy_s(dst, noOfElements, src, count)    strncpy((dst), (src), (count))
+#ifdef FREEBSD
+#define bcm_strncat_s(dst, noOfElements, src, count)    strcat((dst), (src))
+#else
+#define bcm_strncat_s(dst, noOfElements, src, count)    strncat((dst), (src), (count))
+#endif /* FREEBSD */
+#define bcm_snprintf_s snprintf
+#define bcm_sprintf_s snprintf
+
+/*
+ * #define bcm_strcpy_s(dst, count, src)            strncpy((dst), (src), (count))
+ * Use bcm_strcpy_s instead as it is a safer option
+ * bcm_strcat_s: Use bcm_strncat_s as a safer option
+ *
+ */
+
+#define BCM_BIT(x)		(1 << (x))
+
+/* ctype replacement */
+#define _BCM_U	0x01	/* upper */
+#define _BCM_L	0x02	/* lower */
+#define _BCM_D	0x04	/* digit */
+#define _BCM_C	0x08	/* cntrl */
+#define _BCM_P	0x10	/* punct */
+#define _BCM_S	0x20	/* white space (space/lf/tab) */
+#define _BCM_X	0x40	/* hex digit */
+#define _BCM_SP	0x80	/* hard space (0x20) */
+
+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))
+
+#define CIRCULAR_ARRAY_FULL(rd_idx, wr_idx, max) ((wr_idx + 1)%max == rd_idx)
+
+#define KB(bytes)	(((bytes) + 1023) / 1024)
+
+/* Buffer structure for collecting string-formatted data
+* using bcm_bprintf() API.
+* Use bcm_binit() to initialize before use
+*/
+
+struct bcmstrbuf {
+	char *buf;	/* pointer to current position in origbuf */
+	unsigned int size;	/* current (residual) size in bytes */
+	char *origbuf;	/* unmodified pointer to orignal buffer */
+	unsigned int origsize;	/* unmodified orignal buffer size in bytes */
+};
+
+#define BCMSTRBUF_LEN(b)	(b->size)
+#define BCMSTRBUF_BUF(b)	(b->buf)
+
+/* ** driver-only section ** */
+#ifdef BCMDRIVER
+#include <osl.h>
+#include <hnd_pktq.h>
+#include <hnd_pktpool.h>
+
+#define GPIO_PIN_NOTDEFINED 	0x20	/* Pin not defined */
+
+/*
+ * Spin at most 'us' microseconds while 'exp' is true.
+ * Caller should explicitly test 'exp' when this completes
+ * and take appropriate error action if 'exp' is still true.
+ */
+#ifndef SPINWAIT_POLL_PERIOD
+#define SPINWAIT_POLL_PERIOD	10
+#endif
+
+#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; \
+	} \
+}
+
+/* forward definition of ether_addr structure used by some function prototypes */
+
+struct ether_addr;
+
+extern int ether_isbcast(const void *ea);
+extern int ether_isnulladdr(const void *ea);
+
+#define UP_TABLE_MAX	((IPV4_TOS_DSCP_MASK >> IPV4_TOS_DSCP_SHIFT) + 1)	/* 64 max */
+#define CORE_SLAVE_PORT_0	0
+#define CORE_SLAVE_PORT_1	1
+#define CORE_BASE_ADDR_0	0
+#define CORE_BASE_ADDR_1	1
+
+#ifdef DONGLEBUILD
+/* TRIM Tail bytes from lfrag */
+extern void pktfrag_trim_tailbytes(osl_t * osh, void* p, uint16 len, uint8 type);
+#define PKTFRAG_TRIM_TAILBYTES(osh, p, len, type) \
+	pktfrag_trim_tailbytes(osh, p, len, type)
+#endif /* DONGLEBUILD */
+
+/* externs */
+/* packet */
+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);
+
+/* Get priority from a packet and pass it back in scb (or equiv) */
+#define	PKTPRIO_VDSCP	0x100		/* DSCP prio found after VLAN tag */
+#define	PKTPRIO_VLAN	0x200		/* VLAN prio found */
+#define	PKTPRIO_UPD	0x400		/* DSCP used to update VLAN prio */
+#define	PKTPRIO_DSCP	0x800		/* DSCP prio found */
+
+/* DSCP type definitions (RFC4594) */
+/* AF1x: High-Throughput Data (RFC2597) */
+#define DSCP_AF11	0x0A
+#define DSCP_AF12	0x0C
+#define DSCP_AF13	0x0E
+/* AF2x: Low-Latency Data (RFC2597) */
+#define DSCP_AF21	0x12
+#define DSCP_AF22	0x14
+#define DSCP_AF23	0x16
+/* AF3x: Multimedia Streaming (RFC2597) */
+#define DSCP_AF31	0x1A
+#define DSCP_AF32	0x1C
+#define DSCP_AF33	0x1E
+/* EF: Telephony (RFC3246) */
+#define DSCP_EF		0x2E
+
+extern uint pktsetprio(void *pkt, bool update_vtag);
+extern uint pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag);
+extern bool pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp);
+
+/* ethernet address */
+extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf);
+extern int bcm_ether_atoe(const char *p, struct ether_addr *ea);
+
+/* ip address */
+struct ipv4_addr;
+extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf);
+extern char *bcm_ipv6_ntoa(void *ipv6, char *buf);
+extern int bcm_atoipv4(const char *p, struct ipv4_addr *ip);
+
+/* delay */
+extern void bcm_mdelay(uint ms);
+/* variable access */
+#if defined(BCM_RECLAIM)
+extern bool _nvram_reclaim_enb;
+#define NVRAM_RECLAIM_ENAB() (_nvram_reclaim_enb)
+#ifdef BCMDBG
+#define NVRAM_RECLAIM_CHECK(name)							\
+	if (NVRAM_RECLAIM_ENAB() && (bcm_attach_part_reclaimed == TRUE)) {			\
+		printf("%s: NVRAM already reclaimed, %s\n", __FUNCTION__, (name));	\
+		*(char*) 0 = 0; /* TRAP */						\
+		return NULL;								\
+	}
+#else /* BCMDBG */
+#define NVRAM_RECLAIM_CHECK(name)							\
+	if (NVRAM_RECLAIM_ENAB() && (bcm_attach_part_reclaimed == TRUE)) {			\
+		*(char*) 0 = 0; /* TRAP */						\
+		return NULL;								\
+	}
+#endif /* BCMDBG */
+#else /* BCM_RECLAIM */
+#define NVRAM_RECLAIM_CHECK(name)
+#endif /* BCM_RECLAIM */
+
+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 /* BCMDBG */
+#ifdef BCMPERFSTATS
+extern void bcm_perf_enable(void);
+extern void bcmstats(char *fmt);
+extern void bcmlog(char *fmt, uint a1, uint a2);
+extern void bcmdumplog(char *buf, int size);
+extern int bcmdumplogent(char *buf, uint idx);
+#else
+#define bcm_perf_enable()
+#define bcmstats(fmt)
+#define	bcmlog(fmt, a1, a2)
+#define	bcmdumplog(buf, size)	*buf = '\0'
+#define	bcmdumplogent(buf, idx)	-1
+#endif /* BCMPERFSTATS */
+
+#define TSF_TICKS_PER_MS	1000
+#define TS_ENTER		0xdeadbeef	/* Timestamp profiling enter */
+#define TS_EXIT			0xbeefcafe	/* Timestamp profiling exit */
+
+#if defined(BCMTSTAMPEDLOGS)
+/* Store a TSF timestamp and a log line in the log buffer */
+extern void bcmtslog(uint32 tstamp, const char *fmt, uint a1, uint a2);
+/* Print out the log buffer with timestamps */
+extern void bcmprinttslogs(void);
+/* Print out a microsecond timestamp as "sec.ms.us " */
+extern void bcmprinttstamp(uint32 us);
+/* Dump to buffer a microsecond timestamp as "sec.ms.us " */
+extern void bcmdumptslog(struct bcmstrbuf *b);
+#else
+#define bcmtslog(tstamp, fmt, a1, a2)
+#define bcmprinttslogs()
+#define bcmprinttstamp(us)
+#define bcmdumptslog(b)
+#endif /* BCMTSTAMPEDLOGS */
+
+extern char *bcm_nvram_vars(uint *length);
+extern int bcm_nvram_cache(void *sih);
+
+/* Support for sharing code across in-driver iovar implementations.
+ * The intent is that a driver use this structure to map iovar names
+ * to its (private) iovar identifiers, and the lookup function to
+ * find the entry.  Macros are provided to map ids and get/set actions
+ * into a single number space for a switch statement.
+ */
+
+/* iovar structure */
+typedef struct bcm_iovar {
+	const char *name;	/* name for lookup and display */
+	uint16 varid;		/* id for switch */
+	uint16 flags;		/* driver-specific flag bits */
+	uint8 flags2;		 /* driver-specific flag bits */
+	uint8 type;		/* base type of argument */
+	uint16 minlen;		/* min length for buffer vars */
+} bcm_iovar_t;
+
+/* varid definitions are per-driver, may use these get/set bits */
+
+/* IOVar action bits for id mapping */
+#define IOV_GET 0 /* Get an iovar */
+#define IOV_SET 1 /* Set an iovar */
+
+/* Varid to actionid mapping */
+#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)
+
+/* flags are per-driver based on driver attributes */
+
+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);
+
+/* ioctl structure */
+typedef struct wlc_ioctl_cmd {
+	uint16 cmd;			/**< IOCTL command */
+	uint16 flags;			/**< IOCTL command flags */
+	int16 min_len;			/**< IOCTL command minimum argument len (in bytes) */
+} wlc_ioctl_cmd_t;
+
+#if defined(WLTINYDUMP) || defined(BCMDBG) || defined(WLMSG_INFORM) || \
+	defined(WLMSG_ASSOC) || defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
+extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len);
+#endif /* WLTINYDUMP || BCMDBG || WLMSG_INFORM || WLMSG_ASSOC || WLMSG_PRPKT */
+#endif	/* BCMDRIVER */
+
+/* string */
+extern int bcm_atoi(const char *s);
+extern ulong bcm_strtoul(const char *cp, char **endp, uint base);
+extern uint64 bcm_strtoull(const char *cp, char **endp, uint base);
+extern char *bcmstrstr(const char *haystack, const char *needle);
+extern char *bcmstrnstr(const char *s, uint s_len, const char *substr, uint substr_len);
+extern char *bcmstrcat(char *dest, const char *src);
+extern char *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);
+
+/* Base type definitions */
+#define IOVT_VOID	0	/* no value (implictly set only) */
+#define IOVT_BOOL	1	/* any value ok (zero/nonzero) */
+#define IOVT_INT8	2	/* integer values are range-checked */
+#define IOVT_UINT8	3	/* unsigned int 8 bits */
+#define IOVT_INT16	4	/* int 16 bits */
+#define IOVT_UINT16	5	/* unsigned int 16 bits */
+#define IOVT_INT32	6	/* int 32 bits */
+#define IOVT_UINT32	7	/* unsigned int 32 bits */
+#define IOVT_BUFFER	8	/* buffer is size-checked as per minlen */
+#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER)
+
+/* Initializer for IOV type strings */
+#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))
+
+/* ** driver/apps-shared section ** */
+
+#define BCME_STRLEN             64      /* Max string length for BCM errors */
+#define VALID_BCMERROR(e)       valid_bcmerror(e)
+
+
+/*
+ * error codes could be added but the defined ones shouldn't be changed/deleted
+ * these error codes are exposed to the user code
+ * when ever a new error code is added to this list
+ * please update errorstring table with the related error string and
+ * update osl files with os specific errorcode map
+*/
+
+#define BCME_OK				0	/* Success */
+#define BCME_ERROR			-1	/* Error generic */
+#define BCME_BADARG			-2	/* Bad Argument */
+#define BCME_BADOPTION			-3	/* Bad option */
+#define BCME_NOTUP			-4	/* Not up */
+#define BCME_NOTDOWN			-5	/* Not down */
+#define BCME_NOTAP			-6	/* Not AP */
+#define BCME_NOTSTA			-7	/* Not STA  */
+#define BCME_BADKEYIDX			-8	/* BAD Key Index */
+#define BCME_RADIOOFF 			-9	/* Radio Off */
+#define BCME_NOTBANDLOCKED		-10	/* Not  band locked */
+#define BCME_NOCLK			-11	/* No Clock */
+#define BCME_BADRATESET			-12	/* BAD Rate valueset */
+#define BCME_BADBAND			-13	/* BAD Band */
+#define BCME_BUFTOOSHORT		-14	/* Buffer too short */
+#define BCME_BUFTOOLONG			-15	/* Buffer too long */
+#define BCME_BUSY			-16	/* Busy */
+#define BCME_NOTASSOCIATED		-17	/* Not Associated */
+#define BCME_BADSSIDLEN			-18	/* Bad SSID len */
+#define BCME_OUTOFRANGECHAN		-19	/* Out of Range Channel */
+#define BCME_BADCHAN			-20	/* Bad Channel */
+#define BCME_BADADDR			-21	/* Bad Address */
+#define BCME_NORESOURCE			-22	/* Not Enough Resources */
+#define BCME_UNSUPPORTED		-23	/* Unsupported */
+#define BCME_BADLEN			-24	/* Bad length */
+#define BCME_NOTREADY			-25	/* Not Ready */
+#define BCME_EPERM			-26	/* Not Permitted */
+#define BCME_NOMEM			-27	/* No Memory */
+#define BCME_ASSOCIATED			-28	/* Associated */
+#define BCME_RANGE			-29	/* Not In Range */
+#define BCME_NOTFOUND			-30	/* Not Found */
+#define BCME_WME_NOT_ENABLED		-31	/* WME Not Enabled */
+#define BCME_TSPEC_NOTFOUND		-32	/* TSPEC Not Found */
+#define BCME_ACM_NOTSUPPORTED		-33	/* ACM Not Supported */
+#define BCME_NOT_WME_ASSOCIATION	-34	/* Not WME Association */
+#define BCME_SDIO_ERROR			-35	/* SDIO Bus Error */
+#define BCME_DONGLE_DOWN		-36	/* Dongle Not Accessible */
+#define BCME_VERSION			-37 	/* Incorrect version */
+#define BCME_TXFAIL			-38 	/* TX failure */
+#define BCME_RXFAIL			-39	/* RX failure */
+#define BCME_NODEVICE			-40 	/* Device not present */
+#define BCME_NMODE_DISABLED		-41 	/* NMODE disabled */
+#define BCME_HOFFLOAD_RESIDENT		-42	/* offload resident */
+#define BCME_SCANREJECT			-43 	/* reject scan request */
+#define BCME_USAGE_ERROR                -44     /* WLCMD usage error */
+#define BCME_IOCTL_ERROR                -45     /* WLCMD ioctl error */
+#define BCME_SERIAL_PORT_ERR            -46     /* RWL serial port error */
+#define BCME_DISABLED			-47     /* Disabled in this build */
+#define BCME_DECERR				-48		/* Decrypt error */
+#define BCME_ENCERR				-49		/* Encrypt error */
+#define BCME_MICERR				-50		/* Integrity/MIC error */
+#define BCME_REPLAY				-51		/* Replay */
+#define BCME_IE_NOTFOUND		-52		/* IE not found */
+#ifdef __FreeBSD__
+#define BCME_DATA_NOTFOUND		-46		/* Complete data not found in buffer */
+#else
+#define BCME_DATA_NOTFOUND		-53		/* Complete data not found in buffer */
+#endif /* FreeBSD last error */
+#define BCME_NOT_GC			-54     /* expecting a group client */
+#define BCME_PRS_REQ_FAILED		-55     /* GC presence req failed to sent */
+#define BCME_NO_P2P_SE			-56      /* Could not find P2P-Subelement */
+#define BCME_NOA_PND			-57      /* NoA pending, CB shuld be NULL */
+#define BCME_FRAG_Q_FAILED		-58      /* queueing 80211 frag failedi */
+#define BCME_GET_AF_FAILED		-59      /* Get p2p AF pkt failed */
+#define BCME_MSCH_NOTREADY		-60		/* scheduler not ready */
+#define BCME_IOV_LAST_CMD		-61		/* last batched iov sub-command */
+#define BCME_LAST   BCME_IOV_LAST_CMD
+
+#define BCME_NOTENABLED BCME_DISABLED
+
+/* This error code is *internal* to the driver, and is not propogated to users. It should
+ * only be used by IOCTL patch handlers as an indication that it did not handle the IOCTL.
+ * (Since the error code is internal, an entry in 'BCMERRSTRINGTABLE' is not required,
+ * nor does it need to be part of any OSL driver-to-OS error code mapping).
+ */
+#define BCME_IOCTL_PATCH_UNSUPPORTED	-9999
+#if (BCME_LAST <= BCME_IOCTL_PATCH_UNSUPPORTED)
+	#error "BCME_LAST <= BCME_IOCTL_PATCH_UNSUPPORTED"
+#endif
+
+/* These are collection of BCME Error strings */
+#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",		\
+	"Host Offload in device",	\
+	"Scan Rejected",		\
+	"WLCMD usage error",		\
+	"WLCMD ioctl error",		\
+	"RWL serial port error", 	\
+	"Disabled",			\
+	"Decrypt error", \
+	"Encrypt error", \
+	"MIC error", \
+	"Replay", \
+	"IE not found", \
+	"Data not found", \
+	"NOT GC", \
+	"PRS REQ FAILED", \
+	"NO P2P SubElement", \
+	"NOA Pending", \
+	"FRAG Q FAILED", \
+	"GET ActionFrame failed", \
+	"scheduler not ready", \
+	"Last IOV batched sub-cmd", \
+}
+
+#ifndef ABS
+#define	ABS(a)			(((a) < 0) ? -(a) : (a))
+#endif /* ABS */
+
+#ifndef MIN
+#define	MIN(a, b)		(((a) < (b)) ? (a) : (b))
+#endif /* MIN */
+
+#ifndef MAX
+#define	MAX(a, b)		(((a) > (b)) ? (a) : (b))
+#endif /* MAX */
+
+/* limit to [min, max] */
+#ifndef LIMIT_TO_RANGE
+#define LIMIT_TO_RANGE(x, min, max) \
+	((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
+#endif /* LIMIT_TO_RANGE */
+
+/* limit to  max */
+#ifndef LIMIT_TO_MAX
+#define LIMIT_TO_MAX(x, max) \
+	(((x) > (max) ? (max) : (x)))
+#endif /* LIMIT_TO_MAX */
+
+/* limit to min */
+#ifndef LIMIT_TO_MIN
+#define LIMIT_TO_MIN(x, min) \
+	(((x) < (min) ? (min) : (x)))
+#endif /* LIMIT_TO_MIN */
+
+#define DELTA(curr, prev) ((curr) > (prev) ? ((curr) - (prev)) : \
+	(0xffffffff - (prev) + (curr) + 1))
+#define CEIL(x, y)		(((x) + ((y) - 1)) / (y))
+#define ROUNDUP(x, y)		((((x) + ((y) - 1)) / (y)) * (y))
+#define ROUNDDN(p, align)	((p) & ~((align) - 1))
+#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
+/*
+ * The ARM RVCT compiler complains when using OFFSETOF where a constant
+ * expression is expected, such as an initializer for a static object.
+ * offsetof from the runtime library doesn't have that problem.
+ */
+#include <stddef.h>
+#define	OFFSETOF(type, member)	offsetof(type, member)
+#else
+#  if ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 8))
+/* GCC 4.8+ complains when using our OFFSETOF macro in array length declarations. */
+#    define	OFFSETOF(type, member)	__builtin_offsetof(type, member)
+#  else
+#    define	OFFSETOF(type, member)	((uint)(uintptr)&((type *)0)->member)
+#  endif /* GCC 4.8 or newer */
+#endif /* __ARMCC_VERSION */
+#endif /* OFFSETOF */
+
+/* substruct size up to and including a member of the struct */
+#ifndef STRUCT_SIZE_THROUGH
+#define STRUCT_SIZE_THROUGH(sptr, fname) \
+	(((uint8*)&((sptr)->fname) - (uint8*)(sptr)) + sizeof((sptr)->fname))
+#endif
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a)		(sizeof(a) / sizeof(a[0]))
+#endif
+
+#ifndef ARRAYLAST /* returns pointer to last array element */
+#define ARRAYLAST(a)		(&a[ARRAYSIZE(a)-1])
+#endif
+
+/* Reference a function; used to prevent a static function from being optimized out */
+extern void *_bcmutils_dummy_fn;
+#define REFERENCE_FUNCTION(f)	(_bcmutils_dummy_fn = (void *)(f))
+
+/* bit map related macros */
+#ifndef setbit
+#ifndef NBBY		/* the BSD family defines NBBY */
+#define	NBBY	8	/* 8 bits per byte */
+#endif /* #ifndef NBBY */
+#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
+extern void setbit(void *array, uint bit);
+extern void clrbit(void *array, uint bit);
+extern bool isset(const void *array, uint bit);
+extern bool isclr(const void *array, uint bit);
+#else
+#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
+#endif /* setbit */
+extern void set_bitrange(void *array, uint start, uint end, uint maxbit);
+extern int bcm_find_fsb(uint32 num);
+
+#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)
+
+extern void bcm_bitprint32(const uint32 u32);
+
+/*
+ * ----------------------------------------------------------------------------
+ * Multiword map of 2bits, nibbles
+ * setbit2 setbit4 (void *ptr, uint32 ix, uint32 val)
+ * getbit2 getbit4 (void *ptr, uint32 ix)
+ * ----------------------------------------------------------------------------
+ */
+
+#define DECLARE_MAP_API(NB, RSH, LSH, OFF, MSK)                     \
+static INLINE void setbit##NB(void *ptr, uint32 ix, uint32 val)     \
+{                                                                   \
+	uint32 *addr = (uint32 *)ptr;                                   \
+	uint32 *a = addr + (ix >> RSH); /* (ix / 2^RSH) */              \
+	uint32 pos = (ix & OFF) << LSH; /* (ix % 2^RSH) * 2^LSH */      \
+	uint32 mask = (MSK << pos);                                     \
+	uint32 tmp = *a & ~mask;                                        \
+	*a = tmp | (val << pos);                                        \
+}                                                                   \
+static INLINE uint32 getbit##NB(void *ptr, uint32 ix)               \
+{                                                                   \
+	uint32 *addr = (uint32 *)ptr;                                   \
+	uint32 *a = addr + (ix >> RSH);                                 \
+	uint32 pos = (ix & OFF) << LSH;                                 \
+	return ((*a >> pos) & MSK);                                     \
+}
+
+DECLARE_MAP_API(2, 4, 1, 15U, 0x0003) /* setbit2() and getbit2() */
+DECLARE_MAP_API(4, 3, 2, 7U, 0x000F) /* setbit4() and getbit4() */
+DECLARE_MAP_API(8, 2, 3, 3U, 0x00FF) /* setbit8() and getbit8() */
+
+/* basic mux operation - can be optimized on several architectures */
+#define MUX(pred, true, false) ((pred) ? (true) : (false))
+
+/* modulo inc/dec - assumes x E [0, bound - 1] */
+#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1)
+#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
+
+/* modulo inc/dec, bound = 2^k */
+#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
+#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
+
+/* modulo add/sub - assumes x, y E [0, 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))
+
+/* module add/sub, bound = 2^k */
+#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
+#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
+
+/* crc defines */
+#define CRC8_INIT_VALUE  0xff		/* Initial CRC8 checksum value */
+#define CRC8_GOOD_VALUE  0x9f		/* Good final CRC8 checksum value */
+#define CRC16_INIT_VALUE 0xffff		/* Initial CRC16 checksum value */
+#define CRC16_GOOD_VALUE 0xf0b8		/* Good final CRC16 checksum value */
+#define CRC32_INIT_VALUE 0xffffffff	/* Initial CRC32 checksum value */
+#define CRC32_GOOD_VALUE 0xdebb20e3	/* Good final CRC32 checksum value */
+
+/* use for direct output of MAC address in printf etc */
+#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 CONST_ETHERP_TO_MACF(ea) ((const struct ether_addr *) (ea))->octet[0], \
+						 ((const struct ether_addr *) (ea))->octet[1], \
+						 ((const struct ether_addr *) (ea))->octet[2], \
+						 ((const struct ether_addr *) (ea))->octet[3], \
+						 ((const struct ether_addr *) (ea))->octet[4], \
+						 ((const 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]
+#if !defined(SIMPLE_MAC_PRINT)
+#define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5]
+#else
+#define MACDBG				"%02x:%02x:%02x"
+#define MAC2STRDBG(ea) (ea)[0], (ea)[4], (ea)[5]
+#endif /* SIMPLE_MAC_PRINT */
+
+/* bcm_format_flags() bit description structure */
+typedef struct bcm_bit_desc {
+	uint32	bit;
+	const char* name;
+} bcm_bit_desc_t;
+
+/* bcm_format_field */
+typedef struct bcm_bit_desc_ex {
+	uint32 mask;
+	const bcm_bit_desc_t *bitfield;
+} bcm_bit_desc_ex_t;
+
+/* buffer length for ethernet address from bcm_ether_ntoa() */
+#define ETHER_ADDR_STR_LEN	18	/* 18-bytes of Ethernet address buffer length */
+
+static INLINE uint32 /* 32bit word aligned xor-32 */
+bcm_compute_xor32(volatile uint32 *u32_val, int num_u32)
+{
+	int idx;
+	uint32 xor32 = 0;
+	for (idx = 0; idx < num_u32; idx++)
+		xor32 ^= *(u32_val + idx);
+	return xor32;
+}
+
+/* crypto utility function */
+/* 128-bit xor: *dst = *src1 xor *src2. dst1, src1 and src2 may have any alignment */
+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) {
+		/* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */
+		/* x86 supports unaligned.  This version runs 6x-9x faster on x86. */
+		((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 {
+		/* ARM CM3 rel time: 4668 (4191 if alignment check could be omitted) */
+		int k;
+		for (k = 0; k < 16; k++)
+			dst[k] = src1[k] ^ src2[k];
+	}
+}
+
+/* externs */
+/* crc */
+extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc);
+extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc);
+extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc);
+
+/* format/print */
+#if defined(BCMDBG) || defined(DHD_DEBUG) || defined(BCMDBG_ERR) || \
+	defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \
+	defined(BCMDBG_DUMP)
+/* print out the value a field has: fields may have 1-32 bits and may hold any value */
+extern int bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 field, char* buf, int len);
+/* print out which bits in flags are set */
+extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len);
+#endif
+
+extern int bcm_format_hex(char *str, const void *bytes, int len);
+
+#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, const uchar *buf, uint len);
+
+/* bcmerror */
+extern const char *bcmerrorstr(int bcmerror);
+
+extern int wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie);
+
+/* multi-bool data type: set of bools, mbool is true if any is set */
+typedef uint32 mbool;
+#define mboolset(mb, bit)		((mb) |= (bit))		/* set one bool */
+#define mboolclr(mb, bit)		((mb) &= ~(bit))	/* clear one bool */
+#define mboolisset(mb, bit)		(((mb) & (bit)) != 0)	/* TRUE if one bool is set */
+#define	mboolmaskset(mb, mask, val)	((mb) = (((mb) & ~(mask)) | (val)))
+
+/* generic datastruct to help dump routines */
+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,
+	const 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 bcm_bitcount(uint8 *bitmap, uint bytelength);
+
+extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...);
+
+/* power conversion */
+extern uint16 bcm_qdbm_to_mw(uint8 qdbm);
+extern uint8 bcm_mw_to_qdbm(uint16 mw);
+extern uint bcm_mkiovar(const char *name, const char *data, uint datalen, char *buf, uint len);
+
+#ifdef BCMDBG_PKT  /* pkt logging for debugging */
+#define PKTLIST_SIZE 3000
+
+#ifdef BCMDBG_PTRACE
+#define PKTTRACE_MAX_BYTES	12
+#define PKTTRACE_MAX_BITS	(PKTTRACE_MAX_BYTES * NBBY)
+
+enum pkttrace_info {
+	PKTLIST_PRECQ,		/* Pkt in Prec Q */
+	PKTLIST_FAIL_PRECQ, 	/* Pkt failed to Q in PRECQ */
+	PKTLIST_DMAQ,		/* Pkt in DMA Q */
+	PKTLIST_MI_TFS_RCVD,	/* Received TX status */
+	PKTLIST_TXDONE,		/* Pkt TX done */
+	PKTLIST_TXFAIL,		/* Pkt TX failed */
+	PKTLIST_PKTFREE,	/* pkt is freed */
+	PKTLIST_PRECREQ,	/* Pkt requeued in precq */
+	PKTLIST_TXFIFO		/* To trace in wlc_fifo */
+};
+#endif /* BCMDBG_PTRACE */
+
+typedef struct pkt_dbginfo {
+	int     line;
+	char    *file;
+	void	*pkt;
+#ifdef BCMDBG_PTRACE
+	char	pkt_trace[PKTTRACE_MAX_BYTES];
+#endif /* BCMDBG_PTRACE */
+} pkt_dbginfo_t;
+
+typedef struct {
+	pkt_dbginfo_t list[PKTLIST_SIZE]; /* List of pointers to packets */
+	uint16 count; /* Total count of the packets */
+} pktlist_info_t;
+
+
+extern void pktlist_add(pktlist_info_t *pktlist, void *p, int len, char *file);
+extern void pktlist_remove(pktlist_info_t *pktlist, void *p);
+extern char* pktlist_dump(pktlist_info_t *pktlist, char *buf);
+#ifdef BCMDBG_PTRACE
+extern void pktlist_trace(pktlist_info_t *pktlist, void *pkt, uint16 bit);
+#endif /* BCMDBG_PTRACE */
+#endif  /* BCMDBG_PKT */
+unsigned int process_nvram_vars(char *varbuf, unsigned int len);
+
+/* trace any object allocation / free, with / without features (flags) set to the object */
+#if (defined(DONGLEBUILD) && defined(BCMDBG_MEM) && !defined(BCM_OBJECT_TRACE))
+#define BCM_OBJECT_TRACE
+#endif /* (defined(DONGLEBUILD) && defined(BCMDBG_MEM) && (!defined(BCM_OBJECT_TRACE))) */
+
+#define BCM_OBJDBG_ADD           1
+#define BCM_OBJDBG_REMOVE        2
+#define BCM_OBJDBG_ADD_PKT       3
+
+/* object feature: set or clear flags */
+#define BCM_OBJECT_FEATURE_FLAG       1
+#define BCM_OBJECT_FEATURE_PKT_STATE  2
+/* object feature: flag bits */
+#define BCM_OBJECT_FEATURE_0     (1 << 0)
+#define BCM_OBJECT_FEATURE_1     (1 << 1)
+#define BCM_OBJECT_FEATURE_2     (1 << 2)
+/* object feature: clear flag bits field set with this flag */
+#define BCM_OBJECT_FEATURE_CLEAR (1 << 31)
+#ifdef BCM_OBJECT_TRACE
+#define bcm_pkt_validate_chk(obj)	do { \
+	void * pkttag; \
+	bcm_object_trace_chk(obj, 0, 0, \
+		__FUNCTION__, __LINE__); \
+	if ((pkttag = PKTTAG(obj))) { \
+		bcm_object_trace_chk(obj, 1, DHD_PKTTAG_SN(pkttag), \
+			__FUNCTION__, __LINE__); \
+	} \
+} while (0)
+extern void bcm_object_trace_opr(void *obj, uint32 opt, const char *caller, int line);
+extern void bcm_object_trace_upd(void *obj, void *obj_new);
+extern void bcm_object_trace_chk(void *obj, uint32 chksn, uint32 sn,
+	const char *caller, int line);
+extern void bcm_object_feature_set(void *obj, uint32 type, uint32 value);
+extern int  bcm_object_feature_get(void *obj, uint32 type, uint32 value);
+extern void bcm_object_trace_init(void);
+extern void bcm_object_trace_deinit(void);
+#else
+#define bcm_pkt_validate_chk(obj)
+#define bcm_object_trace_opr(a, b, c, d)
+#define bcm_object_trace_upd(a, b)
+#define bcm_object_trace_chk(a, b, c, d, e)
+#define bcm_object_feature_set(a, b, c)
+#define bcm_object_feature_get(a, b, c)
+#define bcm_object_trace_init()
+#define bcm_object_trace_deinit()
+#endif /* BCM_OBJECT_TRACE */
+
+/* calculate a * b + c */
+extern void bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c);
+/* calculate a / b */
+extern void bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b);
+/* calculate uint64 a / b (returns uint64) */
+extern uint64 bcm_uint64_div(uint32 a_high, uint32 a_low, uint32 b);
+
+
+/* Public domain bit twiddling hacks/utilities: Sean Eron Anderson */
+
+/* Table driven count set bits. */
+static const uint8 /* Table only for use by bcm_cntsetbits */
+_CSBTBL[256] =
+{
+#	define B2(n)    n,     n + 1,     n + 1,     n + 2
+#	define B4(n) B2(n), B2(n + 1), B2(n + 1), B2(n + 2)
+#	define B6(n) B4(n), B4(n + 1), B4(n + 1), B4(n + 2)
+	B6(0), B6(0 + 1), B6(0 + 1), B6(0 + 2)
+};
+
+static INLINE uint32 /* Uses table _CSBTBL for fast counting of 1's in a u32 */
+bcm_cntsetbits(const uint32 u32arg)
+{
+	/* function local scope declaration of const _CSBTBL[] */
+	const uint8 * p = (const uint8 *)&u32arg;
+	return (_CSBTBL[p[0]] + _CSBTBL[p[1]] + _CSBTBL[p[2]] + _CSBTBL[p[3]]);
+}
+
+
+static INLINE int /* C equivalent count of leading 0's in a u32 */
+C_bcm_count_leading_zeros(uint32 u32arg)
+{
+	int shifts = 0;
+	while (u32arg) {
+		shifts++; u32arg >>= 1;
+	}
+	return (32U - shifts);
+}
+
+#ifdef BCMDRIVER
+/*
+ * Assembly instructions: Count Leading Zeros
+ * "clz"	: MIPS, ARM
+ * "cntlzw"	: PowerPC
+ * "BSF"	: x86
+ * "lzcnt"	: AMD, SPARC
+ */
+#if defined(__mips__)
+#define __USE_ASM_CLZ__
+#endif /* __mips__ */
+
+#if defined(__arm__)
+#if defined(__ARM_ARCH_7M__) /* Cortex M3 */
+#define __USE_ASM_CLZ__
+#endif /* __ARM_ARCH_7M__ */
+#if defined(__ARM_ARCH_7R__) /* Cortex R4 */
+#define __USE_ASM_CLZ__
+#endif /* __ARM_ARCH_7R__ */
+#endif /* __arm__ */
+
+static INLINE int
+bcm_count_leading_zeros(uint32 u32arg)
+{
+#if defined(__USE_ASM_CLZ__)
+	int zeros;
+	__asm__ volatile("clz    %0, %1 \n" : "=r" (zeros) : "r"  (u32arg));
+	return zeros;
+#else	/* C equivalent */
+	return C_bcm_count_leading_zeros(u32arg);
+#endif  /* C equivalent */
+}
+
+/*
+ * Macro to count leading zeroes
+ *
+ */
+#if defined(__GNUC__)
+#define CLZ(x) __builtin_clzl(x)
+#elif defined(__arm__)
+#define CLZ(x) __clz(x)
+#else
+#define CLZ(x) bcm_count_leading_zeros(x)
+#endif /* __GNUC__ */
+
+/* INTERFACE: Multiword bitmap based small id allocator. */
+struct bcm_mwbmap;	/* forward declaration for use as an opaque mwbmap handle */
+
+#define BCM_MWBMAP_INVALID_HDL	((struct bcm_mwbmap *)NULL)
+#define BCM_MWBMAP_INVALID_IDX	((uint32)(~0U))
+
+/* Incarnate a multiword bitmap based small index allocator */
+extern struct bcm_mwbmap * bcm_mwbmap_init(osl_t * osh, uint32 items_max);
+
+/* Free up the multiword bitmap index allocator */
+extern void bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl);
+
+/* Allocate a unique small index using a multiword bitmap index allocator */
+extern uint32 bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl);
+
+/* Force an index at a specified position to be in use */
+extern void bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
+
+/* Free a previously allocated index back into the multiword bitmap allocator */
+extern void bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
+
+/* Fetch the toal number of free indices in the multiword bitmap allocator */
+extern uint32 bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl);
+
+/* Determine whether an index is inuse or free */
+extern bool bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix);
+
+/* Debug dump a multiword bitmap allocator */
+extern void bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl);
+
+extern void bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl);
+/* End - Multiword bitmap based small Id allocator. */
+
+
+/* INTERFACE: Simple unique 16bit Id Allocator using a stack implementation. */
+
+#define ID8_INVALID     0xFFu
+#define ID16_INVALID    0xFFFFu
+#define ID32_INVALID    0xFFFFFFFFu
+#define ID16_UNDEFINED              ID16_INVALID
+
+/*
+ * Construct a 16bit id allocator, managing 16bit ids in the range:
+ *    [start_val16 .. start_val16+total_ids)
+ * Note: start_val16 is inclusive.
+ * Returns an opaque handle to the 16bit id allocator.
+ */
+extern void * id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16);
+extern void * id16_map_fini(osl_t *osh, void * id16_map_hndl);
+extern void id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16);
+
+/* Allocate a unique 16bit id */
+extern uint16 id16_map_alloc(void * id16_map_hndl);
+
+/* Free a 16bit id value into the id16 allocator */
+extern void id16_map_free(void * id16_map_hndl, uint16 val16);
+
+/* Get the number of failures encountered during id allocation. */
+extern uint32 id16_map_failures(void * id16_map_hndl);
+
+/* Audit the 16bit id allocator state. */
+extern bool id16_map_audit(void * id16_map_hndl);
+/* End - Simple 16bit Id Allocator. */
+#endif /* BCMDRIVER */
+
+extern void bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b);
+
+void bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset);
+void bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset);
+
+uint64 fp_mult_64(uint64 val1, uint64 val2, uint8 nf1, uint8 nf2, uint8 nf_res);
+uint8 fp_div_64(uint64 num, uint32 den, uint8 nf_num, uint8 nf_den, uint32 *div_out);
+uint8 fp_calc_head_room_64(uint64 num);
+uint8 fp_calc_head_room_32(uint32 num);
+uint32 fp_round_64(uint64 num, uint8 rnd_pos);
+uint32 fp_round_32(uint32 num, uint8 rnd_pos);
+uint32 fp_floor_64(uint64 num, uint8 floor_pos);
+uint32 fp_floor_32(uint32 num, uint8 floor_pos);
+uint32 fp_ceil_64(uint64 num, uint8 ceil_pos);
+uint64 bcm_shl_64(uint64 input, uint8 shift_amt);
+uint64 bcm_shr_64(uint64 input, uint8 shift_amt);
+
+#define MASK_32_BITS	(~0)
+#define MASK_8_BITS	((1 << 8) - 1)
+
+#define EXTRACT_LOW32(num)	(uint32)(num & MASK_32BITS)
+#define EXTRACT_HIGH32(num)	(uint32)(((uint64)num >> 32) & MASK_32BITS)
+
+#define MAXIMUM(a, b) ((a > b) ? a : b)
+#define MINIMUM(a, b) ((a < b) ? a : b)
+#define LIMIT(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
+
+/* calculate checksum for ip header, tcp / udp header / data */
+uint16 bcm_ip_cksum(uint8 *buf, uint32 len, uint32 sum);
+
+#ifndef _dll_t_
+#define _dll_t_
+/*
+ * -----------------------------------------------------------------------------
+ *                      Double Linked List Macros
+ * -----------------------------------------------------------------------------
+ *
+ * All dll operations must be performed on a pre-initialized node.
+ * Inserting an uninitialized node into a list effectively initialized it.
+ *
+ * When a node is deleted from a list, you may initialize it to avoid corruption
+ * incurred by double deletion. You may skip initialization if the node is
+ * immediately inserted into another list.
+ *
+ * By placing a dll_t element at the start of a struct, you may cast a dll_t *
+ * to the struct or vice versa.
+ *
+ * Example of declaring an initializing someList and inserting nodeA, nodeB
+ *
+ *     typedef struct item {
+ *         dll_t node;
+ *         int someData;
+ *     } Item_t;
+ *     Item_t nodeA, nodeB, nodeC;
+ *     nodeA.someData = 11111, nodeB.someData = 22222, nodeC.someData = 33333;
+ *
+ *     dll_t someList;
+ *     dll_init(&someList);
+ *
+ *     dll_append(&someList, (dll_t *) &nodeA);
+ *     dll_prepend(&someList, &nodeB.node);
+ *     dll_insert((dll_t *)&nodeC, &nodeA.node);
+ *
+ *     dll_delete((dll_t *) &nodeB);
+ *
+ * Example of a for loop to walk someList of node_p
+ *
+ *   extern void mydisplay(Item_t * item_p);
+ *
+ *   dll_t * item_p, * next_p;
+ *   for (item_p = dll_head_p(&someList); ! dll_end(&someList, item_p);
+ *        item_p = next_p)
+ *   {
+ *       next_p = dll_next_p(item_p);
+ *       ... use item_p at will, including removing it from list ...
+ *       mydisplay((PItem_t)item_p);
+ *   }
+ *
+ * -----------------------------------------------------------------------------
+ */
+typedef struct dll {
+	struct dll * next_p;
+	struct dll * prev_p;
+} dll_t;
+
+static INLINE void
+dll_init(dll_t *node_p)
+{
+	node_p->next_p = node_p;
+	node_p->prev_p = node_p;
+}
+/* dll macros returing a pointer to dll_t */
+
+static INLINE dll_t *
+dll_head_p(dll_t *list_p)
+{
+	return list_p->next_p;
+}
+
+
+static INLINE dll_t *
+dll_tail_p(dll_t *list_p)
+{
+	return (list_p)->prev_p;
+}
+
+
+static INLINE dll_t *
+dll_next_p(dll_t *node_p)
+{
+	return (node_p)->next_p;
+}
+
+
+static INLINE dll_t *
+dll_prev_p(dll_t *node_p)
+{
+	return (node_p)->prev_p;
+}
+
+
+static INLINE bool
+dll_empty(dll_t *list_p)
+{
+	return ((list_p)->next_p == (list_p));
+}
+
+
+static INLINE bool
+dll_end(dll_t *list_p, dll_t * node_p)
+{
+	return (list_p == node_p);
+}
+
+
+/* inserts the node new_p "after" the node at_p */
+static INLINE void
+dll_insert(dll_t *new_p, dll_t * at_p)
+{
+	new_p->next_p = at_p->next_p;
+	new_p->prev_p = at_p;
+	at_p->next_p = new_p;
+	(new_p->next_p)->prev_p = new_p;
+}
+
+static INLINE void
+dll_append(dll_t *list_p, dll_t *node_p)
+{
+	dll_insert(node_p, dll_tail_p(list_p));
+}
+
+static INLINE void
+dll_prepend(dll_t *list_p, dll_t *node_p)
+{
+	dll_insert(node_p, list_p);
+}
+
+
+/* deletes a node from any list that it "may" be in, if at all. */
+static INLINE void
+dll_delete(dll_t *node_p)
+{
+	node_p->prev_p->next_p = node_p->next_p;
+	node_p->next_p->prev_p = node_p->prev_p;
+}
+#endif  /* ! defined(_dll_t_) */
+
+/* Elements managed in a double linked list */
+
+typedef struct dll_pool {
+	dll_t       free_list;
+	uint16      free_count;
+	uint16      elems_max;
+	uint16      elem_size;
+	dll_t       elements[1];
+} dll_pool_t;
+
+dll_pool_t * dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size);
+void * dll_pool_alloc(dll_pool_t * dll_pool_p);
+void dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p);
+void dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p);
+typedef void (* dll_elem_dump)(void * elem_p);
+#ifdef BCMDBG
+void dll_pool_dump(dll_pool_t * dll_pool_p, dll_elem_dump dump);
+#endif
+void dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size);
+
+int valid_bcmerror(int e);
+
+/* calculate IPv4 header checksum
+ * - input ip points to IP header in network order
+ * - output cksum is in network order
+ */
+uint16 ipv4_hdr_cksum(uint8 *ip, int ip_len);
+
+/* calculate IPv4 TCP header checksum
+ * - input ip and tcp points to IP and TCP header in network order
+ * - output cksum is in network order
+ */
+uint16 ipv4_tcp_hdr_cksum(uint8 *ip, uint8 *tcp, uint16 tcp_len);
+
+/* calculate IPv6 TCP header checksum
+ * - input ipv6 and tcp points to IPv6 and TCP header in network order
+ * - output cksum is in network order
+ */
+uint16 ipv6_tcp_hdr_cksum(uint8 *ipv6, uint8 *tcp, uint16 tcp_len);
+
+#ifdef __cplusplus
+	}
+#endif
+
+/* #define DEBUG_COUNTER */
+#ifdef DEBUG_COUNTER
+#define CNTR_TBL_MAX 10
+typedef struct _counter_tbl_t {
+	char name[16];				/* name of this counter table */
+	uint32 prev_log_print;		/* Internal use. Timestamp of the previous log print */
+	uint log_print_interval;	/* Desired interval to print logs in ms */
+	uint needed_cnt;			/* How many counters need to be used */
+	uint32 cnt[CNTR_TBL_MAX];		/* Counting entries to increase at desired places */
+	bool enabled;				/* Whether to enable printing log */
+} counter_tbl_t;
+
+
+void counter_printlog(counter_tbl_t *ctr_tbl);
+#endif /* DEBUG_COUNTER */
+
+#if defined(__GNUC__)
+#define CALL_SITE __builtin_return_address(0)
+#else
+#define CALL_SITE ((void*) 0)
+#endif
+#ifdef SHOW_LOGTRACE
+#define TRACE_LOG_BUF_MAX_SIZE 1500
+#define BUF_NOT_AVAILABLE	0
+#define NEXT_BUF_NOT_AVAIL	1
+#define NEXT_BUF_AVAIL		2
+
+typedef struct trace_buf_info {
+	int availability;
+	int size;
+	char buf[TRACE_LOG_BUF_MAX_SIZE];
+} trace_buf_info_t;
+#endif /* SHOW_LOGTRACE */
+
+typedef int32 math_fixed; /* s15.16 fixed-point */
+
+typedef struct _cint32 {
+	math_fixed	q;
+	math_fixed	i;
+} math_cint32;
+
+typedef math_cint32 cint32;
+
+extern void mult_cint32_cfixed(const cint32* in1, const cint32* in2, const uint8 prec,
+	cint32* out, bool conj);
+extern void add_cint32(const cint32* in1, const cint32* in2, cint32* out);
+extern void power_cint32(const cint32* in1, uint32* pwr);
+extern void power_cint32_arr(const cint32* in1, const uint16* idx_arr, uint16 len, uint32* pwr);
+extern uint32 sqrt_int(uint32 value);
+
+#endif	/* _bcmutils_h_ */
diff --git a/wl/src/include/brcm_nl80211.h b/wl/src/include/brcm_nl80211.h
new file mode 100644
index 0000000..47f5801
--- /dev/null
+++ b/wl/src/include/brcm_nl80211.h
@@ -0,0 +1,63 @@
+/*
+ * Definitions for nl80211 vendor command/event access to host driver
+ *
+ * Copyright (C) 2017, Broadcom. 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: brcm_nl80211.h 601873 2015-11-24 11:04:28Z $
+ *
+ */
+
+#ifndef _brcm_nl80211_h_
+#define _brcm_nl80211_h_
+
+#define OUI_BRCM  0x001018
+#define OUI_GOOGLE  0x001A11
+
+enum wl_vendor_subcmd {
+	BRCM_VENDOR_SCMD_UNSPEC,
+	BRCM_VENDOR_SCMD_PRIV_STR,
+	BRCM_VENDOR_SCMD_BCM_STR
+};
+
+
+struct bcm_nlmsg_hdr {
+	uint cmd;	/* common ioctl definition */
+	int len;	/* expected return buffer length */
+	uint offset;	/* user buffer offset */
+	uint set;	/* get or set request optional */
+	uint magic;	/* magic number for verification */
+};
+
+enum bcmnl_attrs {
+	BCM_NLATTR_UNSPEC,
+
+	BCM_NLATTR_LEN,
+	BCM_NLATTR_DATA,
+
+	__BCM_NLATTR_AFTER_LAST,
+	BCM_NLATTR_MAX = __BCM_NLATTR_AFTER_LAST - 1
+};
+
+struct nl_prv_data {
+	int err;			/* return result */
+	void *data;			/* ioctl return buffer pointer */
+	uint len;			/* ioctl return buffer length */
+	struct bcm_nlmsg_hdr *nlioc;	/* bcm_nlmsg_hdr header pointer */
+};
+
+#endif /* _brcm_nl80211_h_ */
diff --git a/wl/src/include/dhdioctl.h b/wl/src/include/dhdioctl.h
new file mode 100644
index 0000000..72bbd7e
--- /dev/null
+++ b/wl/src/include/dhdioctl.h
@@ -0,0 +1,151 @@
+/*
+ * Definitions for ioctls to access DHD iovars.
+ * Based on wlioctl.h (for Broadcom 802.11abg driver).
+ * (Moves towards generic ioctls for BCM drivers/iovars.)
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 2017, Broadcom. 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: dhdioctl.h 660496 2016-09-20 19:28:50Z $
+ */
+
+#ifndef _dhdioctl_h_
+#define	_dhdioctl_h_
+
+#include <typedefs.h>
+
+#if defined(__FreeBSD__)
+/* NetBSD 2.0 does not have SIOCDEVPRIVATE. This is NetBSD 2.0 specific */
+#define SIOCDEVPRIVATE  _IOWR('i', 139, struct ifreq)
+#endif
+
+/* Linux network driver ioctl encoding */
+typedef struct dhd_ioctl {
+	uint32 cmd;	/* common ioctl definition */
+	void *buf;	/* pointer to user buffer */
+	uint32 len;	/* length of user buffer */
+	uint32 set;	/* get or set request boolean (optional) */
+	uint32 used;	/* bytes read or written (optional) */
+	uint32 needed;	/* bytes needed (optional) */
+	uint32 driver;	/* to identify target driver */
+} dhd_ioctl_t;
+
+/* Underlying BUS definition */
+enum {
+	BUS_TYPE_USB = 0, /* for USB dongles */
+	BUS_TYPE_SDIO, /* for SDIO dongles */
+	BUS_TYPE_PCIE /* for PCIE dongles */
+};
+
+
+/* per-driver magic numbers */
+#define DHD_IOCTL_MAGIC		0x00444944
+
+/* bump this number if you change the ioctl interface */
+#define DHD_IOCTL_VERSION	1
+
+/*
+ * Increase the DHD_IOCTL_MAXLEN to 16K for supporting download of NVRAM files of size
+ * > 8K. In the existing implementation when NVRAM is to be downloaded via the "vars"
+ * DHD IOVAR, the NVRAM is copied to the DHD Driver memory. Later on when "dwnldstate" is
+ * invoked with FALSE option, the NVRAM gets copied from the DHD driver to the Dongle
+ * memory. The simple way to support this feature without modifying the DHD application,
+ * driver logic is to increase the DHD_IOCTL_MAXLEN size. This macro defines the "size"
+ * of the buffer in which data is exchanged between the DHD App and DHD driver.
+ */
+#define	DHD_IOCTL_MAXLEN	(16384)	/* max length ioctl buffer required */
+#define	DHD_IOCTL_SMLEN		256		/* "small" length ioctl buffer required */
+
+/* common ioctl definitions */
+#define DHD_GET_MAGIC				0
+#define DHD_GET_VERSION				1
+#define DHD_GET_VAR				2
+#define DHD_SET_VAR				3
+
+/* message levels */
+#define DHD_ERROR_VAL	0x0001
+#define DHD_TRACE_VAL	0x0002
+#define DHD_INFO_VAL	0x0004
+#define DHD_DATA_VAL	0x0008
+#define DHD_CTL_VAL	0x0010
+#define DHD_TIMER_VAL	0x0020
+#define DHD_HDRS_VAL	0x0040
+#define DHD_BYTES_VAL	0x0080
+#define DHD_INTR_VAL	0x0100
+#define DHD_LOG_VAL	0x0200
+#define DHD_GLOM_VAL	0x0400
+#define DHD_EVENT_VAL	0x0800
+#define DHD_BTA_VAL	0x1000
+#if 0 && (NDISVER >= 0x0630) && defined(BCMDONGLEHOST)
+#define DHD_SCAN_VAL	0x2000
+#else
+#define DHD_ISCAN_VAL	0x2000
+#endif
+#define DHD_ARPOE_VAL	0x4000
+#define DHD_REORDER_VAL	0x8000
+#define DHD_WL_VAL		0x10000
+#define DHD_NOCHECKDIED_VAL		0x20000 /* UTF WAR */
+#define DHD_WL_VAL2		0x40000
+#define DHD_PNO_VAL		0x80000
+#define DHD_RTT_VAL		0x100000
+#define DHD_MSGTRACE_VAL	0x200000
+#define DHD_FWLOG_VAL		0x400000
+#define DHD_DBGIF_VAL		0x800000
+#ifdef DHD_PCIE_NATIVE_RUNTIMEPM
+#define DHD_RPM_VAL		0x1000000
+#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */
+#define DHD_PKT_MON_VAL		0x2000000
+#define DHD_PKT_MON_DUMP_VAL	0x4000000
+
+#ifdef SDTEST
+/* For pktgen iovar */
+typedef struct dhd_pktgen {
+	uint32 version;		/* To allow structure change tracking */
+	uint32 freq;		/* Max ticks between tx/rx attempts */
+	uint32 count;		/* Test packets to send/rcv each attempt */
+	uint32 print;		/* Print counts every <print> attempts */
+	uint32 total;		/* Total packets (or bursts) */
+	uint32 minlen;		/* Minimum length of packets to send */
+	uint32 maxlen;		/* Maximum length of packets to send */
+	uint32 numsent;		/* Count of test packets sent */
+	uint32 numrcvd;		/* Count of test packets received */
+	uint32 numfail;		/* Count of test send failures */
+	uint32 mode;		/* Test mode (type of test packets) */
+	uint32 stop;		/* Stop after this many tx failures */
+} dhd_pktgen_t;
+
+/* Version in case structure changes */
+#define DHD_PKTGEN_VERSION 2
+
+/* Type of test packets to use */
+#define DHD_PKTGEN_ECHO		1 /* Send echo requests */
+#define DHD_PKTGEN_SEND 	2 /* Send discard packets */
+#define DHD_PKTGEN_RXBURST	3 /* Request dongle send N packets */
+#define DHD_PKTGEN_RECV		4 /* Continuous rx from continuous tx dongle */
+#endif /* SDTEST */
+
+/* Enter idle immediately (no timeout) */
+#define DHD_IDLE_IMMEDIATE	(-1)
+
+/* Values for idleclock iovar: other values are the sd_divisor to use when idle */
+#define DHD_IDLE_ACTIVE	0	/* Do not request any SD clock change when idle */
+#define DHD_IDLE_STOP   (-1)	/* Request SD clock be stopped (and use SD1 mode) */
+
+
+#endif /* _dhdioctl_h_ */
diff --git a/wl/src/include/epivers.h b/wl/src/include/epivers.h
new file mode 100644
index 0000000..8a2d74a
--- /dev/null
+++ b/wl/src/include/epivers.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017, Broadcom. 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: epivers.h.in 596126 2015-10-29 19:53:48Z $
+ *
+*/
+
+#ifndef _epivers_h_
+#define _epivers_h_
+
+#define	EPI_MAJOR_VERSION	2017
+
+#define	EPI_MINOR_VERSION	5
+
+#define	EPI_RC_NUMBER		14
+
+#define	EPI_INCREMENTAL_NUMBER	0
+
+#define	EPI_BUILD_NUMBER	0
+
+#define	EPI_VERSION		2017, 5, 14, 0
+
+#define	EPI_VERSION_NUM		0x7e1050e0
+
+#define EPI_VERSION_DEV		2017.5.14
+
+/* Driver Version String, ASCII, 32 chars max */
+#define	EPI_VERSION_STR		"2017.05.14 (r665031)"
+
+#endif /* _epivers_h_ */
diff --git a/wl/src/include/event_log.h b/wl/src/include/event_log.h
new file mode 100644
index 0000000..57dec6b
--- /dev/null
+++ b/wl/src/include/event_log.h
@@ -0,0 +1,388 @@
+/*
+ * EVENT_LOG system definitions
+ *
+ * Copyright (C) 2017, Broadcom. 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: event_log.h 657831 2016-09-02 18:52:56Z $
+ */
+
+#ifndef _EVENT_LOG_H_
+#define _EVENT_LOG_H_
+
+#include <typedefs.h>
+#include <proto/event_log_set.h>
+#include <proto/event_log_tag.h>
+#include <proto/event_log_payload.h>
+#include <osl_decl.h>
+
+/* logstrs header */
+#define LOGSTRS_MAGIC   0x4C4F4753
+#define LOGSTRS_VERSION 0x1
+
+/* We make sure that the block size will fit in a single packet
+ *  (allowing for a bit of overhead on each packet
+ */
+#if defined(BCMPCIEDEV)
+#define EVENT_LOG_MAX_BLOCK_SIZE	1648
+#else
+#define EVENT_LOG_MAX_BLOCK_SIZE	1400
+#endif
+#define EVENT_LOG_WL_BLOCK_SIZE		0x200
+#define EVENT_LOG_PSM_BLOCK_SIZE	0x200
+#define EVENT_LOG_BUS_BLOCK_SIZE	0x200
+#define EVENT_LOG_ERROR_BLOCK_SIZE	0x200
+/* Maximum event log record payload size = 1024 bytes or 256 words. */
+#define EVENT_LOG_MAX_RECORD_PAYLOAD_SIZE	256
+
+/*
+ * There are multiple levels of objects define here:
+ *   event_log_set - a set of buffers
+ *   event log groups - every event log call is part of just one.  All
+ *                      event log calls in a group are handled the
+ *                      same way.  Each event log group is associated
+ *                      with an event log set or is off.
+ */
+
+#ifndef __ASSEMBLER__
+
+/* On the external system where the dumper is we need to make sure
+ * that these types are the same size as they are on the ARM the
+ * produced them
+ */
+#ifdef EVENT_LOG_DUMPER
+#define _EL_BLOCK_PTR uint32
+#define _EL_TYPE_PTR uint32
+#define _EL_SET_PTR uint32
+#define _EL_TOP_PTR uint32
+#else
+#define _EL_BLOCK_PTR struct event_log_block *
+#define _EL_TYPE_PTR uint32 *
+#define _EL_SET_PTR struct event_log_set **
+#define _EL_TOP_PTR struct event_log_top *
+#endif /* EVENT_LOG_DUMPER */
+
+/* Event log sets (a logical circurlar buffer) consist of one or more
+ * event_log_blocks.  The blocks themselves form a logical circular
+ * list.  The log entries are placed in each event_log_block until it
+ * is full.  Logging continues with the next event_log_block in the
+ * event_set until the last event_log_block is reached and then
+ * logging starts over with the first event_log_block in the
+ * event_set.
+ */
+typedef struct event_log_block {
+	_EL_BLOCK_PTR next_block;
+	_EL_BLOCK_PTR prev_block;
+	_EL_TYPE_PTR end_ptr;
+
+	/* Start of packet sent for log tracing */
+	uint16 pktlen;			/* Size of rest of block */
+	uint16 count;			/* Logtrace counter */
+	uint32 extra_hdr_info;		/* LSB: 6 bits set id. MSB 24 bits reserved */
+	uint32 event_logs;
+} event_log_block_t;
+
+typedef enum {
+	SET_DESTINATION_INVALID = -1,
+	SET_DESTINATION_HOST = 0,
+	SET_DESTINATION_NONE = 1,
+	SET_DESTINATION_MAX
+} event_log_set_destination_t;
+
+/* There can be multiple event_sets with each logging a set of
+ * associated events (i.e, "fast" and "slow" events).
+ */
+typedef struct event_log_set {
+	_EL_BLOCK_PTR first_block; 	/* Pointer to first event_log block */
+	_EL_BLOCK_PTR last_block; 	/* Pointer to last event_log block */
+	_EL_BLOCK_PTR logtrace_block;	/* next block traced */
+	_EL_BLOCK_PTR cur_block;   	/* Pointer to current event_log block */
+	_EL_TYPE_PTR cur_ptr;      	/* Current event_log pointer */
+	uint32 blockcount;		/* Number of blocks */
+	uint16 logtrace_count;		/* Last count for logtrace */
+	uint16 blockfill_count;		/* Fill count for logtrace */
+	uint32 timestamp;		/* Last timestamp event */
+	uint32 cyclecount;		/* Cycles at last timestamp event */
+	event_log_set_destination_t destination;
+	uint16 size;			/* same size for all buffers in one  set */
+} event_log_set_t;
+
+/* Top data structure for access to everything else */
+typedef struct event_log_top {
+	uint32 magic;
+#define EVENT_LOG_TOP_MAGIC 0x474C8669 /* 'EVLG' */
+	uint32 version;
+#define EVENT_LOG_VERSION 1
+	uint32 num_sets;
+	uint32 logstrs_size;		/* Size of lognums + logstrs area */
+	uint32 timestamp;		/* Last timestamp event */
+	uint32 cyclecount;		/* Cycles at last timestamp event */
+	_EL_SET_PTR sets; 		/* Ptr to array of <num_sets> set ptrs */
+} event_log_top_t;
+
+/* Data structure of Keeping the Header from logstrs.bin */
+typedef struct {
+	uint32 logstrs_size;    /* Size of the file */
+	uint32 rom_lognums_offset; /* Offset to the ROM lognum */
+	uint32 ram_lognums_offset; /* Offset to the RAM lognum */
+	uint32 rom_logstrs_offset; /* Offset to the ROM logstr */
+	uint32 ram_logstrs_offset; /* Offset to the RAM logstr */
+	/* Keep version and magic last since "header" is appended to the end of logstrs file. */
+	uint32 version;            /* Header version */
+	uint32 log_magic;       /* MAGIC number for verification 'LOGS' */
+} logstr_header_t;
+
+/*
+ * Use the following macros for generating log events.
+ *
+ * The FAST versions check the enable of the tag before evaluating the arguments and calling the
+ * event_log function.  This adds 5 instructions.  The COMPACT versions evaluate the arguments
+ * and call the event_log function unconditionally.  The event_log function will then skip logging
+ * if this tag is disabled.
+ *
+ * To support easy usage of existing debugging (e.g. msglevel) via macro re-definition there are
+ * two variants of these macros to help.
+ *
+ * First there are the CAST versions.  The event_log function normally logs uint32 values or else
+ * they have to be cast to uint32.  The CAST versions blindly cast for you so you don't have to edit
+ * any existing code.
+ *
+ * Second there are the PAREN_ARGS versions.  These expect the logging format string and arguments
+ * to be enclosed in parentheses.  This allows us to make the following mapping of an existing
+ * msglevel macro:
+ *  #define WL_ERROR(args)   EVENT_LOG_CAST_PAREN_ARGS(EVENT_LOG_TAG_WL_ERROR, args)
+ *
+ * The versions of the macros without FAST or COMPACT in their name are just synonyms for the
+ * COMPACT versions.
+ *
+ * You should use the COMPACT macro (or its synonym) in cases where there is some preceding logic
+ * that prevents the execution of the macro, e.g. WL_ERROR by definition rarely gets executed.
+ * Use the FAST macro in performance sensitive paths. The key concept here is that you should be
+ * assuming that your macro usage is compiled into ROM and can't be changed ... so choose wisely.
+ *
+ */
+
+#if !defined(EVENT_LOG_DUMPER) && !defined(DHD_EFI)
+
+#ifndef EVENT_LOG_COMPILE
+
+/* Null define if no tracing */
+#define EVENT_LOG(format, ...)
+#define EVENT_LOG_FAST(tag, fmt, ...)
+#define EVENT_LOG_COMPACT(tag, fmt, ...)
+
+#define EVENT_LOG_CAST(tag, fmt, ...)
+#define EVENT_LOG_FAST_CAST(tag, fmt, ...)
+#define EVENT_LOG_COMPACT_CAST(tag, fmt, ...)
+
+#define EVENT_LOG_CAST_PAREN_ARGS(tag, pargs)
+#define EVENT_LOG_FAST_CAST_PAREN_ARGS(tag, pargs)
+#define EVENT_LOG_COMPACT_CAST_PAREN_ARGS(tag, pargs)
+
+#define EVENT_LOG_IS_ON(tag)		0
+#define EVENT_LOG_IS_LOG_ON(tag)	0
+
+#define EVENT_LOG_BUFFER(tag, buf, size)
+
+#else  /* EVENT_LOG_COMPILE */
+
+/* The first few are special because they can be done more efficiently
+ * this way and they are the common case.  Once there are too many
+ * parameters the code size starts to be an issue and a loop is better
+ */
+#define _EVENT_LOG0(tag, fmt_num) 			\
+	event_log0(tag, fmt_num)
+#define _EVENT_LOG1(tag, fmt_num, t1) 			\
+	event_log1(tag, fmt_num, t1)
+#define _EVENT_LOG2(tag, fmt_num, t1, t2) 		\
+	event_log2(tag, fmt_num, t1, t2)
+#define _EVENT_LOG3(tag, fmt_num, t1, t2, t3) 		\
+	event_log3(tag, fmt_num, t1, t2, t3)
+#define _EVENT_LOG4(tag, fmt_num, t1, t2, t3, t4) 	\
+	event_log4(tag, fmt_num, t1, t2, t3, t4)
+
+/* The rest call the generic routine that takes a count */
+#define _EVENT_LOG5(tag, fmt_num, ...) event_logn(5, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG6(tag, fmt_num, ...) event_logn(6, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG7(tag, fmt_num, ...) event_logn(7, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG8(tag, fmt_num, ...) event_logn(8, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG9(tag, fmt_num, ...) event_logn(9, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGA(tag, fmt_num, ...) event_logn(10, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGB(tag, fmt_num, ...) event_logn(11, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGC(tag, fmt_num, ...) event_logn(12, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGD(tag, fmt_num, ...) event_logn(13, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGE(tag, fmt_num, ...) event_logn(14, tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOGF(tag, fmt_num, ...) event_logn(15, tag, fmt_num, __VA_ARGS__)
+
+
+/* Casting  low level macros */
+#define _EVENT_LOG_CAST0(tag, fmt_num)			\
+	event_log0(tag, fmt_num)
+#define _EVENT_LOG_CAST1(tag, fmt_num, t1)		\
+	event_log1(tag, fmt_num, (uint32)(t1))
+#define _EVENT_LOG_CAST2(tag, fmt_num, t1, t2)		\
+	event_log2(tag, fmt_num, (uint32)(t1), (uint32)(t2))
+#define _EVENT_LOG_CAST3(tag, fmt_num, t1, t2, t3)	\
+	event_log3(tag, fmt_num, (uint32)(t1), (uint32)(t2), (uint32)(t3))
+#define _EVENT_LOG_CAST4(tag, fmt_num, t1, t2, t3, t4)	\
+	event_log4(tag, fmt_num, (uint32)(t1), (uint32)(t2), (uint32)(t3), (uint32)(t4))
+
+/* The rest call the generic routine that takes a count */
+#define _EVENT_LOG_CAST5(tag, fmt_num, ...) _EVENT_LOG5(tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG_CAST6(tag, fmt_num, ...) _EVENT_LOG6(tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG_CAST7(tag, fmt_num, ...) _EVENT_LOG7(tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG_CAST8(tag, fmt_num, ...) _EVENT_LOG8(tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG_CAST9(tag, fmt_num, ...) _EVENT_LOG9(tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG_CASTA(tag, fmt_num, ...) _EVENT_LOGA(tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG_CASTB(tag, fmt_num, ...) _EVENT_LOGB(tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG_CASTC(tag, fmt_num, ...) _EVENT_LOGC(tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG_CASTD(tag, fmt_num, ...) _EVENT_LOGD(tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG_CASTE(tag, fmt_num, ...) _EVENT_LOGE(tag, fmt_num, __VA_ARGS__)
+#define _EVENT_LOG_CASTF(tag, fmt_num, ...) _EVENT_LOGF(tag, fmt_num, __VA_ARGS__)
+
+/* Hack to make the proper routine call when variadic macros get
+ * passed.  Note the max of 15 arguments.  More than that can't be
+ * handled by the event_log entries anyways so best to catch it at compile
+ * time
+ */
+
+#define _EVENT_LOG_VA_NUM_ARGS(F, _1, _2, _3, _4, _5, _6, _7, _8, _9,	\
+			       _A, _B, _C, _D, _E, _F, N, ...) F ## N
+
+/* cast = _EVENT_LOG for no casting
+ * cast = _EVENT_LOG_CAST for casting of fmt arguments to uint32.
+ *        Only first 4 arguments are casted to uint32. event_logn() is called
+ *        if more than 4 arguments are present. This function internally assumes
+ *        all arguments are uint32
+ */
+#define _EVENT_LOG(cast, tag, fmt, ...)					\
+	static char logstr[] __attribute__ ((section(".logstrs"))) = fmt; \
+	static uint32 fmtnum __attribute__ ((section(".lognums"))) = (uint32) &logstr; \
+	_EVENT_LOG_VA_NUM_ARGS(cast, ##__VA_ARGS__,			\
+			       F, E, D, C, B, A, 9, 8,			\
+			       7, 6, 5, 4, 3, 2, 1, 0)			\
+	(tag, (int) &fmtnum , ## __VA_ARGS__)
+
+
+#define EVENT_LOG_FAST(tag, fmt, ...)					\
+	do {								\
+		if (event_log_tag_sets != NULL) {			\
+			uint8 tag_flag = *(event_log_tag_sets + tag);	\
+			if ((tag_flag & ~EVENT_LOG_TAG_FLAG_SET_MASK) != 0) {		\
+				_EVENT_LOG(_EVENT_LOG, tag, fmt , ## __VA_ARGS__);	\
+			}						\
+		}							\
+	} while (0)
+
+#define EVENT_LOG_COMPACT(tag, fmt, ...)				\
+	do {								\
+		_EVENT_LOG(_EVENT_LOG, tag, fmt , ## __VA_ARGS__);	\
+	} while (0)
+
+/* Event log macro with casting to uint32 of arguments */
+#define EVENT_LOG_FAST_CAST(tag, fmt, ...)				\
+	do {								\
+		if (event_log_tag_sets != NULL) {			\
+			uint8 tag_flag = *(event_log_tag_sets + tag);	\
+			if ((tag_flag & ~EVENT_LOG_TAG_FLAG_SET_MASK) != 0) {		\
+				_EVENT_LOG(_EVENT_LOG_CAST, tag, fmt , ## __VA_ARGS__);	\
+			}						\
+		}							\
+	} while (0)
+
+#define EVENT_LOG_COMPACT_CAST(tag, fmt, ...)				\
+	do {								\
+		_EVENT_LOG(_EVENT_LOG_CAST, tag, fmt , ## __VA_ARGS__);	\
+	} while (0)
+
+
+#define EVENT_LOG(tag, fmt, ...) EVENT_LOG_COMPACT(tag, fmt , ## __VA_ARGS__)
+
+#define EVENT_LOG_CAST(tag, fmt, ...) EVENT_LOG_COMPACT_CAST(tag, fmt , ## __VA_ARGS__)
+
+#define _EVENT_LOG_REMOVE_PAREN(...) __VA_ARGS__
+#define EVENT_LOG_REMOVE_PAREN(args) _EVENT_LOG_REMOVE_PAREN args
+
+#define EVENT_LOG_CAST_PAREN_ARGS(tag, pargs)				\
+		EVENT_LOG_CAST(tag, EVENT_LOG_REMOVE_PAREN(pargs))
+
+#define EVENT_LOG_FAST_CAST_PAREN_ARGS(tag, pargs)			\
+		EVENT_LOG_FAST_CAST(tag, EVENT_LOG_REMOVE_PAREN(pargs))
+
+#define EVENT_LOG_COMPACT_CAST_PAREN_ARGS(tag, pargs)			\
+		EVENT_LOG_COMPACT_CAST(tag, EVENT_LOG_REMOVE_PAREN(pargs))
+
+/* Minimal event logging. Event log internally calls event_logx()
+ * log return address in caller.
+ * Note that the if(0){..} below is to avoid compiler warnings
+ * due to unused variables caused by this macro
+ */
+#define EVENT_LOG_RA(tag, args)						\
+	do {								\
+		if (0) {						\
+			EVENT_LOG_COMPACT_CAST_PAREN_ARGS(tag, args);	\
+		}							\
+		event_log_caller_return_address(tag);			\
+	} while (0)
+
+#define EVENT_LOG_IS_ON(tag) (*(event_log_tag_sets + (tag)) & ~EVENT_LOG_TAG_FLAG_SET_MASK)
+#define EVENT_LOG_IS_LOG_ON(tag) (*(event_log_tag_sets + (tag)) & EVENT_LOG_TAG_FLAG_LOG)
+
+#define EVENT_LOG_BUFFER(tag, buf, size)	event_log_buffer(tag, buf, size)
+#define EVENT_DUMP	event_log_buffer
+
+extern uint8 *event_log_tag_sets;
+
+extern int event_log_init(osl_t *osh);
+extern int event_log_set_init(osl_t *osh, int set_num, int size);
+extern int event_log_set_expand(osl_t *osh, int set_num, int size);
+extern int event_log_set_shrink(osl_t *osh, int set_num, int size);
+
+extern int event_log_tag_start(int tag, int set_num, int flags);
+extern int event_log_tag_stop(int tag);
+
+typedef void (*event_log_logtrace_trigger_fn_t)(void *ctx);
+void event_log_set_logtrace_trigger_fn(event_log_logtrace_trigger_fn_t fn, void *ctx);
+
+event_log_top_t *event_log_get_top(void);
+
+extern int event_log_get(int set_num, int buflen, void *buf);
+
+extern uint8 *event_log_next_logtrace(int set_num);
+
+extern void event_log0(int tag, int fmtNum);
+extern void event_log1(int tag, int fmtNum, uint32 t1);
+extern void event_log2(int tag, int fmtNum, uint32 t1, uint32 t2);
+extern void event_log3(int tag, int fmtNum, uint32 t1, uint32 t2, uint32 t3);
+extern void event_log4(int tag, int fmtNum, uint32 t1, uint32 t2, uint32 t3, uint32 t4);
+extern void event_logn(int num_args, int tag, int fmtNum, ...);
+
+extern void event_log_time_sync(uint32 ms);
+extern void event_log_buffer(int tag, uint8 *buf, int size);
+extern void event_log_caller_return_address(int tag);
+extern int event_log_set_destination_set(int set, event_log_set_destination_t dest);
+extern event_log_set_destination_t event_log_set_destination_get(int set);
+extern int event_log_flush_log_buffer(int set);
+extern bool event_log_is_ready(void);
+
+#endif /* EVENT_LOG_DUMPER */
+
+#endif /* EVENT_LOG_COMPILE */
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* _EVENT_LOG_H_ */
diff --git a/wl/src/include/miniopt.h b/wl/src/include/miniopt.h
new file mode 100644
index 0000000..80ab967
--- /dev/null
+++ b/wl/src/include/miniopt.h
@@ -0,0 +1,80 @@
+/*
+ * Command line options parser.
+ *
+ * Copyright (C) 2017, Broadcom. 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: miniopt.h 514727 2014-11-12 03:02:48Z $
+ */
+
+
+#ifndef MINI_OPT_H
+#define MINI_OPT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ---- Include Files ---------------------------------------------------- */
+
+#if defined(__FreeBSD__)
+#include <stdbool.h>
+#endif
+
+/* ---- Constants and Types ---------------------------------------------- */
+
+#define MINIOPT_MAXKEY	128	/* Max options */
+typedef struct miniopt {
+
+	/* These are persistent after miniopt_init() */
+	const char* name;		/* name for prompt in error strings */
+	const char* flags;		/* option chars that take no args */
+	bool longflags;		/* long options may be flags */
+	bool opt_end;		/* at end of options (passed a "--") */
+
+	/* These are per-call to miniopt() */
+
+	int consumed;		/* number of argv entries cosumed in
+				 * the most recent call to miniopt()
+				 */
+	bool positional;
+	bool good_int;		/* 'val' member is the result of a sucessful
+				 * strtol conversion of the option value
+				 */
+	char opt;
+	char key[MINIOPT_MAXKEY];
+	char* valstr;		/* positional param, or value for the option,
+				 * or null if the option had
+				 * no accompanying value
+				 */
+	uint uval;		/* strtol translation of valstr */
+	int  val;		/* strtol translation of valstr */
+} miniopt_t;
+
+void miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags);
+int miniopt(miniopt_t *t, char **argv);
+
+
+/* ---- Variable Externs ------------------------------------------------- */
+/* ---- Function Prototypes ---------------------------------------------- */
+
+
+#ifdef __cplusplus
+	}
+#endif
+
+#endif  /* MINI_OPT_H  */
diff --git a/wl/src/include/osl_decl.h b/wl/src/include/osl_decl.h
new file mode 100644
index 0000000..7ad7261
--- /dev/null
+++ b/wl/src/include/osl_decl.h
@@ -0,0 +1,31 @@
+/*
+ * osl forward declarations
+ *
+ * Copyright (C) 2017, Broadcom. 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: osl_decl.h 596126 2015-10-29 19:53:48Z $
+ */
+
+#ifndef _osl_decl_h_
+#define _osl_decl_h_
+
+/* osl handle type forward declaration */
+typedef struct osl_info osl_t;
+typedef struct osl_dmainfo osldma_t;
+extern unsigned int lmtest; /* low memory test */
+#endif
diff --git a/wl/src/include/packed_section_end.h b/wl/src/include/packed_section_end.h
new file mode 100644
index 0000000..5c4e772
--- /dev/null
+++ b/wl/src/include/packed_section_end.h
@@ -0,0 +1,59 @@
+/*
+ * 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) 2017, Broadcom. 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: packed_section_end.h 660496 2016-09-20 19:28:50Z $
+ */
+
+
+/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h
+ * and undefined in packed_section_end.h. If it is NOT defined at this
+ * point, then there is a missing include of packed_section_start.h.
+ */
+#ifdef BWL_PACKED_SECTION
+	#undef BWL_PACKED_SECTION
+#else
+	#error "BWL_PACKED_SECTION is NOT defined!"
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning(disable:4103)
+#pragma pack(pop)
+#endif
+
+/* Compiler-specific directives for structure packing are declared in
+ * packed_section_start.h. This marks the end of the structure packing section,
+ * so, undef them here.
+ */
+#undef	BWL_PRE_PACKED_STRUCT
+#undef	BWL_POST_PACKED_STRUCT
diff --git a/wl/src/include/packed_section_start.h b/wl/src/include/packed_section_start.h
new file mode 100644
index 0000000..da805bd
--- /dev/null
+++ b/wl/src/include/packed_section_start.h
@@ -0,0 +1,109 @@
+/*
+ * 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) 2017, Broadcom. 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: packed_section_start.h 660529 2016-09-20 23:01:03Z $
+ */
+
+
+#ifndef _alignment_test_
+#define _alignment_test_
+
+/* ASSERT default packing */
+typedef struct T4 {
+	uint8  a;
+	uint32 b;
+	uint16 c;
+	uint8  d;
+} T4_t;
+
+/* 4 byte alignment support */
+/*
+* a . . .
+* b b b b
+* c c d .
+*/
+
+/*
+ * Below function is meant to verify that this file is compiled with the default alignment of 4.
+ * Function will fail to compile if the condition is not met.
+ */
+#ifdef __GNUC__
+#define VARIABLE_IS_NOT_USED __attribute__ ((unused))
+#else
+#define VARIABLE_IS_NOT_USED
+#endif
+static void alignment_test(void);
+static void
+VARIABLE_IS_NOT_USED alignment_test(void)
+{
+	/* verify 4 byte alignment support */
+	STATIC_ASSERT(sizeof(T4_t) == 12);
+}
+#endif /* _alignment_test_ */
+
+
+/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h
+ * and undefined in packed_section_end.h. If it is already defined at this
+ * point, then there is a missing include of packed_section_end.h.
+ */
+#ifdef BWL_PACKED_SECTION
+	#error "BWL_PACKED_SECTION is already defined!"
+#else
+	#define BWL_PACKED_SECTION
+#endif
+
+#if defined(BWL_DEFAULT_PACKING)
+	/* generate an error if BWL_DEFAULT_PACKING is defined */
+	#error "BWL_DEFAULT_PACKING not supported any more."
+#endif /* BWL_PACKED_SECTION */
+
+#if defined(_MSC_VER)
+#pragma warning(disable:4103)
+#pragma pack(push)
+#pragma pack(1)
+#endif
+
+/* Declare compiler-specific directives for structure packing. */
+#if defined(_MSC_VER)
+	#define	BWL_PRE_PACKED_STRUCT
+	#define	BWL_POST_PACKED_STRUCT
+#elif 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/wl/src/include/rte_ioctl.h b/wl/src/include/rte_ioctl.h
new file mode 100644
index 0000000..bb9023e
--- /dev/null
+++ b/wl/src/include/rte_ioctl.h
@@ -0,0 +1,87 @@
+/*
+ * HND Run Time Environment ioctl.
+ *
+ * Copyright (C) 2017, Broadcom. 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: rte_ioctl.h 637908 2016-05-16 06:59:09Z $
+ */
+
+#ifndef _rte_ioctl_h_
+#define _rte_ioctl_h_
+
+/* RTE IOCTL definitions for generic ether devices */
+#define RTEGHWADDR		0x8901
+#define RTESHWADDR		0x8902
+#define RTEGMTU			0x8903
+#define RTEGSTATS		0x8904
+#define RTEGALLMULTI		0x8905
+#define RTESALLMULTI		0x8906
+#define RTEGPROMISC		0x8907
+#define RTESPROMISC		0x8908
+#define RTESMULTILIST	0x8909
+#define RTEGUP			0x890A
+#define RTEGPERMADDR		0x890B
+#define RTEDEVPWRSTCHG		0x890C	/* Device pwr state change for PCIedev */
+#define RTEDEVPMETOGGLE		0x890D	/* Toggle PME# to wake up the host */
+#define RTEDEVTIMESYNC		0x890E	/* Device TimeSync */
+#define RTEDEVDSNOTIFY		0x890F	/* Bus DS state notification */
+
+#define RTE_IOCTL_QUERY			0x00
+#define RTE_IOCTL_SET			0x01
+#define RTE_IOCTL_OVL_IDX_MASK	0x1e
+#define RTE_IOCTL_OVL_RSV		0x20
+#define RTE_IOCTL_OVL			0x40
+#define RTE_IOCTL_OVL_IDX_SHIFT	1
+
+enum hnd_ioctl_cmd {
+	HND_RTE_DNGL_IS_SS = 1, /* true if device connected at super speed */
+
+	/* PCIEDEV specific wl <--> bus ioctls */
+	BUS_GET_VAR = 2,
+	BUS_SET_VAR = 3,
+	BUS_FLUSH_RXREORDER_Q = 4,
+	BUS_SET_LTR_STATE = 5,
+	BUS_FLUSH_CHAINED_PKTS = 6,
+	BUS_SET_COPY_COUNT = 7,
+	BUS_UPDATE_FLOW_PKTS_MAX = 8,
+	BUS_UPDATE_EXTRA_TXLFRAGS = 9,
+	BUS_UPDATE_FRWD_RESRV_BUFCNT = 10
+};
+
+#define SDPCMDEV_SET_MAXTXPKTGLOM	1
+#define RTE_MEMUSEINFO_VER 0x00
+
+typedef struct memuse_info {
+	uint16 ver;			/* version of this struct */
+	uint16 len;			/* length in bytes of this structure */
+	uint32 tot;			/* Total memory */
+	uint32 text_len;	/* Size of Text segment memory */
+	uint32 data_len;	/* Size of Data segment memory */
+	uint32 bss_len;		/* Size of BSS segment memory */
+
+	uint32 arena_size;	/* Total Heap size */
+	uint32 arena_free;	/* Heap memory available or free */
+	uint32 inuse_size;	/* Heap memory currently in use */
+	uint32 inuse_hwm;	/* High watermark of memory - reclaimed memory */
+	uint32 inuse_overhead;	/* tally of allocated mem_t blocks */
+	uint32 inuse_total;	/* Heap in-use + Heap overhead memory  */
+	uint32 free_lwm;        /* Least free size since reclaim */
+	uint32 mf_count;        /* Malloc failure count */
+} memuse_info_t;
+
+#endif /* _rte_ioctl_h_ */
diff --git a/wl/src/include/rwl_wifi.h b/wl/src/include/rwl_wifi.h
new file mode 100644
index 0000000..1e3f050
--- /dev/null
+++ b/wl/src/include/rwl_wifi.h
@@ -0,0 +1,98 @@
+/*
+ * RWL definitions  of
+ * Broadcom 802.11bang Networking Device Driver
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: rwl_wifi.h 524641 2015-01-07 15:25:03Z $
+ *
+ */
+
+#ifndef _rwl_wifi_h_
+#define _rwl_wifi_h_
+
+#if defined(RWL_WIFI) || defined(WIFI_REFLECTOR) || defined(RFAWARE)
+
+#define RWL_ACTION_WIFI_CATEGORY	127  /* Vendor-specific category value for WiFi */
+#define RWL_WIFI_OUI_BYTE0		0x00 /* BRCM-specific public OUI */
+#define RWL_WIFI_OUI_BYTE1		0x90
+#define RWL_WIFI_OUI_BYTE2		0x4c
+#define RWL_WIFI_ACTION_FRAME_SIZE	sizeof(struct dot11_action_wifi_vendor_specific)
+
+/*
+ * Information about the action frame data fields in the dot11_action_wifi_vendor_specific
+ * cdc structure (1 to 16). This does not include the status flag. Since this
+ * is not directly visible to the driver code, we can't use sizeof(struct cdc_ioctl).
+ * Hence Ref MAC address offset starts from byte 17.
+ * REF MAC ADDR (6 bytes (MAC Address len) from byte 17 to 22)
+ * DUT MAC ADDR (6 bytes after the REF MAC Address byte 23 to 28)
+ * unused (byte 29 to 49)
+ * REF/Client Channel offset (50)
+ * DUT/Server channel offset (51)
+ * ---------------------------------------------------------------------------------------
+ * cdc struct|REF MAC ADDR|DUT_MAC_ADDR|un used|REF Channel|DUT channel|Action frame Data|
+ * 1---------17-----------23-------------------50----------51----------52----------------1040
+ * REF MAC addr after CDC struct without status flag (status flag not used by wifi)
+ */
+
+#define RWL_REF_MAC_ADDRESS_OFFSET	17
+#define RWL_DUT_MAC_ADDRESS_OFFSET	23
+#define RWL_WIFI_CLIENT_CHANNEL_OFFSET	50
+#define RWL_WIFI_SERVER_CHANNEL_OFFSET	51
+
+#ifdef WIFI_REFLECTOR
+#include <bcmcdc.h>
+#define REMOTE_FINDSERVER_CMD 	16
+#define RWL_WIFI_ACTION_CMD		"wifiaction"
+#define RWL_WIFI_ACTION_CMD_LEN		11	/* With the NULL terminator */
+#define REMOTE_SET_CMD 		1
+#define REMOTE_GET_CMD 		2
+#define REMOTE_REPLY 			4
+#define RWL_WIFI_DEFAULT_TYPE           0x00
+#define RWL_WIFI_DEFAULT_SUBTYPE        0x00
+#define RWL_ACTION_FRAME_DATA_SIZE      1024	/* fixed size for the wifi frame data */
+#define RWL_WIFI_CDC_HEADER_OFFSET      0
+#define RWL_WIFI_FRAG_DATA_SIZE         960	/* max size of the frag data */
+#define RWL_DEFAULT_WIFI_FRAG_COUNT 	127 	/* maximum fragment count */
+#define RWL_WIFI_RETRY			5       /* CMD retry count for wifi */
+#define RWL_WIFI_SEND			5	/* WIFI frame sent count */
+#define RWL_WIFI_SEND_DELAY		100	/* delay between two frames */
+#define MICROSEC_CONVERTOR_VAL		1000
+#ifndef IFNAMSIZ
+#define IFNAMSIZ			16
+#endif
+
+typedef struct rem_packet {
+	rem_ioctl_t rem_cdc;
+	uchar message [RWL_ACTION_FRAME_DATA_SIZE];
+} rem_packet_t;
+
+#include <packed_section_start.h>
+struct BWL_PRE_PACKED_STRUCT send_packet {
+	char command [RWL_WIFI_ACTION_CMD_LEN];
+	dot11_action_wifi_vendor_specific_t response;
+} BWL_POST_PACKED_STRUCT;
+#include <packed_section_end.h>
+
+typedef struct send_packet send_packet_t;
+
+#define REMOTE_SIZE     sizeof(rem_ioctl_t)
+#endif /* WIFI_REFLECTOR */
+
+typedef struct rwl_request {
+	struct rwl_request* next_request;
+	struct dot11_action_wifi_vendor_specific action_frame;
+} rwl_request_t;
+
+
+#endif 
+#endif	/* _rwl_wifi_h_ */
diff --git a/wl/src/include/sbpcmcia.h b/wl/src/include/sbpcmcia.h
new file mode 100644
index 0000000..a9a6484
--- /dev/null
+++ b/wl/src/include/sbpcmcia.h
@@ -0,0 +1,417 @@
+/*
+ * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions.
+ *
+ * Copyright (C) 2017, Broadcom. 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: sbpcmcia.h 647676 2016-07-07 02:59:05Z $
+ */
+
+#ifndef	_SBPCMCIA_H
+#define	_SBPCMCIA_H
+
+/* All the addresses that are offsets in attribute space are divided
+ * by two to account for the fact that odd bytes are invalid in
+ * attribute space and our read/write routines make the space appear
+ * as if they didn't exist. Still we want to show the original numbers
+ * as documented in the hnd_pcmcia core manual.
+ */
+
+/* PCMCIA Function Configuration Registers */
+#define	PCMCIA_FCR		(0x700 / 2)
+
+#define	FCR0_OFF		0
+#define	FCR1_OFF		(0x40 / 2)
+#define	FCR2_OFF		(0x80 / 2)
+#define	FCR3_OFF		(0xc0 / 2)
+
+#define	PCMCIA_FCR0		(0x700 / 2)
+#define	PCMCIA_FCR1		(0x740 / 2)
+#define	PCMCIA_FCR2		(0x780 / 2)
+#define	PCMCIA_FCR3		(0x7c0 / 2)
+
+/* Standard PCMCIA FCR registers */
+
+#define	PCMCIA_COR		0
+
+#define	COR_RST			0x80
+#define	COR_LEV			0x40
+#define	COR_IRQEN		0x04
+#define	COR_BLREN		0x01
+#define	COR_FUNEN		0x01
+
+
+#define	PCICIA_FCSR		(2 / 2)
+#define	PCICIA_PRR		(4 / 2)
+#define	PCICIA_SCR		(6 / 2)
+#define	PCICIA_ESR		(8 / 2)
+
+
+#define PCM_MEMOFF		0x0000
+#define F0_MEMOFF		0x1000
+#define F1_MEMOFF		0x2000
+#define F2_MEMOFF		0x3000
+#define F3_MEMOFF		0x4000
+
+/* Memory base in the function fcr's */
+#define MEM_ADDR0		(0x728 / 2)
+#define MEM_ADDR1		(0x72a / 2)
+#define MEM_ADDR2		(0x72c / 2)
+
+/* PCMCIA base plus Srom access in fcr0: */
+#define PCMCIA_ADDR0		(0x072e / 2)
+#define PCMCIA_ADDR1		(0x0730 / 2)
+#define PCMCIA_ADDR2		(0x0732 / 2)
+
+#define MEM_SEG			(0x0734 / 2)
+#define SROM_CS			(0x0736 / 2)
+#define SROM_DATAL		(0x0738 / 2)
+#define SROM_DATAH		(0x073a / 2)
+#define SROM_ADDRL		(0x073c / 2)
+#define SROM_ADDRH		(0x073e / 2)
+#define	SROM_INFO2		(0x0772 / 2)	/* Corerev >= 2 && <= 5 */
+#define	SROM_INFO		(0x07be / 2)	/* Corerev >= 6 */
+
+/*  Values for srom_cs: */
+#define SROM_IDLE		0
+#define SROM_WRITE		1
+#define SROM_READ		2
+#define SROM_WEN		4
+#define SROM_WDS		7
+#define SROM_DONE		8
+
+/* Fields in srom_info: */
+#define	SRI_SZ_MASK		0x03
+#define	SRI_BLANK		0x04
+#define	SRI_OTP			0x80
+
+
+#define SROM16K_BANK_SEL_MASK		(3 << 11)
+#define SROM16K_BANK_SHFT_MASK		11
+#define SROM16K_ADDR_SEL_MASK	((1 << SROM16K_BANK_SHFT_MASK) - 1)
+#define SROM_PRSNT_MASK		0x1
+#define SROM_SUPPORT_SHIFT_MASK 30
+#define SROM_SUPPORTED	(0x1 << SROM_SUPPORT_SHIFT_MASK)
+#define SROM_SIZE_MASK    0x00000006
+#define SROM_SIZE_2K	2
+#define SROM_SIZE_512	1
+#define SROM_SIZE_128	0
+#define SROM_SIZE_SHFT_MASK  1
+
+#if !defined(LINUX_POSTMOGRIFY_REMOVAL)
+/* CIS stuff */
+
+/* The CIS stops where the FCRs start */
+#define	CIS_SIZE		PCMCIA_FCR
+#define CIS_SIZE_12K    1154    /* Maximum h/w + s/w sub region size for 12k OTP */
+
+/* CIS tuple length field max */
+#define CIS_TUPLE_LEN_MAX	0xff
+#endif /* !defined(LINUX_POSTMOGRIFY_REMOVAL) */
+
+/* Standard tuples we know about */
+
+#define CISTPL_NULL		0x00
+#define	CISTPL_END		0xff		/* End of the CIS tuple chain */
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define	CISTPL_VERS_1		0x15		/* CIS ver, manf, dev & ver strings */
+#define	CISTPL_MANFID		0x20		/* Manufacturer and device id */
+#define CISTPL_FUNCID		0x21		/* Function identification */
+#define	CISTPL_FUNCE		0x22		/* Function extensions */
+#define	CISTPL_CFTABLE		0x1b		/* Config table entry */
+
+/* Function identifier provides context for the function extentions tuple */
+#define CISTPL_FID_SDIO		0x0c		/* Extensions defined by SDIO spec */
+
+/* Function extensions for LANs (assumed for extensions other than SDIO) */
+#define	LAN_TECH		1		/* Technology type */
+#define	LAN_SPEED		2		/* Raw bit rate */
+#define	LAN_MEDIA		3		/* Transmission media */
+#define	LAN_NID			4		/* Node identification (aka MAC addr) */
+#define	LAN_CONN		5		/* Connector standard */
+
+
+/* CFTable */
+#define CFTABLE_REGWIN_2K	0x08		/* 2k reg windows size */
+#define CFTABLE_REGWIN_4K	0x10		/* 4k reg windows size */
+#define CFTABLE_REGWIN_8K	0x20		/* 8k reg windows size */
+
+/* Vendor unique tuples are 0x80-0x8f. Within Broadcom we'll
+ * take one for HNBU, and use "extensions" (a la FUNCE) within it.
+ */
+#endif /* !defined(LINUX_POSTMOGRIFY_REMOVAL) */
+
+#define	CISTPL_BRCM_HNBU	0x80
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+/* Subtypes of BRCM_HNBU: */
+
+#define HNBU_SROMREV		0x00	/* A byte with sromrev, 1 if not present */
+#define HNBU_CHIPID		0x01	/* Two 16bit values: PCI vendor & device id */
+#endif /* !defined(LINUX_POSTMOGRIFY_REMOVAL) */
+
+#define HNBU_BOARDREV		0x02	/* One byte board revision */
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define HNBU_PAPARMS		0x03	/* PA parameters: 8 (sromrev == 1)
+					 * or 9 (sromrev > 1) bytes
+					 */
+#define HNBU_OEM		0x04	/* Eight bytes OEM data (sromrev == 1) */
+#define HNBU_CC			0x05	/* Default country code (sromrev == 1) */
+#define	HNBU_AA			0x06	/* Antennas available */
+#define	HNBU_AG			0x07	/* Antenna gain */
+#define HNBU_BOARDFLAGS		0x08	/* board flags (2 or 4 bytes) */
+#define HNBU_LEDS		0x09	/* LED set */
+#define HNBU_CCODE		0x0a	/* Country code (2 bytes ascii + 1 byte cctl)
+					 * in rev 2
+					 */
+#define HNBU_CCKPO		0x0b	/* 2 byte cck power offsets in rev 3 */
+#define HNBU_OFDMPO		0x0c	/* 4 byte 11g ofdm power offsets in rev 3 */
+#define HNBU_GPIOTIMER		0x0d	/* 2 bytes with on/off values in rev 3 */
+#define HNBU_PAPARMS5G		0x0e	/* 5G PA params */
+#define HNBU_ANT5G		0x0f	/* 4328 5G antennas available/gain */
+#define HNBU_RDLID		0x10	/* 2 byte USB remote downloader (RDL) product Id */
+#define HNBU_RSSISMBXA2G	0x11	/* 4328 2G RSSI mid pt sel & board switch arch,
+					 * 2 bytes, rev 3.
+					 */
+#define HNBU_RSSISMBXA5G	0x12	/* 4328 5G RSSI mid pt sel & board switch arch,
+					 * 2 bytes, rev 3.
+					 */
+#define HNBU_XTALFREQ		0x13	/* 4 byte Crystal frequency in kilohertz */
+#define HNBU_TRI2G		0x14	/* 4328 2G TR isolation, 1 byte */
+#define HNBU_TRI5G		0x15	/* 4328 5G TR isolation, 3 bytes */
+#define HNBU_RXPO2G		0x16	/* 4328 2G RX power offset, 1 byte */
+#define HNBU_RXPO5G		0x17	/* 4328 5G RX power offset, 1 byte */
+#define HNBU_BOARDNUM		0x18	/* board serial number, independent of mac addr */
+#define HNBU_MACADDR		0x19	/* mac addr override for the standard CIS LAN_NID */
+#define HNBU_RDLSN		0x1a	/* 2 bytes; serial # advertised in USB descriptor */
+#endif /* !defined(LINUX_POSTMOGRIFY_REMOVAL) */
+
+#define HNBU_BOARDTYPE		0x1b	/* 2 bytes; boardtype */
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define HNBU_LEDDC		0x1c	/* 2 bytes; LED duty cycle */
+#endif /* !defined(LINUX_POSTMOGRIFY_REMOVAL) */
+
+#define HNBU_HNBUCIS		0x1d	/* what follows is proprietary HNBU CIS format */
+
+#ifndef LINUX_POSTMOGRIFY_REMOVAL
+#define HNBU_PAPARMS_SSLPNPHY	0x1e	/* SSLPNPHY PA params */
+#define HNBU_RSSISMBXA2G_SSLPNPHY 0x1f /* SSLPNPHY RSSI mid pt sel & board switch arch */
+#define HNBU_RDLRNDIS		0x20	/* 1 byte; 1 = RDL advertises RNDIS config */
+#define HNBU_CHAINSWITCH	0x21	/* 2 byte; txchain, rxchain */
+#define HNBU_REGREV		0x22	/* 1 byte; */
+#define HNBU_FEM		0x23	/* 2 or 4 byte: 11n frontend specification */
+#define HNBU_PAPARMS_C0		0x24	/* 8 or 30 bytes: 11n pa paramater for chain 0 */
+#define HNBU_PAPARMS_C1		0x25	/* 8 or 30 bytes: 11n pa paramater for chain 1 */
+#define HNBU_PAPARMS_C2		0x26	/* 8 or 30 bytes: 11n pa paramater for chain 2 */
+#define HNBU_PAPARMS_C3		0x27	/* 8 or 30 bytes: 11n pa paramater for chain 3 */
+#define HNBU_PO_CCKOFDM		0x28	/* 6 or 18 bytes: cck2g/ofdm2g/ofdm5g power offset */
+#define HNBU_PO_MCS2G		0x29	/* 8 bytes: mcs2g power offset */
+#define HNBU_PO_MCS5GM		0x2a	/* 8 bytes: mcs5g mid band power offset */
+#define HNBU_PO_MCS5GLH		0x2b	/* 16 bytes: mcs5g low-high band power offset */
+#define HNBU_PO_CDD		0x2c	/* 2 bytes: cdd2g/5g power offset */
+#define HNBU_PO_STBC		0x2d	/* 2 bytes: stbc2g/5g power offset */
+#define HNBU_PO_40M		0x2e	/* 2 bytes: 40Mhz channel 2g/5g power offset */
+#define HNBU_PO_40MDUP		0x2f	/* 2 bytes: 40Mhz channel dup 2g/5g power offset */
+
+#define HNBU_RDLRWU		0x30	/* 1 byte; 1 = RDL advertises Remote Wake-up */
+#define HNBU_WPS		0x31	/* 1 byte; GPIO pin for WPS button */
+#define HNBU_USBFS		0x32	/* 1 byte; 1 = USB advertises FS mode only */
+#define HNBU_BRMIN		0x33	/* 4 byte bootloader min resource mask */
+#define HNBU_BRMAX		0x34	/* 4 byte bootloader max resource mask */
+#define HNBU_PATCH		0x35	/* bootloader patch addr(2b) & data(4b) pair */
+#define HNBU_CCKFILTTYPE	0x36	/* CCK digital filter selection options */
+#define HNBU_OFDMPO5G		0x37	/* 4 * 3 = 12 byte 11a ofdm power offsets in rev 3 */
+#define HNBU_ELNA2G             0x38
+#define HNBU_ELNA5G             0x39
+#define HNBU_TEMPTHRESH 0x3A /* 2 bytes
+					 * byte1 tempthresh
+					 * byte2 period(msb 4 bits) | hysterisis(lsb 4 bits)
+					 */
+#define HNBU_UUID 0x3B /* 16 Bytes Hex */
+
+#define HNBU_USBEPNUM		0x40	/* USB endpoint numbers */
+
+/* POWER PER RATE for SROM V9 */
+#define HNBU_CCKBW202GPO       0x41    /* 2 bytes each
+					 * CCK Power offsets for 20 MHz rates (11, 5.5, 2, 1Mbps)
+					 * cckbw202gpo cckbw20ul2gpo
+					 */
+
+#define HNBU_LEGOFDMBW202GPO    0x42    /* 4 bytes each
+					 * OFDM power offsets for 20 MHz Legacy rates
+					 * (54, 48, 36, 24, 18, 12, 9, 6 Mbps)
+					 * legofdmbw202gpo  legofdmbw20ul2gpo
+					 */
+
+#define HNBU_LEGOFDMBW205GPO   0x43    /* 4 bytes each
+					* 5G band: OFDM power offsets for 20 MHz Legacy rates
+					* (54, 48, 36, 24, 18, 12, 9, 6 Mbps)
+					* low subband : legofdmbw205glpo  legofdmbw20ul2glpo
+					* mid subband :legofdmbw205gmpo  legofdmbw20ul2gmpo
+					* high subband :legofdmbw205ghpo  legofdmbw20ul2ghpo
+					*/
+
+#define HNBU_MCS2GPO    0x44    /* 4 bytes each
+				     * mcs 0-7  power-offset. LSB nibble: m0, MSB nibble: m7
+				     * mcsbw202gpo  mcsbw20ul2gpo mcsbw402gpo
+				     */
+#define HNBU_MCS5GLPO    0x45    /* 4 bytes each
+				     * 5G low subband mcs 0-7 power-offset.
+				     * LSB nibble: m0, MSB nibble: m7
+				     * mcsbw205glpo  mcsbw20ul5glpo mcsbw405glpo
+				     */
+#define HNBU_MCS5GMPO    0x46    /* 4 bytes each
+				     * 5G mid subband mcs 0-7 power-offset.
+				     * LSB nibble: m0, MSB nibble: m7
+				     * mcsbw205gmpo  mcsbw20ul5gmpo mcsbw405gmpo
+				     */
+#define HNBU_MCS5GHPO    0x47    /* 4 bytes each
+				     * 5G high subband mcs 0-7 power-offset.
+				     * LSB nibble: m0, MSB nibble: m7
+				     * mcsbw205ghpo  mcsbw20ul5ghpo mcsbw405ghpo
+				     */
+#define HNBU_MCS32PO	0x48	/*  2 bytes total
+				 * mcs-32 power offset for each band/subband.
+				 * LSB nibble: 2G band, MSB nibble:
+				 * mcs322ghpo, mcs325gmpo, mcs325glpo, mcs322gpo
+				 */
+#define HNBU_LEG40DUPPO	0x49 /*  2 bytes total
+				* Additional power offset for Legacy Dup40 transmissions.
+				 * Applied in addition to legofdmbw20ulXpo, X=2g, 5gl, 5gm, or 5gh.
+				 * LSB nibble: 2G band, MSB nibble: 5G band high subband.
+				 * leg40dup5ghpo, leg40dup5gmpo, leg40dup5glpo, leg40dup2gpo
+				 */
+
+#define HNBU_PMUREGS	0x4a /* Variable length (5 bytes for each register)
+				* The setting of the ChipCtrl, PLL, RegulatorCtrl, Up/Down Timer and
+				* ResourceDependency Table registers.
+				*/
+
+#define HNBU_PATCH2		0x4b	/* bootloader TCAM patch addr(4b) & data(4b) pair .
+				* This is required for socram rev 15 onwards.
+				*/
+
+#define HNBU_USBRDY		0x4c	/* Variable length (upto 5 bytes)
+				* This is to indicate the USB/HSIC host controller
+				* that the device is ready for enumeration.
+				*/
+
+#define HNBU_USBREGS	0x4d	/* Variable length
+				* The setting of the devcontrol, HSICPhyCtrl1 and HSICPhyCtrl2
+				* registers during the USB initialization.
+				*/
+
+#define HNBU_BLDR_TIMEOUT	0x4e	/* 2 bytes used for HSIC bootloader to reset chip
+				* on connect timeout.
+				* The Delay after USBConnect for timeout till dongle receives
+				* get_descriptor request.
+				*/
+#define HNBU_USBFLAGS		0x4f
+#define HNBU_PATCH_AUTOINC	0x50
+#define HNBU_MDIO_REGLIST	0x51
+#define HNBU_MDIOEX_REGLIST	0x52
+/* Unified OTP: tupple to embed USB manfid inside SDIO CIS */
+#define HNBU_UMANFID		0x53
+#define HNBU_PUBKEY		0x54	/* 128 byte; publick key to validate downloaded FW */
+#define HNBU_WOWLGPIO       0x55   /* 1 byte bit 7 initial polarity, bit 6..0 gpio pin */
+#define HNBU_MUXENAB		0x56	/* 1 byte to enable mux options */
+#define HNBU_GCI_CCR		0x57	/* GCI Chip control register */
+
+#define HNBU_FEM_CFG		0x58	/* FEM config */
+#define HNBU_ACPA_C0		0x59	/* ACPHY PA parameters: chain 0 */
+#define HNBU_ACPA_C1		0x5a	/* ACPHY PA parameters: chain 1 */
+#define HNBU_ACPA_C2		0x5b	/* ACPHY PA parameters: chain 2 */
+#define HNBU_MEAS_PWR		0x5c
+#define HNBU_PDOFF		0x5d
+#define HNBU_ACPPR_2GPO		0x5e	/* ACPHY Power-per-rate 2gpo */
+#define HNBU_ACPPR_5GPO		0x5f	/* ACPHY Power-per-rate 5gpo */
+#define HNBU_ACPPR_SBPO		0x60	/* ACPHY Power-per-rate sbpo */
+#define HNBU_NOISELVL		0x61
+#define HNBU_RXGAIN_ERR		0x62
+#define HNBU_AGBGA		0x63
+#define HNBU_USBDESC_COMPOSITE	0x64    /* USB WLAN/BT composite descriptor */
+#define HNBU_PATCH_AUTOINC8	0x65	/* Auto increment patch entry for 8 byte patching */
+#define HNBU_PATCH8		0x66	/* Patch entry for 8 byte patching */
+#define HNBU_ACRXGAINS_C0	0x67	/* ACPHY rxgains: chain 0 */
+#define HNBU_ACRXGAINS_C1	0x68	/* ACPHY rxgains: chain 1 */
+#define HNBU_ACRXGAINS_C2	0x69	/* ACPHY rxgains: chain 2 */
+#define HNBU_TXDUTY		0x6a	/* Tx duty cycle for ACPHY 5g 40/80 Mhz */
+#define HNBU_USBUTMI_CTL        0x6b    /* 2 byte USB UTMI/LDO Control */
+#define HNBU_PDOFF_2G		0x6c
+#define HNBU_USBSSPHY_UTMI_CTL0 0x6d    /* 4 byte USB SSPHY UTMI Control */
+#define HNBU_USBSSPHY_UTMI_CTL1 0x6e    /* 4 byte USB SSPHY UTMI Control */
+#define HNBU_USBSSPHY_UTMI_CTL2 0x6f    /* 4 byte USB SSPHY UTMI Control */
+#define HNBU_USBSSPHY_SLEEP0    0x70    /* 2 byte USB SSPHY sleep */
+#define HNBU_USBSSPHY_SLEEP1    0x71    /* 2 byte USB SSPHY sleep */
+#define HNBU_USBSSPHY_SLEEP2    0x72    /* 2 byte USB SSPHY sleep */
+#define HNBU_USBSSPHY_SLEEP3    0x73    /* 2 byte USB SSPHY sleep */
+#define HNBU_USBSSPHY_MDIO      0x74    /* USB SSPHY INIT regs setting */
+#define HNBU_USB30PHY_NOSS      0x75    /* USB30 NO Super Speed */
+#define HNBU_USB30PHY_U1U2      0x76    /* USB30 PHY U1U2 Enable */
+#define HNBU_USB30PHY_REGS      0x77    /* USB30 PHY REGs update */
+#define HNBU_GPIO_PULL_DOWN     0x78    /* 4 byte GPIO pull down mask */
+
+#define HNBU_SROM3SWRGN		0x80	/* 78 bytes; srom rev 3 s/w region without crc8
+					 * plus extra info appended.
+					 */
+#define HNBU_RESERVED		0x81	/* Reserved for non-BRCM post-mfg additions */
+#define HNBU_CUSTOM1		0x82	/* 4 byte; For non-BRCM post-mfg additions */
+#define HNBU_CUSTOM2		0x83	/* Reserved; For non-BRCM post-mfg additions */
+#define HNBU_ACPAPARAM		0x84	/* ACPHY PAPARAM */
+#define HNBU_ACPA_CCK_C0	0x86	/* ACPHY PA trimming parameters: CCK */
+#define HNBU_ACPA_40		0x87	/* ACPHY PA trimming parameters: 40 */
+#define HNBU_ACPA_80		0x88	/* ACPHY PA trimming parameters: 80 */
+#define HNBU_ACPA_4080		0x89	/* ACPHY PA trimming parameters: 40/80 */
+#define HNBU_SUBBAND5GVER	0x8a	/* subband5gver */
+#define HNBU_PAPARAMBWVER	0x8b	/* paparambwver */
+
+#define HNBU_MCS5Gx1PO		0x8c
+#define HNBU_ACPPR_SB8080_PO		0x8d
+#define HNBU_TXBFRPCALS			0x8f	/* phy txbf rpcalvars */
+#define HNBU_MACADDR2				0x90	/* (optional) 2nd mac-addr for RSDB chips */
+
+#define HNBU_ACPA_4X4C0	0x91
+#define HNBU_ACPA_4X4C1	0x92
+#define HNBU_ACPA_4X4C2	0x93
+#define HNBU_ACPA_4X4C3	0x94
+#define HNBU_ACPA_BW20_4X4C0	0x95
+#define HNBU_ACPA_BW40_4X4C0	0x96
+#define HNBU_ACPA_BW80_4X4C0	0x97
+#define HNBU_ACPA_BW20_4X4C1	0x98
+#define HNBU_ACPA_BW40_4X4C1	0x99
+#define HNBU_ACPA_BW80_4X4C1	0x9a
+#define HNBU_ACPA_BW20_4X4C2	0x9b
+#define HNBU_ACPA_BW40_4X4C2	0x9c
+#define HNBU_ACPA_BW80_4X4C2	0x9d
+#define HNBU_ACPA_BW20_4X4C3	0x9e
+#define HNBU_ACPA_BW40_4X4C3	0x9f
+#define HNBU_ACPA_BW80_4X4C3	0xa0
+#define HNBU_ACPA_CCK_C1	0xa1	/* ACPHY PA trimming parameters: CCK */
+
+
+#endif /* !defined(LINUX_POSTMOGRIFY_REMOVAL) */
+
+/* sbtmstatelow */
+#define SBTML_INT_ACK		0x40000		/* ack the sb interrupt */
+#define SBTML_INT_EN		0x20000		/* enable sb interrupt */
+
+/* sbtmstatehigh */
+#define SBTMH_INT_STATUS	0x40000		/* sb interrupt status */
+#endif	/* _SBPCMCIA_H */
diff --git a/wl/src/include/sdiovar.h b/wl/src/include/sdiovar.h
new file mode 100644
index 0000000..3628ac0
--- /dev/null
+++ b/wl/src/include/sdiovar.h
@@ -0,0 +1,117 @@
+/*
+ * Structure used by apps whose drivers access SDIO drivers.
+ * Pulled out separately so dhdu and wlu can both use it.
+ *
+ * Copyright (C) 2017, Broadcom. 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: sdiovar.h 660496 2016-09-20 19:28:50Z $
+ */
+
+#ifndef _sdiovar_h_
+#define _sdiovar_h_
+
+#include <typedefs.h>
+
+typedef struct sdreg {
+	int func;
+	int offset;
+	int value;
+} sdreg_t;
+
+/* Common msglevel constants */
+#define SDH_ERROR_VAL		0x0001	/* Error */
+#define SDH_TRACE_VAL		0x0002	/* Trace */
+#define SDH_INFO_VAL		0x0004	/* Info */
+#define SDH_DEBUG_VAL		0x0008	/* Debug */
+#define SDH_DATA_VAL		0x0010	/* Data */
+#define SDH_CTRL_VAL		0x0020	/* Control Regs */
+#define SDH_LOG_VAL		0x0040	/* Enable bcmlog */
+#define SDH_DMA_VAL		0x0080	/* DMA */
+
+#define NUM_PREV_TRANSACTIONS	16
+
+#ifdef BCMSPI
+/* Error statistics for gSPI */
+struct spierrstats_t {
+	uint32  dna;	/* The requested data is not available. */
+	uint32  rdunderflow;	/* FIFO underflow happened due to current (F2, F3) rd command */
+	uint32  wroverflow;	/* FIFO underflow happened due to current (F1, F2, F3) wr command */
+
+	uint32  f2interrupt;	/* OR of all F2 related intr status bits. */
+	uint32  f3interrupt;	/* OR of all F3 related intr status bits. */
+
+	uint32  f2rxnotready;	/* F2 FIFO is not ready to receive data (FIFO empty) */
+	uint32  f3rxnotready;	/* F3 FIFO is not ready to receive data (FIFO empty) */
+
+	uint32  hostcmddataerr;	/* Error in command or host data, detected by CRC/checksum
+	                         * (optional)
+	                         */
+	uint32  f2pktavailable;	/* Packet is available in F2 TX FIFO */
+	uint32  f3pktavailable;	/* Packet is available in F2 TX FIFO */
+
+	uint32	dstatus[NUM_PREV_TRANSACTIONS];	/* dstatus bits of last 16 gSPI transactions */
+	uint32  spicmd[NUM_PREV_TRANSACTIONS];
+};
+#endif /* BCMSPI */
+
+typedef struct sdio_bus_metrics {
+	uint32 active_dur;	/* msecs */
+
+	/* Generic */
+	uint32 data_intr_cnt;	/* data interrupt counter */
+	uint32 mb_intr_cnt;	/* mailbox interrupt counter */
+	uint32 error_intr_cnt;	/* error interrupt counter */
+	uint32 wakehost_cnt;	/* counter for OOB wakehost */
+
+	/* DS forcewake */
+	uint32 ds_wake_on_cnt;	/* counter for (clock) ON   */
+	uint32 ds_wake_on_dur;	/* duration for (clock) ON) */
+	uint32 ds_wake_off_cnt;	/* counter for (clock) OFF  */
+	uint32 ds_wake_off_dur;	/* duration for (clock) OFF */
+
+	/* DS_D0 state */
+	uint32 ds_d0_cnt;	/* counter for DS_D0 state */
+	uint32 ds_d0_dur;	/* duration for DS_D0 state */
+
+	/* DS_D3 state */
+	uint32 ds_d3_cnt;	/* counter for DS_D3 state */
+	uint32 ds_d3_dur;	/* duration for DS_D3 state */
+
+	/* DS DEV_WAKE */
+	uint32 ds_dw_assrt_cnt;		/* counter for DW_ASSERT */
+	uint32 ds_dw_dassrt_cnt;	/* counter for DW_DASSERT */
+
+	/* DS mailbox signals */
+	uint32 ds_tx_dsreq_cnt;		/* counter for tx HMB_DATA_DSREQ */
+	uint32 ds_tx_dsexit_cnt;	/* counter for tx HMB_DATA_DSEXIT */
+	uint32 ds_tx_d3ack_cnt;		/* counter for tx HMB_DATA_D3ACK */
+	uint32 ds_tx_d3exit_cnt;	/* counter for tx HMB_DATA_D3EXIT */
+	uint32 ds_rx_dsack_cnt;		/* counter for rx SMB_DATA_DSACK */
+	uint32 ds_rx_dsnack_cnt;	/* counter for rx SMB_DATA_DSNACK */
+	uint32 ds_rx_d3inform_cnt;	/* counter for rx SMB_DATA_D3INFORM */
+} sdio_bus_metrics_t;
+
+/* Bus interface info for SDIO */
+typedef struct wl_pwr_sdio_stats {
+	uint16 type;	     /* WL_PWRSTATS_TYPE_SDIO */
+	uint16 len;	     /* Up to 4K-1, top 4 bits are reserved */
+
+	sdio_bus_metrics_t sdio;	/* stats from SDIO bus driver */
+} wl_pwr_sdio_stats_t;
+
+#endif /* _sdiovar_h_ */
diff --git a/wl/src/include/trxhdr.h b/wl/src/include/trxhdr.h
new file mode 100644
index 0000000..e67e6c9
--- /dev/null
+++ b/wl/src/include/trxhdr.h
@@ -0,0 +1,93 @@
+/*
+ * TRX image file header format.
+ *
+ * Copyright (C) 2017, Broadcom. 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: trxhdr.h 520026 2014-12-10 01:29:40Z $
+ */
+
+#ifndef _TRX_HDR_H
+#define _TRX_HDR_H
+
+#include <typedefs.h>
+
+#define TRX_MAGIC	0x30524448	/* "HDR0" */
+#define TRX_MAX_LEN	0x3B0000	/* Max length */
+#define TRX_NO_HEADER	1		/* Do not write TRX header */
+#define TRX_GZ_FILES	0x2     /* Contains up to TRX_MAX_OFFSET individual gzip files */
+#define TRX_EMBED_UCODE	0x8	/* Trx contains embedded ucode image */
+#define TRX_ROMSIM_IMAGE	0x10	/* Trx contains ROM simulation image */
+#define TRX_UNCOMP_IMAGE	0x20	/* Trx contains uncompressed rtecdc.bin image */
+#define TRX_BOOTLOADER		0x40	/* the image is a bootloader */
+
+#define TRX_V1		1
+#define TRX_V1_MAX_OFFSETS	3		/* V1: Max number of individual files */
+
+#ifndef BCMTRXV2
+#define TRX_VERSION	TRX_V1		/* Version 1 */
+#define TRX_MAX_OFFSET TRX_V1_MAX_OFFSETS
+#endif
+
+/* BMAC Host driver/application like bcmdl need to support both Ver 1 as well as
+ * Ver 2 of trx header. To make it generic, trx_header is structure is modified
+ * as below where size of "offsets" field will vary as per the TRX version.
+ * Currently, BMAC host driver and bcmdl are modified to support TRXV2 as well.
+ * To make sure, other applications like "dhdl" which are yet to be enhanced to support
+ * TRXV2 are not broken, new macro and structure defintion take effect only when BCMTRXV2
+ * is defined.
+ */
+struct trx_header {
+	uint32 magic;		/* "HDR0" */
+	uint32 len;		/* Length of file including header */
+	uint32 crc32;		/* 32-bit CRC from flag_version to end of file */
+	uint32 flag_version;	/* 0:15 flags, 16:31 version */
+#ifndef BCMTRXV2
+	uint32 offsets[TRX_MAX_OFFSET];	/* Offsets of partitions from start of header */
+#else
+	uint32 offsets[1];	/* Offsets of partitions from start of header */
+#endif
+};
+
+#ifdef BCMTRXV2
+#define TRX_VERSION		TRX_V2		/* Version 2 */
+#define TRX_MAX_OFFSET  TRX_V2_MAX_OFFSETS
+
+#define TRX_V2		2
+/* V2: Max number of individual files
+ * To support SDR signature + Config data region
+ */
+#define TRX_V2_MAX_OFFSETS	5
+#define SIZEOF_TRXHDR_V1	(sizeof(struct trx_header)+(TRX_V1_MAX_OFFSETS-1)*sizeof(uint32))
+#define SIZEOF_TRXHDR_V2	(sizeof(struct trx_header)+(TRX_V2_MAX_OFFSETS-1)*sizeof(uint32))
+#ifdef IL_BIGENDIAN
+#define TRX_VER(trx)		(ltoh32((trx)->flag_version>>16))
+#else
+#define TRX_VER(trx)		((trx)->flag_version>>16)
+#endif
+#define ISTRX_V1(trx)		(TRX_VER(trx) == TRX_V1)
+#define ISTRX_V2(trx)		(TRX_VER(trx) == TRX_V2)
+/* For V2, return size of V2 size: others, return V1 size */
+#define SIZEOF_TRX(trx)	    (ISTRX_V2(trx) ? SIZEOF_TRXHDR_V2: SIZEOF_TRXHDR_V1)
+#else
+#define SIZEOF_TRX(trx)	    (sizeof(struct trx_header))
+#endif /* BCMTRXV2 */
+
+/* Compatibility */
+typedef struct trx_header TRXHDR, *PTRXHDR;
+
+#endif /* _TRX_HDR_H */
diff --git a/wl/src/include/typedefs.h b/wl/src/include/typedefs.h
new file mode 100644
index 0000000..26d9e6a
--- /dev/null
+++ b/wl/src/include/typedefs.h
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2017, Broadcom. 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: typedefs.h 657121 2016-08-31 05:26:32Z $
+ */
+
+#ifndef _TYPEDEFS_H_
+#define _TYPEDEFS_H_
+
+#if (!defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)) || \
+	!defined(BWL_NO_INTERNAL_STDLIB_SUPPORT)
+
+#ifdef SITE_TYPEDEFS
+
+/*
+ * Define SITE_TYPEDEFS in the compile to include a site-specific
+ * typedef file "site_typedefs.h".
+ *
+ * If SITE_TYPEDEFS is not defined, then the code section below makes
+ * inferences about the compile environment based on defined symbols and
+ * possibly compiler pragmas.
+ *
+ * Following these two sections is the Default Typedefs section.
+ * This section is only processed if USE_TYPEDEF_DEFAULTS is
+ * defined. This section has a default set of typedefs and a few
+ * preprocessor symbols (TRUE, FALSE, NULL, ...).
+ */
+
+#include "site_typedefs.h"
+
+#else
+
+/*
+ * Infer the compile environment based on preprocessor symbols and pragmas.
+ * Override type definitions as needed, and include configuration-dependent
+ * header files to define types.
+ */
+
+#ifdef __cplusplus
+
+#define TYPEDEF_BOOL
+#ifndef FALSE
+#define FALSE	false
+#endif
+#ifndef TRUE
+#define TRUE	true
+#endif
+
+#else	/* ! __cplusplus */
+
+#if defined(_WIN32)
+
+#define TYPEDEF_BOOL
+typedef	unsigned char	bool;			/* consistent w/BOOL */
+
+#endif /* _WIN32 */
+
+#endif	/* ! __cplusplus */
+
+
+#if defined(_WIN64)
+/* use the Windows ULONG_PTR type when compiling for 64 bit */
+#include <basetsd.h>
+#define TYPEDEF_UINTPTR
+typedef ULONG_PTR uintptr;
+#elif defined(__LP64__)
+#define TYPEDEF_UINTPTR
+typedef unsigned long long int uintptr;
+#endif
+
+
+
+
+#if defined(TARGETOS_nucleus)
+/* for 'size_t' type */
+#include <stddef.h>
+#endif /* TARGETOS_nucleus */
+/* float_t types conflict with the same typedefs from the standard ANSI-C
+** math.h header file. Don't re-typedef them here.
+*/
+#if defined(TARGETOS_nucleus)
+#define TYPEDEF_FLOAT_T
+#endif 
+
+#if defined(_NEED_SIZE_T_)
+typedef long unsigned int size_t;
+#endif
+
+#ifdef _MSC_VER	/* Microsoft C */
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+typedef signed __int64	int64;
+typedef unsigned __int64 uint64;
+#endif
+
+
+
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#define TYPEDEF_BOOL
+#if !defined(__bool_true_false_are_defined)
+typedef		int	bool;
+#endif
+#endif /* (defined(__FreeBSD__)) */
+
+#if defined(__sparc__)
+#define TYPEDEF_ULONG
+#endif
+
+#if defined(linux)
+/*
+ * If this is either a Linux hybrid build or the per-port code of a hybrid build
+ * then use the Linux header files to get some of the typedefs.  Otherwise, define
+ * them entirely in this file.  We can't always define the types because we get
+ * a duplicate typedef error; there is no way to "undefine" a typedef.
+ * We know when it's per-port code because each file defines LINUX_PORT at the top.
+ */
+#define TYPEDEF_UINT
+#ifndef TARGETENV_android
+#define TYPEDEF_USHORT
+#define TYPEDEF_ULONG
+#endif /* TARGETENV_android */
+#ifdef __KERNEL__
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
+#define TYPEDEF_BOOL
+#endif	/* >= 2.6.19 */
+/* special detection for 2.6.18-128.7.1.0.1.el5 */
+#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 18))
+#include <linux/compiler.h>
+#ifdef noinline_for_stack
+#define TYPEDEF_BOOL
+#endif
+#endif	/* == 2.6.18 */
+#endif	/* __KERNEL__ */
+#endif	
+
+#if !defined(linux) && !defined(_WIN32) && !defined(__DJGPP__) && !defined(__BOB__) && \
+	!defined(TARGETOS_nucleus) && !defined(__FreeBSD__)
+#define TYPEDEF_UINT
+#define TYPEDEF_USHORT
+#endif
+
+/* Do not support the (u)int64 types with strict ansi for GNU C */
+#if defined(__GNUC__) && defined(__STRICT_ANSI__)
+#if !defined(__FreeBSD__)
+#define TYPEDEF_INT64
+#define TYPEDEF_UINT64
+#endif /* !defined(__FreeBSD__) */
+#endif /* defined(__GNUC__) && defined(__STRICT_ANSI__) */
+
+/* ICL accepts unsigned 64 bit type only, and complains in ANSI mode
+ * for signed or unsigned
+ */
+#if defined(__ICL)
+
+#define TYPEDEF_INT64
+
+#if defined(__STDC__)
+#define TYPEDEF_UINT64
+#endif
+
+#endif /* __ICL */
+
+#if !defined(_WIN32) && !defined(__DJGPP__) && !defined(__BOB__) && \
+	!defined(TARGETOS_nucleus)
+
+/* pick up ushort & uint from standard types.h */
+#if defined(linux) && defined(__KERNEL__)
+
+/* See note above */
+#ifdef USER_MODE
+#include <sys/types.h>
+#else
+#include <linux/types.h>	/* sys/types.h and linux/types.h are oil and water */
+#endif /* USER_MODE */
+
+#else
+
+#include <sys/types.h>
+
+#endif /* linux && __KERNEL__ */
+
+#endif 
+
+
+/* use the default typedefs in the next section of this file */
+#define USE_TYPEDEF_DEFAULTS
+
+#endif /* SITE_TYPEDEFS */
+
+
+/*
+ * Default Typedefs
+ */
+
+#ifdef USE_TYPEDEF_DEFAULTS
+#undef USE_TYPEDEF_DEFAULTS
+
+#ifndef TYPEDEF_BOOL
+typedef	/* @abstract@ */ unsigned char	bool;
+#endif /* endif TYPEDEF_BOOL */
+
+/* define uchar, ushort, uint, ulong */
+
+#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
+
+/* define [u]int8/16/32/64, uintptr */
+
+#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
+
+/* define float32/64, float_t */
+
+#ifndef TYPEDEF_FLOAT32
+typedef float		float32;
+#endif
+
+#ifndef TYPEDEF_FLOAT64
+typedef double		float64;
+#endif
+
+/*
+ * abstracted floating point type allows for compile time selection of
+ * single or double precision arithmetic.  Compiling with -DFLOAT32
+ * selects single precision; the default is double precision.
+ */
+
+#ifndef TYPEDEF_FLOAT_T
+
+#if defined(FLOAT32)
+typedef float32 float_t;
+#else /* default to double precision floating point */
+typedef float64 float_t;
+#endif
+
+#endif /* TYPEDEF_FLOAT_T */
+
+/* define macro values */
+
+#ifndef FALSE
+#define FALSE	0
+#endif
+
+#ifndef TRUE
+#define TRUE	1  /* TRUE */
+#endif
+
+#ifndef NULL
+#define	NULL	0
+#endif
+
+#ifndef OFF
+#define	OFF	0
+#endif
+
+#ifndef ON
+#define	ON	1  /* ON = 1 */
+#endif
+
+#define	AUTO	(-1) /* Auto = -1 */
+
+/* define PTRSZ, INLINE */
+
+#ifndef PTRSZ
+#define	PTRSZ	sizeof(char*)
+#endif
+
+
+/* Detect compiler type. */
+#ifdef _MSC_VER
+	#define BWL_COMPILER_MICROSOFT
+#elif defined(__GNUC__) || defined(__lint)
+	#define BWL_COMPILER_GNU
+#elif defined(__CC_ARM) && __CC_ARM
+	#define BWL_COMPILER_ARMCC
+#else
+	#error "Unknown compiler!"
+#endif /* _MSC_VER */
+
+
+#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 /* _MSC_VER */
+#endif /* INLINE */
+
+#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 /* USE_TYPEDEF_DEFAULTS */
+
+/* Suppress unused parameter warning */
+#define UNUSED_PARAMETER(x) (void)(x)
+
+/* Avoid warning for discarded const or volatile qualifier in special cases (-Wcast-qual) */
+#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr))
+
+#else /* !EDK_RELEASE_VERSION || (EDK_RELEASE_VERSION < 0x00020000) */
+
+#include <sys/types.h>
+#include <strings.h>
+#include <stdlib.h>
+
+#ifdef stderr
+#undef stderr
+#define stderr stdout
+#endif
+
+typedef UINT8   uint8;
+typedef UINT16  uint16;
+typedef UINT32  uint32;
+typedef UINT64  uint64;
+typedef INT8    int8;
+typedef INT16   int16;
+typedef INT32   int32;
+typedef INT64   int64;
+
+typedef BOOLEAN       bool;
+typedef unsigned char uchar;
+typedef UINTN         uintptr;
+
+#define UNUSED_PARAMETER(x) (void)(x)
+#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr))
+#define INLINE
+#define	AUTO	(-1) /* Auto = -1 */
+#define	ON	1  /* ON = 1 */
+#define	OFF	0
+
+#endif /* !EDK_RELEASE_VERSION || (EDK_RELEASE_VERSION < 0x00020000) */
+
+/*
+ * Including the bcmdefs.h here, to make sure everyone including typedefs.h
+ * gets this automatically
+*/
+#include <bcmdefs.h>
+#endif /* _TYPEDEFS_H_ */
diff --git a/wl/src/include/wlc_extlog_idstr.h b/wl/src/include/wlc_extlog_idstr.h
new file mode 100644
index 0000000..6a55e97
--- /dev/null
+++ b/wl/src/include/wlc_extlog_idstr.h
@@ -0,0 +1,120 @@
+/*
+ * EXTLOG Module log ID to log Format String mapping table
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlc_extlog_idstr.h 514727 2014-11-12 03:02:48Z $
+ */
+#ifndef _WLC_EXTLOG_IDSTR_H_
+#define _WLC_EXTLOG_IDSTR_H_
+
+#include "wlioctl.h"
+
+/* Strings corresponding to the IDs defined in wlioctl.h
+ * This file is only included by the apps and not included by the external driver
+ * Formats of pre-existing ids should NOT be changed
+ */
+log_idstr_t extlog_fmt_str[ ] = {
+	{FMTSTR_DRIVER_UP_ID, 0, LOG_ARGTYPE_NULL,
+	"Driver is Up\n"},
+
+	{FMTSTR_DRIVER_DOWN_ID, 0, LOG_ARGTYPE_NULL,
+	"Driver is Down\n"},
+
+	{FMTSTR_SUSPEND_MAC_FAIL_ID, 0, LOG_ARGTYPE_INT,
+	"wlc_suspend_mac_and_wait() failed with psmdebug 0x%08x\n"},
+
+	{FMTSTR_NO_PROGRESS_ID, 0, LOG_ARGTYPE_INT,
+	"No Progress on TX for %d seconds\n"},
+
+	{FMTSTR_RFDISABLE_ID, 0, LOG_ARGTYPE_INT,
+	"Detected a change in RF Disable Input 0x%x\n"},
+
+	{FMTSTR_REG_PRINT_ID, 0, LOG_ARGTYPE_STR_INT,
+	"Register %s = 0x%x\n"},
+
+	{FMTSTR_EXPTIME_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Strong RF interference detected\n"},
+
+	{FMTSTR_JOIN_START_ID, FMTSTRF_USER, LOG_ARGTYPE_STR,
+	"Searching for networks with ssid %s\n"},
+
+	{FMTSTR_JOIN_COMPLETE_ID, FMTSTRF_USER, LOG_ARGTYPE_STR,
+	"Successfully joined network with BSSID %s\n"},
+
+	{FMTSTR_NO_NETWORKS_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"No networks found. Please check if the network exists and is in range\n"},
+
+	{FMTSTR_SECURITY_MISMATCH_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"AP rejected due to security mismatch. Change the security settings and try again...\n"},
+
+	{FMTSTR_RATE_MISMATCH_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"AP rejected due to rate mismatch\n"},
+
+	{FMTSTR_AP_PRUNED_ID, 0, LOG_ARGTYPE_INT,
+	"AP rejected due to reason %d\n"},
+
+	{FMTSTR_KEY_INSERTED_ID, 0, LOG_ARGTYPE_INT,
+	"Inserting keys for algorithm %d\n"},
+
+	{FMTSTR_DEAUTH_ID, FMTSTRF_USER, LOG_ARGTYPE_STR_INT,
+	"Received Deauth from %s with Reason %d\n"},
+
+	{FMTSTR_DISASSOC_ID, FMTSTRF_USER, LOG_ARGTYPE_STR_INT,
+	"Received Disassoc from %s with Reason %d\n"},
+
+	{FMTSTR_LINK_UP_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Link Up\n"},
+
+	{FMTSTR_LINK_DOWN_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Link Down\n"},
+
+	{FMTSTR_RADIO_HW_OFF_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Radio button is turned OFF. Please turn it on...\n"},
+
+	{FMTSTR_RADIO_HW_ON_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Hardware Radio button is turned ON\n"},
+
+	{FMTSTR_EVENT_DESC_ID, 0, LOG_ARGTYPE_INT_STR,
+	"Generated event id %d: (result status) is (%s)\n"},
+
+	{FMTSTR_PNP_SET_POWER_ID, 0, LOG_ARGTYPE_INT,
+	"Device going into power state %d\n"},
+
+	{FMTSTR_RADIO_SW_OFF_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Software Radio is disabled. Please enable it through the UI...\n"},
+
+	{FMTSTR_RADIO_SW_ON_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Software Radio is enabled\n"},
+
+	{FMTSTR_PWD_MISMATCH_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Potential passphrase mismatch. Please try a different one...\n"},
+
+	{FMTSTR_FATAL_ERROR_ID, 0, LOG_ARGTYPE_INT,
+	"Fatal Error: intstatus 0x%x\n"},
+
+	{FMTSTR_AUTH_FAIL_ID, 0, LOG_ARGTYPE_STR_INT,
+	"Authentication to %s Failed with status %d\n"},
+
+	{FMTSTR_ASSOC_FAIL_ID, 0, LOG_ARGTYPE_STR_INT,
+	"Association to %s Failed with status %d\n"},
+
+	{FMTSTR_IBSS_FAIL_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Unable to start IBSS since PeerNet is already active\n"},
+
+	{FMTSTR_EXTAP_FAIL_ID, FMTSTRF_USER, LOG_ARGTYPE_NULL,
+	"Unable to start Ext-AP since PeerNet is already active\n"},
+
+	{FMTSTR_MAX_ID, 0, 0, "\0"}
+};
+
+#endif /* _WLC_EXTLOG_IDSTR_H_ */
diff --git a/wl/src/include/wlioctl.h b/wl/src/include/wlioctl.h
new file mode 100644
index 0000000..2200383
--- /dev/null
+++ b/wl/src/include/wlioctl.h
@@ -0,0 +1,28 @@
+/*
+ * Custom OID/ioctl definitions for
+ *
+ *
+ * Broadcom 802.11abg Networking Device Driver
+ *
+ * Definitions subject to change without notice.
+ *
+ * Copyright (C) 2017, Broadcom. 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: wlioctl.h 661028 2016-09-23 00:14:48Z $
+ */
+
+/* wlioctl.h has been moved to components/shared/devctrl_if */
+#include <devctrl_if/wlioctl.h>
diff --git a/wl/src/include/wlioctl_utils.h b/wl/src/include/wlioctl_utils.h
new file mode 100644
index 0000000..498d78a
--- /dev/null
+++ b/wl/src/include/wlioctl_utils.h
@@ -0,0 +1,55 @@
+/*
+ * Custom OID/ioctl related helper functions.
+ *
+ * Copyright (C) 2017, Broadcom. 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: wlioctl_utils.h 626207 2016-03-19 17:39:14Z $
+ */
+
+#ifndef _wlioctl_utils_h_
+#define _wlioctl_utils_h_
+
+#include <wlioctl.h>
+
+#ifndef BCMDRIVER
+#define CCA_THRESH_MILLI	14
+#define CCA_THRESH_INTERFERE	6
+
+extern cca_congest_channel_req_t * cca_per_chan_summary(cca_congest_channel_req_t *input,
+	cca_congest_channel_req_t *avg, bool percent);
+
+extern int cca_analyze(cca_congest_channel_req_t *input[], int num_chans,
+	uint flags, chanspec_t *answer);
+#endif /* BCMDRIVER */
+
+extern int wl_cntbuf_to_xtlv_format(void *ctx, void *cntbuf,
+	int buflen, uint32 corerev);
+
+extern const char * wl_get_reinit_rc_name(int rc);
+
+/* Get data pointer of wlc layer counters tuple from xtlv formatted counters IOVar buffer. */
+#define GET_WLCCNT_FROM_CNTBUF(cntbuf) (const wl_cnt_wlc_t*) \
+		bcm_get_data_from_xtlv_buf(((const wl_cnt_info_t *)cntbuf)->data,	\
+		((const wl_cnt_info_t *)cntbuf)->datalen, WL_CNT_XTLV_WLC,		\
+		NULL, BCM_XTLV_OPTION_ALIGN32)
+
+#define CHK_CNTBUF_DATALEN(cntbuf, ioctl_buflen) do {					\
+	if (((wl_cnt_info_t *)cntbuf)->datalen +			\
+		OFFSETOF(wl_cnt_info_t, data) > ioctl_buflen)	\
+		printf("%s: IOVAR buffer short!\n", __FUNCTION__);	\
+} while (0)
+
+#endif /* _wlioctl_utils_h_ */
diff --git a/wl/src/makefiles/RelPath.mk b/wl/src/makefiles/RelPath.mk
new file mode 100644
index 0000000..d95a36b
--- /dev/null
+++ b/wl/src/makefiles/RelPath.mk
@@ -0,0 +1,103 @@
+# General-purpose GNU make include file
+#
+# Copyright (C) 2017, Broadcom. 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: Makefile 506823 2014-10-07 12:59:32Z $
+#
+
+ifdef _RELPATH_MK_
+$(if $D,$(info =-= Avoiding redundant include ($(MAKEFILE_LIST))))
+else
+unexport _RELPATH_MK_	# in case of make -e
+_RELPATH_MK_ := 1
+
+# Protection against process recursion when this file is
+# included by setting MAKEFILES.
+ifneq (,$(filter %$(notdir $(lastword $(MAKEFILE_LIST))),$(MAKEFILES)))
+MAKEFILES := $(filter-out %$(notdir $(lastword $(MAKEFILE_LIST))),$(MAKEFILES))
+ifndef MAKEFILES
+unexport MAKEFILES
+endif
+endif
+
+# Usage: $(call relpath,[<from-dir>,]<to-dir>)
+# Returns the relative path from <from-dir> to <to-dir>; <from-dir>
+# may be elided in which case it defaults to $(CURDIR).
+
+_rp_space :=
+_rp_space +=
+_rp_uname_s := $(shell uname -s)
+
+# Utility functions.
+_rp_compose = $(subst ${_rp_space},$(strip $1),$(strip $2))
+_rp_endlist = $(wordlist $1,$(words $2),$2)
+_rp_canonpath = $(if $(findstring CYGWIN,$(_rp_uname_s)),$(shell cygpath -a -u $1),$(abspath $1))
+
+# ----relpath(): Self-recursive function which compares the first element
+#                of two given paths, then calls itself with the next two
+#                elements, and so on, until a difference is found.  At each
+#                step, if the first element of both paths matches, that
+#                element is produced.
+----relpath = $(if $(filter $(firstword $1),$(firstword $2)), \
+                $(firstword $1) \
+                $(call $0,$(call _rp_endlist,2,$1),$(call _rp_endlist,2,$2)) \
+               )
+# ---relpath():  This function removes $1 from the front of both $2 and
+#                $3 (removes common path prefix) and generates a relative
+#                path between the locations given by $2 and $3, by replacing
+#                each remaining element of $2 (after common prefix removal)
+#                with '..', then appending the remainder of $3 (after common
+#                prefix removal) to the string of '..'s
+---relpath  = $(foreach e,$(subst /, ,$(patsubst $(if $1,/)$1/%,%,$2)),..) \
+              $(if $3,$(patsubst $(if $1,/)$1/%,%,$3))
+# --relpath():   This function runs the output of ----relpath() through
+#                ---relpath(), and turns the result into an actual relative
+#                path string, separated by '/'.
+--relpath   = $(call _rp_compose,/, \
+                $(call -$0,$(call _rp_compose,/,$(call --$0,$3,$4)),$1,$2) \
+               )
+# -relpath():    This function makes a determination about the two given
+#                paths -- does one strictly prefix the other?  If so, this
+#                function produces a relative path between the two inputs,
+#                without calling --relpath() and taking the "long road".
+#                If $1 prefixes $2, the result is the remainder of $2 after
+#                removing $1.  If $2 prefixes $1, the result is the remainder
+#                of $1 after removing $2, but with each element in that
+#                remainder converted to '..'.
+-relpath    = $(if $(filter $1,$2),., \
+                $(if $(filter $1/%,$2), \
+                 $(patsubst $1/%,%,$2), \
+                 $(if $(filter $2/%,$1), \
+                   $(call _rp_compose,/, \
+                     $(foreach e,$(subst /, ,$(patsubst $2/%,%,$1)),..) \
+                    ), \
+                   $(call -$0,$1,$2,$(subst /, ,$1),$(subst /, ,$2)) \
+                  ) \
+                ) \
+              )
+
+# relpath():     This function loops over each element in $2, calculating
+#                the relative path from $1 to each element of $2.
+relpath     = $(if $1,,$(error Error: missing first parameter to $0))$(strip \
+                $(if $2, \
+                  $(foreach d,$2,$(call -$0,$(call _rp_canonpath,$1),$(call _rp_canonpath,$d))), \
+                  $(foreach d,$1,$(call -$0,$(call _rp_canonpath,${CURDIR}),$(call _rp_canonpath,$d))) \
+                 ) \
+               )
+
+endif #_RELPATH_MK_
diff --git a/wl/src/makefiles/WLAN_Common.mk b/wl/src/makefiles/WLAN_Common.mk
new file mode 100644
index 0000000..4affa3f
--- /dev/null
+++ b/wl/src/makefiles/WLAN_Common.mk
@@ -0,0 +1,511 @@
+# General-purpose GNU make include file
+#
+# Copyright (C) 2017, Broadcom. 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: Makefile 506823 2014-10-07 12:59:32Z $
+#
+ifdef _WLAN_COMMON_MK
+  $(if $D,$(info Info: Avoiding redundant include ($(MAKEFILE_LIST))))
+else	# _WLAN_COMMON_MK
+  _WLAN_COMMON_MK := 1
+unexport _WLAN_COMMON_MK	# in case of make -e
+
+################################################################
+# Summary and Namespace Rules
+################################################################
+#   This is a special makefile fragment intended for common use.
+# The most important design principle is that it defines variables
+# and functions only within a tightly controlled namespace.
+# If a make include file is used to set rules, pattern rules,
+# or well known variables like CFLAGS, it can have unexpected
+# effects on the including makefile with the result that people
+# either stop including it or stop changing it.
+# Therefore, the only way to keep this a file which can be
+# safely included by any GNU makefile and extended at will is
+# to allow it only to set variables and only in its own namespace.
+#   The namespace is "WLAN_CamelCase" for normal variables,
+# "wlan_lowercase" for functions, and WLAN_UPPERCASE for boolean
+# "constants" (these are all really just make variables; only the
+# usage patterns differ).
+#   Internal (logically file-scoped) variables are prefixed with "-"
+# and have no other namespace restrictions.
+#   Every variable defined here should match one of these patterns.
+
+################################################################
+# Enforce required conditions
+################################################################
+
+ifneq (,$(filter 3.7% 3.80,$(MAKE_VERSION)))
+  $(error $(MAKE): Error: version $(MAKE_VERSION) too old, 3.81+ required)
+endif
+
+################################################################
+# Store this makefile's path before MAKEFILE_LIST gets changed.
+################################################################
+
+WLAN_Common := $(lastword $(MAKEFILE_LIST))
+
+################################################################
+# Derive including makefile since it's a little tricky.
+################################################################
+
+WLAN_Makefile := $(abspath $(lastword $(filter-out $(lastword $(MAKEFILE_LIST)),$(MAKEFILE_LIST))))
+
+################################################################
+# Shiny new ideas, can be enabled via environment for testing.
+################################################################
+
+ifdef WLAN_MakeBeta
+  $(info Info: BUILDING WITH "WLAN_MakeBeta" ENABLED!)
+  SHELL := /bin/bash
+  #.SUFFIXES:
+  #MAKEFLAGS += -r
+endif
+
+################################################################
+# Allow a makefile to force this file into all child makes.
+################################################################
+
+ifdef WLAN_StickyCommon
+  export MAKEFILES := $(MAKEFILES) $(abspath $(lastword $(MAKEFILE_LIST)))
+endif
+
+################################################################
+# Host type determination
+################################################################
+
+_common-uname-s := $(shell uname -s)
+
+# Typically this will not be tested explicitly; it's the default condition.
+WLAN_HOST_TYPE := unix
+
+ifneq (,$(filter Linux,$(_common-uname-s)))
+  WLAN_LINUX_HOST := 1
+else ifneq (,$(filter CYGWIN%,$(_common-uname-s)))
+  WLAN_CYGWIN_HOST := 1
+  WLAN_WINDOWS_HOST := 1
+else ifneq (,$(filter Darwin,$(_common-uname-s)))
+  WLAN_MACOS_HOST := 1
+  WLAN_BSD_HOST := 1
+else ifneq (,$(filter FreeBSD NetBSD,$(_common-uname-s)))
+  WLAN_BSD_HOST := 1
+else ifneq (,$(filter SunOS%,$(_common-uname-s)))
+  WLAN_SOLARIS_HOST := 1
+endif
+
+################################################################
+# Utility variables
+################################################################
+
+empty :=
+space := $(empty) $(empty)
+comma := ,
+
+################################################################
+# Utility functions
+################################################################
+
+# Provides enhanced-format messages from make logic.
+wlan_die = $(error Error: $1)
+wlan_warning = $(warning Warning: $1)
+wlan_info = $(info Info: $1)
+
+# Debug function to enable make verbosity.
+wlan_dbg = $(if $D,$(call wlan_info,$1))
+
+# Debug function to expose values of the listed variables.
+wlan_dbgv = $(foreach _,$1,$(call wlan_dbg,$_=$($_)))
+
+# Make-time assertion.
+define wlan_assert
+  ifeq (,$(findstring clean,$(MAKECMDGOALS)))
+    $(if $1,,$(call wlan_die,$2))
+  endif
+endef
+
+# Checks for the presence of an option in an option string
+# like "aaa-bbb-ccc-ddd".
+wlan_opt = $(if $(findstring -$1-,-$2-),1,0)
+
+# The purpose of this macro is to avoid the need for full directory
+# paths to be created via mkdir -p since mkdir -p has an inherent
+# race in parallel use cases. Interestingly, though it exists to
+# make -p unnecessary, it actually uses -p. Why is that? It's to
+# take advantage of a useful side effect of -p which is that it
+# doesn't complain if the directory already exists. In other words
+# it creates directories one at a time to avoid creating its own
+# race but still uses mkdir -p to protect itself against races with
+# unrelated make processes.
+# Usage: $(call wlan_target_needs_dir,<target>,<dir-path>)
+define wlan_target_needs_dir
+$(eval
+$$1: | $$2
+$$2: | $$(filter-out .,$$(patsubst %/,%,$$(dir $$2))); mkdir -p $$@
+ifneq (,$$(findstring /,$$2))
+  $$(call wlan_target_needs_dir,$$1,$$(patsubst %/,%,$$(dir $$2)))
+endif
+)
+endef
+
+# Compares two dotted numeric strings (e.g 2.3.16.1) for $1 >= $2
+define wlan_version_ge
+$(findstring TRUE,$(shell bash -c 'sort -cu -t. -k1,1nr -k2,2nr -k3,3nr -k4,4nr <(echo -e "$2\n$1") 2>&1 || echo TRUE'))
+endef
+
+# This is a useful macro to wrap around a compiler command line,
+# e.g. "$(call wlan_cc,<command-line>). It organizes flags in a
+# readable way while taking care not to change any ordering
+# which matters. It also provides a hook for externally
+# imposed C flags which can be passed in from the top level.
+# This would be the best place to add a check for
+# command line length. Requires a $(strlen) function;
+# GMSL has one.
+define wlan_cc
+$(filter-out -D% -I%,$1) $(filter -D%,$1) $(filter -I%,$1) $(WLAN_EXTERNAL_CFLAGS)
+endef
+
+# Applies the standard cygpath translation for a path on Cygwin.
+define wlan_cygpath
+$(if $(WLAN_CYGWIN_HOST),$(shell cygpath -m $1),$1)
+endef
+
+# Change case without requiring a shell.
+wlan_tolower = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,\
+$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,\
+$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,\
+$(subst X,x,$(subst Y,y,$(subst Z,z,$1))))))))))))))))))))))))))
+
+wlan_toupper = $(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,\
+$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,\
+$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,\
+$(subst x,X,$(subst y,Y,$(subst z,Z,$1))))))))))))))))))))))))))
+
+# This macro derives the base (aka root) of the entire "checkout tree" as well as the
+# current "build tree" and "component tree" (svn or git checkout).
+# Definitions:
+# - Checkout Tree: the root of the full tree of files retrieved from SCM. May comprise
+#   any number of individual checkouts, potentially from different branches, repos,
+#   or even SCM tools.
+# - Build Tree: the root of a coherent subtree within the checkout tree, sufficient to
+#   build some subset of the required deliverables.
+# - Component Tree: the root of a single component within the build tree, generally a
+#   single checkout from svn or git.
+# These could all have the same value but more often a component is a subdir of a build
+# tree which may be a subdir of a DEPS checkout. The only guaranteed relationship is that
+# each component tree is within a build tree which is within the unitary checkout tree.
+# Returns a list: [checkout-tree, build-tree, component-tree]
+# Notes:
+# 1. We've observed a bug, or at least a surprising behavior, in emake which causes
+# $(realpath ...) to fail. That's why a $(shell ...) fallback is used below.
+# 2. There may be no SCM metadata at all, particularly in the case of a source package
+# delivered to a customer. This is where guessing (as described below) comes in.
+# 3. This macro always trusts .wlbase if present. It looks next for a .gclient
+# file, then sparsefile_url.py. If none of these are found we have to guess starting
+# from the location of this file. If a ../../../main file exists from here, set the
+# base there. Otherwise set it at ../.. from here.
+define wlan_basedirs
+$(eval\
+  _refdir := $$(realpath $$(or $1,$$(dir $$(lastword $$(MAKEFILE_LIST)))))
+  _refdir ?= $$(shell cd $$(or $1,$$(dir $$(lastword $$(MAKEFILE_LIST)))) && pwd -P)
+  _parts := $$(strip $$(subst /,$$(space),$$(subst \,/,$$(_refdir))))
+  _paths := /
+  $$(foreach _i,$$(_parts),$$(eval _paths += $$(addsuffix /$$(_i),$$(lastword $$(_paths)))))
+  _paths := $$(patsubst //%,/%,$$(wordlist 2,$$(words $$(_paths)),$$(_paths)))
+  _wlb := $$(patsubst %/,%,$$(dir $$(lastword $$(wildcard $$(addsuffix /.wlbase,$$(_paths))))))
+  _dep := $$(patsubst %/,%,$$(dir $$(lastword $$(wildcard $$(addsuffix /.gclient,$$(_paths))))))
+  ifndef _dep
+    _sprs := $$(subst /.svn/sparsefile_url.py,,$$(lastword $$(wildcard $$(addsuffix /.svn/sparsefile_url.py,$$(_paths)))))
+    ifndef _sprs
+      _guess := $$(strip $$(if $$(wildcard $$(dir $$(abspath $$(WLAN_Common)))../../../main),\
+	$$(abspath $$(dir $$(WLAN_Common))../../..),\
+	$$(abspath $$(dir $$(WLAN_Common))../..)))
+    endif  # _sprs
+  endif  # _dep
+  _arg3 := $$(patsubst %/,%,$$(dir $$(lastword $$(wildcard $$(addsuffix /.svn,$$(_paths)) $$(addsuffix /.git,$$(_paths))))))
+  _arg2 := $$(abspath $$(_refdir)/../..)
+  _arg1 := $$(or $$(_wlb),$$(_dep),$$(_sprs),$$(_guess),$$(_arg3))
+)$(strip $(_arg1) $(_arg2) $(_arg3))
+endef
+
+################################################################
+# Standard make variables
+################################################################
+
+# The WLAN_CheckoutBaseA variable points to the root of the entire
+# checkout while WLAN_TreeBaseA points to the root of the current
+# build tree and WLAN_ComponentBaseA points to the root of the
+# component containing the including Makefile. They could have the
+# values values but in other cases such as DHDAP routers a single
+# DEPS checkout may contain multiple build trees (potentially from
+# different branches) with each build tree composed of multiple components.
+# These 'A' variables are absolute paths; each has an 'R' variant
+# which is relative.
+ifndef WLAN_TreeBaseA
+  _basedata := $(call wlan_basedirs)
+  WLAN_CheckoutBaseA := $(word 1,$(_basedata))
+  WLAN_TreeBaseA := $(word 2,$(_basedata))
+  WLAN_ComponentBaseA := $(word 3,$(_basedata))
+  ifdef WLAN_CYGWIN_HOST
+    WLAN_TreeBaseA := $(shell cygpath -m -a $(WLAN_TreeBaseA))
+  endif
+endif
+
+# Pick up the "relpath" make function from the same dir as this makefile.
+include $(dir $(lastword $(MAKEFILE_LIST)))RelPath.mk
+
+# The *R variables are relativized versions of the *A variables.
+WLAN_CheckoutBaseR = $(call relpath,$(WLAN_CheckoutBaseA))
+WLAN_TreeBaseR = $(call relpath,$(WLAN_TreeBaseA))
+WLAN_ComponentBaseR = $(call relpath,$(WLAN_ComponentBaseA))
+
+# For compatibility, due to the prevalence of $(SRCBASE)
+WLAN_SrcBaseA := $(WLAN_TreeBaseA)/src
+WLAN_SrcBaseR  = $(patsubst %/,%,$(dir $(WLAN_TreeBaseR)))
+
+# Show makefile list before we start including things.
+$(call wlan_dbgv, CURDIR MAKEFILE_LIST)
+
+################################################################
+# Pick up the "universal settings file" containing
+# the list of all available software components.
+################################################################
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../tools/release/WLAN.usf
+
+################################################################
+# Calculate paths to requested components.
+################################################################
+
+# This uses pattern matching to pull component paths from
+# their basenames (e.g. src/wl/xyz => xyz).
+# It also strips out component paths which don't currently exist.
+# This may be required due to our "sparse tree" build styles
+# and the fact that linux mkdep throws an error when a directory
+# specified with -I doesn't exist.
+define _common-component-names-to-rel-paths
+$(strip \
+  $(patsubst $(WLAN_TreeBaseA)/%,%,$(wildcard $(addprefix $(WLAN_TreeBaseA)/,\
+  $(sort $(foreach name,$(if $1,$1,$(WLAN_COMPONENT_PATHS)),$(filter %/$(name),$(WLAN_COMPONENT_PATHS))))))))
+endef
+
+# It's also possible to request the full set with a literal '*'.
+ifeq (,$(WLAN_ComponentsInUse))
+  WLAN_ComponentsInUse		:= $(sort $(notdir $(WLAN_COMPONENT_PATHS)))
+  # $(call wlan_die,no SW component request)
+else ifeq (*,$(WLAN_ComponentsInUse))
+  WLAN_ComponentsInUse		:= $(sort $(notdir $(WLAN_COMPONENT_PATHS)))
+  # $(call wlan_info,all SW components requested ("$(WLAN_ComponentsInUse)"))
+else
+  WLAN_ComponentsInUse		:= $(sort $(WLAN_ComponentsInUse))
+endif
+
+# For backward compatibility we accept certain old component names from older
+# branches and convert them to their updated names here.
+WLAN_ComponentsInUse := $(sort $(subst phymods,phy,$(WLAN_ComponentsInUse)))
+
+# Translate the resulting list of components names to paths.
+WLAN_ComponentPathsInUse	:= $(call _common-component-names-to-rel-paths,$(WLAN_ComponentsInUse))
+
+# Loop through all components in use. If a cfg-xyz.mk file exists at the base of
+# component xyz's subtree, include it and use its contents to modify the list
+# of include and src dirs. Otherwise, use the defaults for that component.
+# Also generate a WLAN_ComponentBaseDir_xyz variable for each component "xyz".
+WLAN_ComponentIncPathsInUse :=
+WLAN_ComponentSrcPathsInUse :=
+$(foreach _path,$(WLAN_ComponentPathsInUse), \
+  $(if $(wildcard $(WLAN_TreeBaseA)/$(_path)/cfg-$(notdir $(_path)).mk),$(eval include $(WLAN_TreeBaseA)/$(_path)/cfg-$(notdir $(_path)).mk)) \
+  $(eval $(notdir $(_path))_IncDirs ?= include) \
+  $(eval $(notdir $(_path))_SrcDirs ?= src) \
+  $(eval WLAN_ComponentIncPathsInUse += $(addprefix $(_path)/,$($(notdir $(_path))_IncDirs))) \
+  $(eval WLAN_ComponentSrcPathsInUse += $(addprefix $(_path)/,$($(notdir $(_path))_SrcDirs))) \
+  $(eval WLAN_ComponentBaseDir_$$(notdir $(_path)) := $$(WLAN_TreeBaseA)/$(_path)) \
+)
+
+# Global include/source path
+WLAN_StdSrcDirs = src/shared src/wl/sys src/bcmcrypto
+WLAN_StdSrcDirs += components/clm-api/src
+WLAN_StdIncDirs = src/include components/shared
+WLAN_StdIncDirs += components/clm-api/include
+WLAN_SrcIncDirs = src/shared src/wl/sys src/bcmcrypto \
+	src/wl/keymgmt/src src/wl/iocv/src \
+	components/drivers/wl/shim/src src/wl/proxd/src src/wl/mesh/src \
+	src/wl/randmac/src
+
+WLAN_StdSrcDirsR	 = $(addprefix $(WLAN_TreeBaseR)/,$(WLAN_StdSrcDirs))
+WLAN_StdIncDirsR	 = $(addprefix $(WLAN_TreeBaseR)/,$(WLAN_StdIncDirs))
+WLAN_SrcIncDirsR	 = $(addprefix $(WLAN_TreeBaseR)/,$(WLAN_SrcIncDirs))
+WLAN_StdIncPathR	 = $(addprefix -I,$(wildcard $(WLAN_StdIncDirsR)))
+WLAN_IncDirsR		 = $(WLAN_StdIncDirsR) $(WLAN_SrcIncDirsR)
+WLAN_IncPathR		 = $(addprefix -I,$(wildcard $(WLAN_IncDirsR)))
+
+WLAN_StdSrcDirsA	 = $(addprefix $(WLAN_TreeBaseA)/,$(WLAN_StdSrcDirs))
+WLAN_StdIncDirsA	 = $(addprefix $(WLAN_TreeBaseA)/,$(WLAN_StdIncDirs))
+WLAN_SrcIncDirsA	 = $(addprefix $(WLAN_TreeBaseA)/,$(WLAN_SrcIncDirs))
+WLAN_StdIncPathA	 = $(addprefix -I,$(wildcard $(WLAN_StdIncDirsA)))
+WLAN_IncDirsA		 = $(WLAN_StdIncDirsA) $(WLAN_SrcIncDirsA)
+WLAN_IncPathA		 = $(addprefix -I,$(wildcard $(WLAN_IncDirsA)))
+
+# Public convenience macros based on WLAN_ComponentPathsInUse list.
+WLAN_ComponentSrcDirsR	 = $(addprefix $(WLAN_TreeBaseR)/,$(WLAN_ComponentSrcPathsInUse))
+WLAN_ComponentIncDirsR	 = $(addprefix $(WLAN_TreeBaseR)/,$(WLAN_ComponentIncPathsInUse))
+WLAN_ComponentIncPathR	 = $(addprefix -I,$(wildcard $(WLAN_ComponentIncDirsR)))
+
+WLAN_ComponentSrcDirsA	 = $(addprefix $(WLAN_TreeBaseA)/,$(WLAN_ComponentSrcPathsInUse))
+WLAN_ComponentIncDirsA	 = $(addprefix $(WLAN_TreeBaseA)/,$(WLAN_ComponentIncPathsInUse))
+WLAN_ComponentIncPathA	 = $(addprefix -I,$(wildcard $(WLAN_ComponentIncDirsA)))
+
+WLAN_ComponentSrcDirs	 = $(WLAN_ComponentSrcDirsA)
+WLAN_ComponentIncDirs	 = $(WLAN_ComponentIncDirsA)
+WLAN_ComponentIncPath	 = $(WLAN_ComponentIncPathA)
+
+# Dump a representative sample of derived variables in debug mode.
+$(call wlan_dbgv, WLAN_TreeBaseA WLAN_TreeBaseR WLAN_SrcBaseA WLAN_SrcBaseR \
+    WLAN_ComponentPathsInUse WLAN_ComponentIncPath WLAN_ComponentIncPathR \
+    WLAN_ComponentSrcDirs WLAN_ComponentSrcDirsR)
+
+# Special case for Windows to reflect CL in the build log if used.
+ifdef WLAN_WINDOWS_HOST
+  ifdef CL
+    $(info Info: CL=$(CL))
+  endif
+endif
+
+# A big hammer for debugging each shell invocation.
+# Warning: this can get lost if a sub-makefile sets SHELL explicitly, and
+# in that case the parent should add $(WLAN_ShellDebugSHELL) to the call.
+ifeq ($D,2)
+  WLAN_ShellDebug := 1
+endif
+ifdef WLAN_ShellDebug
+  ORIG_SHELL := $(SHELL)
+  SHELL = $(strip $(warning Shell: ORIG_SHELL=$(ORIG_SHELL) PATH=$(PATH))$(ORIG_SHELL)) -x
+  WLAN_ShellDebugSHELL := SHELL='$$(warning Shell: ORIG_SHELL=$$(ORIG_SHELL) PATH=$$(PATH))$(ORIG_SHELL) -x'
+endif
+
+# Variables of general utility.
+WLAN_Perl := perl
+WLAN_Python := python
+WLAN_WINPFX ?= Z:
+
+# These macros are used to stash an extra copy of generated source files,
+# such that when a source release is made those files can be reconstituted
+# from the stash during builds. Required if the generating tools or inputs
+# are not shipped.
+define wlan_copy_to_gen
+  $(if $(WLAN_COPY_GEN),&& mkdir -p $(subst $(abspath $2),$(abspath $2/$(WLAN_GEN_BASEDIR)),$(dir $(abspath $1))) && \
+    cp -pv $1 $(subst $(abspath $2),$(abspath $2/$(WLAN_GEN_BASEDIR)),$(abspath $1).GEN))
+endef
+
+############################################################################
+# CLM function; Generates a rule to run ClmCompiler iff the XML exists.
+# USAGE: $(call WLAN_GenClmCompilerRule,target-dir,src-base[,flags])
+#     $1 is the directory where the generated .c file goes (it must exist)
+#     $2 gives the base of the WL driver tree (SRCBASE).
+#     $3 is an optional set of flags to pass to ClmCompiler.
+#   The ClmCompiler options are concatenated from three places.
+#     1) The optional $3 argument
+#     2) The make variable CLMCOMPEXTFLAGS which is by default --obfuscate
+#        but can be overridden AFTER the WLAN_GenClmCompilerRule usage
+#     3) --config $(CLM_TYPE) if ($CLM_TYPE) is defined.  CLM_TYPE
+#        represent the basename, without the .clm, of a ClmCompiler
+#        config that is expected to be in src/wl/clm/types directory.
+#        If $(CLM_TYPE) is defined, a dependency to that .clm will
+#        be added.
+#   The created ClmCompiler rule will use/depend on a xml file.  This will be
+# src/wl/clm/private/wlc_clm_data_$CLM_TYPE).xml if it exists else
+# components/clm/clm-private/wlc_clm_data.xml will be used.  This allows you
+# to use a xml file that corresponds to the .clm being used.
+#   This macro uses GNU make's eval function to generate an
+# explicit rule to generate a particular CLM data file each time
+# it's called. Make variables which should be evaluated during eval
+# processing get one $, those which must defer till "runtime" get $$.
+#   The "clm_compiled" phony target is provided for makefiles which need
+# to defer some other processing until CLM data is ready, and "clm_clean"
+# and "CLM_DATA_FILES" make it easier for internal client makefiles to
+# clean up CLM data (externally, this is treated as source and not removed).
+#   The outermost conditional allows this rule to become a no-op
+# in external settings where there is no XML input file while allowing
+# it to turn back on automatically if an XML file is provided.
+#   A vpath is used to find the XML input because this file is not allowed
+# to be present in external builds. Use of vpath allows it to be "poached"
+# from the internal build as necessary.
+#   Note: the .c file is listed with and without a path due to the way the
+# Linux kernel Makefiles generate .depend data.
+CLMCOMPEXTFLAGS := --obfuscate
+define WLAN_GenClmCompilerRule
+$(eval\
+.PHONY: clm_compiled clm_clean
+
+# The "mkdir -p foo 2>/dev/null || test -d foo || mkdir -p foo" logic below is
+# intended to defeat potential race conditions. If the first mkdir fails we
+# check whether we just lost the race to create it; if it still doesn't exist
+# there must be some other problem so we run mkdir again to generate
+# the appropriate error message and die.
+$1: ; mkdir -p $$@ 2>/dev/null || test -d $$@ || mkdir -p $$@
+vpath wlc_clm_data.c $1 $$(abspath $1)
+ifneq (,$(or $(wildcard $(addsuffix /../components/clm-private/wlc_clm_data.xml,$2 $2/../../src $2/../../../src)),$(wildcard $(addsuffix /wl/clm/private/wlc_clm_data_$(CLM_TYPE).xml,$2 $2/../../src $2/../../../src))))
+  vpath wlc_clm_data.xml $(wildcard $(addsuffix /../components/clm-private,$2 $2/../../src $2/../../../src))
+  vpath wlc_clm_data_$(CLM_TYPE).xml $(addsuffix /wl/clm/private,$2 $2/../../src $2/../../../src)
+  vpath %.clm $(addsuffix /wl/clm/types,$2 $2/../../src $2/../../../src)
+  $1/wlc_clm_data.c: \
+      $$(if $$(wildcard $2/wl/clm/private/wlc_clm_data_$$(CLM_TYPE).xml),$2/wl/clm/private/wlc_clm_data_$$(CLM_TYPE).xml,wlc_clm_data.xml) \
+      $2/../components/clm-api/include/wlc_clm_data.h \
+      $$(wildcard $2/../components/clm-bin/ClmCompiler.py) \
+      $$(if $$(CLM_TYPE),$$(CLM_TYPE).clm) \
+      | $1; \
+    @echo wlc_clm_data.c rule -- $$@: $$+ ;\
+    $$(strip $$(firstword $$(wildcard $$(addsuffix /components/clm-bin/ClmCompiler.py, $2/.. $2/../.. $2/../../..))) \
+      --clmapi_include_dir $$(firstword $$(wildcard $$(addsuffix components/clm-api/include, $2/../ $2/../../ $2/../../../ ))) \
+      --print_options --bcmwifi_include_dir $$(firstword $$(wildcard $$(addsuffix shared/bcmwifi/include, $2/ $2/../../src/ $2/../../../src/ ))) \
+      $$(if $$(CLM_TYPE),--config_file $$(lastword $$^)) $3 $(CLMCOMPEXTFLAGS) $$< $$@ $$(call wlan_copy_to_gen,$$@,$2))
+else
+  vpath %.GEN $(subst $(abspath $2),$(abspath $2/$(WLAN_GEN_BASEDIR)),$1) $(sort $(patsubst %/,%,$(dir $(wildcard $(subst $(abspath $2),$(abspath $2/$(WLAN_GEN_BASEDIR)),$(dir $1))*/*.GEN))))
+  $1/%: %.GEN ; cp -pv $$< $$@
+endif
+  clm_compiled: $1/wlc_clm_data.c
+  clm_clean:: ; $$(RM) $1/wlc_clm_data.c
+  CLM_DATA_FILES += $1/wlc_clm_data.c
+)
+endef
+
+################################################################
+# Generates rule that generates wlc_sar_tbl.c file
+# USAGE: $(call WLAN_GenSarTblRule,target-dir,src-base,[sar-files])
+# Arguments:
+# target-dir -- Directory where generated wlc_sar_tbl.c shall be put.
+# src-base   -- Top level 'src' directory. Strange manipulations with
+#               it within macro expansion are due to some strange
+#               peculiarities of Linux driver builds
+# sar_files  -- Space-separated list of base names of .csv files that
+#               contain SAR entries that shall be put to generated SAR
+#               table. Empty means use all files in src/wl/sar directory
+define WLAN_GenSarTblRule
+$(eval\
+$1/wlc_sar_tbl.c: ; $$(firstword $$(wildcard \
+    $$(addsuffix /components/tools/bin/sar_conv.py, $2/.. $2/../.. $2/../../..))) create_c \
+    --driver_dir $$(addsuffix /../.., $$(firstword $$(wildcard \
+    $$(addsuffix /include, $2 $2/../../src $2/../../../src)))) \
+    $$(addprefix $$(firstword $$(wildcard \
+    $$(addsuffix /wl/sar, $2 $2/../../src $2/../../../src)))/, \
+    $$(if $3,$3,*.csv)) $$@
+)
+endef
+
+################################################################
+
+endif	# _WLAN_COMMON_MK
diff --git a/wl/src/shared/bcm_app_utils.c b/wl/src/shared/bcm_app_utils.c
new file mode 100644
index 0000000..76e89b9
--- /dev/null
+++ b/wl/src/shared/bcm_app_utils.c
@@ -0,0 +1,1231 @@
+/*
+ * Misc utility routines used by kernel or app-level.
+ * Contents are wifi-specific, used by any kernel or app-level
+ * software that might want wifi things as it grows.
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcm_app_utils.c 625864 2016-03-18 00:12:54Z $
+ */
+
+#include <typedefs.h>
+
+#ifdef BCMDRIVER
+#include <osl.h>
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
+#else /* BCMDRIVER */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifndef ASSERT
+#define ASSERT(exp)
+#endif
+#endif /* BCMDRIVER */
+#include <bcmwifi_channels.h>
+
+#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
+#include <bcmstdlib.h>	/* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
+#endif
+
+#include <bcmutils.h>
+#include <wlioctl.h>
+#include <wlioctl_utils.h>
+
+#ifndef BCMDRIVER
+/*	Take an array of measurments representing a single channel over time and return
+	a summary. Currently implemented as a simple average but could easily evolve
+	into more cpomplex alogrithms.
+*/
+cca_congest_channel_req_t *
+cca_per_chan_summary(cca_congest_channel_req_t *input, cca_congest_channel_req_t *avg, bool percent)
+{
+	int sec;
+	cca_congest_t totals;
+
+	totals.duration  = 0;
+	totals.congest_ibss  = 0;
+	totals.congest_obss  = 0;
+	totals.interference  = 0;
+	avg->num_secs = 0;
+
+	for (sec = 0; sec < input->num_secs; sec++) {
+		if (input->secs[sec].duration) {
+			totals.duration += input->secs[sec].duration;
+			totals.congest_ibss += input->secs[sec].congest_ibss;
+			totals.congest_obss += input->secs[sec].congest_obss;
+			totals.interference += input->secs[sec].interference;
+			avg->num_secs++;
+		}
+	}
+	avg->chanspec = input->chanspec;
+
+	if (!avg->num_secs || !totals.duration)
+		return (avg);
+
+	if (percent) {
+		avg->secs[0].duration = totals.duration / avg->num_secs;
+		avg->secs[0].congest_ibss = totals.congest_ibss * 100/totals.duration;
+		avg->secs[0].congest_obss = totals.congest_obss * 100/totals.duration;
+		avg->secs[0].interference = totals.interference * 100/totals.duration;
+	} else {
+		avg->secs[0].duration = totals.duration / avg->num_secs;
+		avg->secs[0].congest_ibss = totals.congest_ibss / avg->num_secs;
+		avg->secs[0].congest_obss = totals.congest_obss / avg->num_secs;
+		avg->secs[0].interference = totals.interference / avg->num_secs;
+	}
+
+	return (avg);
+}
+
+static void
+cca_info(uint8 *bitmap, int num_bits, int *left, int *bit_pos)
+{
+	int i;
+	for (*left = 0, i = 0; i < num_bits; i++) {
+		if (isset(bitmap, i)) {
+			(*left)++;
+			*bit_pos = i;
+		}
+	}
+}
+
+static uint8
+spec_to_chan(chanspec_t chspec)
+{
+	uint8 center_ch, edge, primary, sb;
+
+	center_ch = CHSPEC_CHANNEL(chspec);
+
+	if (CHSPEC_BW_LE20(chspec)) {
+		return center_ch;
+	} else {
+		/* the lower edge of the wide channel is half the bw from
+		 * the center channel.
+		 */
+		if (CHSPEC_IS40(chspec)) {
+			edge = center_ch - CH_20MHZ_APART;
+		} else {
+			/* must be 80MHz (until we support more) */
+			ASSERT(CHSPEC_IS80(chspec));
+			edge = center_ch - CH_40MHZ_APART;
+		}
+
+		/* find the channel number of the lowest 20MHz primary channel */
+		primary = edge + CH_10MHZ_APART;
+
+		/* select the actual subband */
+		sb = (chspec & WL_CHANSPEC_CTL_SB_MASK) >> WL_CHANSPEC_CTL_SB_SHIFT;
+		primary = primary + sb * CH_20MHZ_APART;
+
+		return primary;
+	}
+}
+
+/*
+	Take an array of measumrements representing summaries of different channels.
+	Return a recomended channel.
+	Interference is evil, get rid of that first.
+	Then hunt for lowest Other bss traffic.
+	Don't forget that channels with low duration times may not have accurate readings.
+	For the moment, do not overwrite input array.
+*/
+int
+cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags, chanspec_t *answer)
+{
+	uint8 *bitmap = NULL;	/* 38 Max channels needs 5 bytes  = 40 */
+	int i, left, winner, ret_val = 0;
+	uint32 min_obss = 1 << 30;
+	uint bitmap_sz;
+
+	bitmap_sz = CEIL(num_chans, NBBY);
+	bitmap = (uint8 *)malloc(bitmap_sz);
+	if (bitmap == NULL) {
+		printf("unable to allocate memory\n");
+		return BCME_NOMEM;
+	}
+
+	memset(bitmap, 0, bitmap_sz);
+	/* Initially, all channels are up for consideration */
+	for (i = 0; i < num_chans; i++) {
+		if (input[i]->chanspec)
+			setbit(bitmap, i);
+	}
+	cca_info(bitmap, num_chans, &left, &i);
+	if (!left) {
+		ret_val = CCA_ERRNO_TOO_FEW;
+		goto f_exit;
+	}
+
+	/* Filter for 2.4 GHz Band */
+	if (flags & CCA_FLAG_2G_ONLY) {
+		for (i = 0; i < num_chans; i++) {
+			if (!CHSPEC_IS2G(input[i]->chanspec))
+				clrbit(bitmap, i);
+		}
+	}
+	cca_info(bitmap, num_chans, &left, &i);
+	if (!left) {
+		ret_val = CCA_ERRNO_BAND;
+		goto f_exit;
+	}
+
+	/* Filter for 5 GHz Band */
+	if (flags & CCA_FLAG_5G_ONLY) {
+		for (i = 0; i < num_chans; i++) {
+			if (!CHSPEC_IS5G(input[i]->chanspec))
+				clrbit(bitmap, i);
+		}
+	}
+	cca_info(bitmap, num_chans, &left, &i);
+	if (!left) {
+		ret_val = CCA_ERRNO_BAND;
+		goto f_exit;
+	}
+
+	/* Filter for Duration */
+	if (!(flags & CCA_FLAG_IGNORE_DURATION)) {
+		for (i = 0; i < num_chans; i++) {
+			if (input[i]->secs[0].duration < CCA_THRESH_MILLI)
+				clrbit(bitmap, i);
+		}
+	}
+	cca_info(bitmap, num_chans, &left, &i);
+	if (!left) {
+		ret_val = CCA_ERRNO_DURATION;
+		goto f_exit;
+	}
+
+	/* Filter for 1 6 11 on 2.4 Band */
+	if (flags &  CCA_FLAGS_PREFER_1_6_11) {
+		int tmp_channel = spec_to_chan(input[i]->chanspec);
+		int is2g = CHSPEC_IS2G(input[i]->chanspec);
+		for (i = 0; i < num_chans; i++) {
+			if (is2g && tmp_channel != 1 && tmp_channel != 6 && tmp_channel != 11)
+				clrbit(bitmap, i);
+		}
+	}
+	cca_info(bitmap, num_chans, &left, &i);
+	if (!left) {
+		ret_val = CCA_ERRNO_PREF_CHAN;
+		goto f_exit;
+	}
+
+	/* Toss high interference interference */
+	if (!(flags & CCA_FLAG_IGNORE_INTERFER)) {
+		for (i = 0; i < num_chans; i++) {
+			if (input[i]->secs[0].interference > CCA_THRESH_INTERFERE)
+				clrbit(bitmap, i);
+		}
+		cca_info(bitmap, num_chans, &left, &i);
+		if (!left) {
+			ret_val = CCA_ERRNO_INTERFER;
+			goto f_exit;
+		}
+	}
+
+	/* Now find lowest obss */
+	winner = 0;
+	for (i = 0; i < num_chans; i++) {
+		if (isset(bitmap, i) && input[i]->secs[0].congest_obss < min_obss) {
+			winner = i;
+			min_obss = input[i]->secs[0].congest_obss;
+		}
+	}
+	*answer = input[winner]->chanspec;
+	f_exit:
+	free(bitmap);	/* free the allocated memory for bitmap */
+	return ret_val;
+}
+#endif /* !BCMDRIVER */
+
+/* offset of cntmember by sizeof(uint32) from the first cnt variable, txframe. */
+#define IDX_IN_WL_CNT_VER_6_T(cntmember)		\
+	((OFFSETOF(wl_cnt_ver_6_t, cntmember) - OFFSETOF(wl_cnt_ver_6_t, txframe)) / sizeof(uint32))
+
+#define IDX_IN_WL_CNT_VER_7_T(cntmember)		\
+	((OFFSETOF(wl_cnt_ver_7_t, cntmember) - OFFSETOF(wl_cnt_ver_7_t, txframe)) / sizeof(uint32))
+
+#define IDX_IN_WL_CNT_VER_11_T(cntmember)		\
+	((OFFSETOF(wl_cnt_ver_11_t, cntmember) - OFFSETOF(wl_cnt_ver_11_t, txframe))	\
+	/ sizeof(uint32))
+
+/* Exclude version and length fields */
+#define NUM_OF_CNT_IN_WL_CNT_VER_6_T	\
+	((sizeof(wl_cnt_ver_6_t) - 2 * sizeof(uint16)) / sizeof(uint32))
+/* Exclude macstat cnt variables. wl_cnt_ver_6_t only has 62 macstat cnt variables. */
+#define NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T			\
+	(NUM_OF_CNT_IN_WL_CNT_VER_6_T - (WL_CNT_MCST_VAR_NUM - 2))
+
+/* Exclude version and length fields */
+#define NUM_OF_CNT_IN_WL_CNT_VER_7_T	\
+	((sizeof(wl_cnt_ver_7_t) - 2 * sizeof(uint16)) / sizeof(uint32))
+/* Exclude macstat cnt variables. wl_cnt_ver_7_t only has 61 macstat cnt variables. */
+#define NUM_OF_WLCCNT_IN_WL_CNT_VER_7_T			\
+	(NUM_OF_CNT_IN_WL_CNT_VER_7_T - (WL_CNT_MCST_VAR_NUM - 3))
+
+/* Exclude version and length fields */
+#define NUM_OF_CNT_IN_WL_CNT_VER_11_T	\
+	((sizeof(wl_cnt_ver_11_t) - 2 * sizeof(uint16)) / sizeof(uint32))
+/* Exclude 64 macstat cnt variables. */
+#define NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T		\
+	(NUM_OF_CNT_IN_WL_CNT_VER_11_T - WL_CNT_MCST_VAR_NUM)
+
+/* Index conversion table from wl_cnt_ver_6_t to wl_cnt_wlc_t */
+static const uint8 wlcntver6t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T] = {
+	IDX_IN_WL_CNT_VER_6_T(txframe),
+	IDX_IN_WL_CNT_VER_6_T(txbyte),
+	IDX_IN_WL_CNT_VER_6_T(txretrans),
+	IDX_IN_WL_CNT_VER_6_T(txerror),
+	IDX_IN_WL_CNT_VER_6_T(txctl),
+	IDX_IN_WL_CNT_VER_6_T(txprshort),
+	IDX_IN_WL_CNT_VER_6_T(txserr),
+	IDX_IN_WL_CNT_VER_6_T(txnobuf),
+	IDX_IN_WL_CNT_VER_6_T(txnoassoc),
+	IDX_IN_WL_CNT_VER_6_T(txrunt),
+	IDX_IN_WL_CNT_VER_6_T(txchit),
+	IDX_IN_WL_CNT_VER_6_T(txcmiss),
+	IDX_IN_WL_CNT_VER_6_T(txuflo),
+	IDX_IN_WL_CNT_VER_6_T(txphyerr),
+	IDX_IN_WL_CNT_VER_6_T(txphycrs),
+	IDX_IN_WL_CNT_VER_6_T(rxframe),
+	IDX_IN_WL_CNT_VER_6_T(rxbyte),
+	IDX_IN_WL_CNT_VER_6_T(rxerror),
+	IDX_IN_WL_CNT_VER_6_T(rxctl),
+	IDX_IN_WL_CNT_VER_6_T(rxnobuf),
+	IDX_IN_WL_CNT_VER_6_T(rxnondata),
+	IDX_IN_WL_CNT_VER_6_T(rxbadds),
+	IDX_IN_WL_CNT_VER_6_T(rxbadcm),
+	IDX_IN_WL_CNT_VER_6_T(rxfragerr),
+	IDX_IN_WL_CNT_VER_6_T(rxrunt),
+	IDX_IN_WL_CNT_VER_6_T(rxgiant),
+	IDX_IN_WL_CNT_VER_6_T(rxnoscb),
+	IDX_IN_WL_CNT_VER_6_T(rxbadproto),
+	IDX_IN_WL_CNT_VER_6_T(rxbadsrcmac),
+	IDX_IN_WL_CNT_VER_6_T(rxbadda),
+	IDX_IN_WL_CNT_VER_6_T(rxfilter),
+	IDX_IN_WL_CNT_VER_6_T(rxoflo),
+	IDX_IN_WL_CNT_VER_6_T(rxuflo),
+	IDX_IN_WL_CNT_VER_6_T(rxuflo) + 1,
+	IDX_IN_WL_CNT_VER_6_T(rxuflo) + 2,
+	IDX_IN_WL_CNT_VER_6_T(rxuflo) + 3,
+	IDX_IN_WL_CNT_VER_6_T(rxuflo) + 4,
+	IDX_IN_WL_CNT_VER_6_T(rxuflo) + 5,
+	IDX_IN_WL_CNT_VER_6_T(d11cnt_txrts_off),
+	IDX_IN_WL_CNT_VER_6_T(d11cnt_rxcrc_off),
+	IDX_IN_WL_CNT_VER_6_T(d11cnt_txnocts_off),
+	IDX_IN_WL_CNT_VER_6_T(dmade),
+	IDX_IN_WL_CNT_VER_6_T(dmada),
+	IDX_IN_WL_CNT_VER_6_T(dmape),
+	IDX_IN_WL_CNT_VER_6_T(reset),
+	IDX_IN_WL_CNT_VER_6_T(tbtt),
+	IDX_IN_WL_CNT_VER_6_T(txdmawar),
+	IDX_IN_WL_CNT_VER_6_T(pkt_callback_reg_fail),
+	IDX_IN_WL_CNT_VER_6_T(txfrag),
+	IDX_IN_WL_CNT_VER_6_T(txmulti),
+	IDX_IN_WL_CNT_VER_6_T(txfail),
+	IDX_IN_WL_CNT_VER_6_T(txretry),
+	IDX_IN_WL_CNT_VER_6_T(txretrie),
+	IDX_IN_WL_CNT_VER_6_T(rxdup),
+	IDX_IN_WL_CNT_VER_6_T(txrts),
+	IDX_IN_WL_CNT_VER_6_T(txnocts),
+	IDX_IN_WL_CNT_VER_6_T(txnoack),
+	IDX_IN_WL_CNT_VER_6_T(rxfrag),
+	IDX_IN_WL_CNT_VER_6_T(rxmulti),
+	IDX_IN_WL_CNT_VER_6_T(rxcrc),
+	IDX_IN_WL_CNT_VER_6_T(txfrmsnt),
+	IDX_IN_WL_CNT_VER_6_T(rxundec),
+	IDX_IN_WL_CNT_VER_6_T(tkipmicfaill),
+	IDX_IN_WL_CNT_VER_6_T(tkipcntrmsr),
+	IDX_IN_WL_CNT_VER_6_T(tkipreplay),
+	IDX_IN_WL_CNT_VER_6_T(ccmpfmterr),
+	IDX_IN_WL_CNT_VER_6_T(ccmpreplay),
+	IDX_IN_WL_CNT_VER_6_T(ccmpundec),
+	IDX_IN_WL_CNT_VER_6_T(fourwayfail),
+	IDX_IN_WL_CNT_VER_6_T(wepundec),
+	IDX_IN_WL_CNT_VER_6_T(wepicverr),
+	IDX_IN_WL_CNT_VER_6_T(decsuccess),
+	IDX_IN_WL_CNT_VER_6_T(tkipicverr),
+	IDX_IN_WL_CNT_VER_6_T(wepexcluded),
+	IDX_IN_WL_CNT_VER_6_T(txchanrej),
+	IDX_IN_WL_CNT_VER_6_T(psmwds),
+	IDX_IN_WL_CNT_VER_6_T(phywatchdog),
+	IDX_IN_WL_CNT_VER_6_T(prq_entries_handled),
+	IDX_IN_WL_CNT_VER_6_T(prq_undirected_entries),
+	IDX_IN_WL_CNT_VER_6_T(prq_bad_entries),
+	IDX_IN_WL_CNT_VER_6_T(atim_suppress_count),
+	IDX_IN_WL_CNT_VER_6_T(bcn_template_not_ready),
+	IDX_IN_WL_CNT_VER_6_T(bcn_template_not_ready_done),
+	IDX_IN_WL_CNT_VER_6_T(late_tbtt_dpc),
+	IDX_IN_WL_CNT_VER_6_T(rx1mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx2mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx5mbps5),
+	IDX_IN_WL_CNT_VER_6_T(rx6mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx9mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx11mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx12mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx18mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx24mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx36mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx48mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx54mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx108mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx162mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx216mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx270mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx324mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx378mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx432mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx486mbps),
+	IDX_IN_WL_CNT_VER_6_T(rx540mbps),
+	IDX_IN_WL_CNT_VER_6_T(rfdisable),
+	IDX_IN_WL_CNT_VER_6_T(txexptime),
+	IDX_IN_WL_CNT_VER_6_T(txmpdu_sgi),
+	IDX_IN_WL_CNT_VER_6_T(rxmpdu_sgi),
+	IDX_IN_WL_CNT_VER_6_T(txmpdu_stbc),
+	IDX_IN_WL_CNT_VER_6_T(rxmpdu_stbc),
+	IDX_IN_WL_CNT_VER_6_T(rxundec_mcst),
+	IDX_IN_WL_CNT_VER_6_T(tkipmicfaill_mcst),
+	IDX_IN_WL_CNT_VER_6_T(tkipcntrmsr_mcst),
+	IDX_IN_WL_CNT_VER_6_T(tkipreplay_mcst),
+	IDX_IN_WL_CNT_VER_6_T(ccmpfmterr_mcst),
+	IDX_IN_WL_CNT_VER_6_T(ccmpreplay_mcst),
+	IDX_IN_WL_CNT_VER_6_T(ccmpundec_mcst),
+	IDX_IN_WL_CNT_VER_6_T(fourwayfail_mcst),
+	IDX_IN_WL_CNT_VER_6_T(wepundec_mcst),
+	IDX_IN_WL_CNT_VER_6_T(wepicverr_mcst),
+	IDX_IN_WL_CNT_VER_6_T(decsuccess_mcst),
+	IDX_IN_WL_CNT_VER_6_T(tkipicverr_mcst),
+	IDX_IN_WL_CNT_VER_6_T(wepexcluded_mcst)
+};
+
+static const uint8 wlcntver7t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_7_T] = {
+	IDX_IN_WL_CNT_VER_7_T(txframe),
+	IDX_IN_WL_CNT_VER_7_T(txbyte),
+	IDX_IN_WL_CNT_VER_7_T(txretrans),
+	IDX_IN_WL_CNT_VER_7_T(txerror),
+	IDX_IN_WL_CNT_VER_7_T(txctl),
+	IDX_IN_WL_CNT_VER_7_T(txprshort),
+	IDX_IN_WL_CNT_VER_7_T(txserr),
+	IDX_IN_WL_CNT_VER_7_T(txnobuf),
+	IDX_IN_WL_CNT_VER_7_T(txnoassoc),
+	IDX_IN_WL_CNT_VER_7_T(txrunt),
+	IDX_IN_WL_CNT_VER_7_T(txchit),
+	IDX_IN_WL_CNT_VER_7_T(txcmiss),
+	IDX_IN_WL_CNT_VER_7_T(txuflo),
+	IDX_IN_WL_CNT_VER_7_T(txphyerr),
+	IDX_IN_WL_CNT_VER_7_T(txphycrs),
+	IDX_IN_WL_CNT_VER_7_T(rxframe),
+	IDX_IN_WL_CNT_VER_7_T(rxbyte),
+	IDX_IN_WL_CNT_VER_7_T(rxerror),
+	IDX_IN_WL_CNT_VER_7_T(rxctl),
+	IDX_IN_WL_CNT_VER_7_T(rxnobuf),
+	IDX_IN_WL_CNT_VER_7_T(rxnondata),
+	IDX_IN_WL_CNT_VER_7_T(rxbadds),
+	IDX_IN_WL_CNT_VER_7_T(rxbadcm),
+	IDX_IN_WL_CNT_VER_7_T(rxfragerr),
+	IDX_IN_WL_CNT_VER_7_T(rxrunt),
+	IDX_IN_WL_CNT_VER_7_T(rxgiant),
+	IDX_IN_WL_CNT_VER_7_T(rxnoscb),
+	IDX_IN_WL_CNT_VER_7_T(rxbadproto),
+	IDX_IN_WL_CNT_VER_7_T(rxbadsrcmac),
+	IDX_IN_WL_CNT_VER_7_T(rxbadda),
+	IDX_IN_WL_CNT_VER_7_T(rxfilter),
+	IDX_IN_WL_CNT_VER_7_T(rxoflo),
+	IDX_IN_WL_CNT_VER_7_T(rxuflo),
+	IDX_IN_WL_CNT_VER_7_T(rxuflo) + 1,
+	IDX_IN_WL_CNT_VER_7_T(rxuflo) + 2,
+	IDX_IN_WL_CNT_VER_7_T(rxuflo) + 3,
+	IDX_IN_WL_CNT_VER_7_T(rxuflo) + 4,
+	IDX_IN_WL_CNT_VER_7_T(rxuflo) + 5,
+	IDX_IN_WL_CNT_VER_7_T(d11cnt_txrts_off),
+	IDX_IN_WL_CNT_VER_7_T(d11cnt_rxcrc_off),
+	IDX_IN_WL_CNT_VER_7_T(d11cnt_txnocts_off),
+	IDX_IN_WL_CNT_VER_7_T(dmade),
+	IDX_IN_WL_CNT_VER_7_T(dmada),
+	IDX_IN_WL_CNT_VER_7_T(dmape),
+	IDX_IN_WL_CNT_VER_7_T(reset),
+	IDX_IN_WL_CNT_VER_7_T(tbtt),
+	IDX_IN_WL_CNT_VER_7_T(txdmawar),
+	IDX_IN_WL_CNT_VER_7_T(pkt_callback_reg_fail),
+	IDX_IN_WL_CNT_VER_7_T(txfrag),
+	IDX_IN_WL_CNT_VER_7_T(txmulti),
+	IDX_IN_WL_CNT_VER_7_T(txfail),
+	IDX_IN_WL_CNT_VER_7_T(txretry),
+	IDX_IN_WL_CNT_VER_7_T(txretrie),
+	IDX_IN_WL_CNT_VER_7_T(rxdup),
+	IDX_IN_WL_CNT_VER_7_T(txrts),
+	IDX_IN_WL_CNT_VER_7_T(txnocts),
+	IDX_IN_WL_CNT_VER_7_T(txnoack),
+	IDX_IN_WL_CNT_VER_7_T(rxfrag),
+	IDX_IN_WL_CNT_VER_7_T(rxmulti),
+	IDX_IN_WL_CNT_VER_7_T(rxcrc),
+	IDX_IN_WL_CNT_VER_7_T(txfrmsnt),
+	IDX_IN_WL_CNT_VER_7_T(rxundec),
+	IDX_IN_WL_CNT_VER_7_T(tkipmicfaill),
+	IDX_IN_WL_CNT_VER_7_T(tkipcntrmsr),
+	IDX_IN_WL_CNT_VER_7_T(tkipreplay),
+	IDX_IN_WL_CNT_VER_7_T(ccmpfmterr),
+	IDX_IN_WL_CNT_VER_7_T(ccmpreplay),
+	IDX_IN_WL_CNT_VER_7_T(ccmpundec),
+	IDX_IN_WL_CNT_VER_7_T(fourwayfail),
+	IDX_IN_WL_CNT_VER_7_T(wepundec),
+	IDX_IN_WL_CNT_VER_7_T(wepicverr),
+	IDX_IN_WL_CNT_VER_7_T(decsuccess),
+	IDX_IN_WL_CNT_VER_7_T(tkipicverr),
+	IDX_IN_WL_CNT_VER_7_T(wepexcluded),
+	IDX_IN_WL_CNT_VER_7_T(txchanrej),
+	IDX_IN_WL_CNT_VER_7_T(psmwds),
+	IDX_IN_WL_CNT_VER_7_T(phywatchdog),
+	IDX_IN_WL_CNT_VER_7_T(prq_entries_handled),
+	IDX_IN_WL_CNT_VER_7_T(prq_undirected_entries),
+	IDX_IN_WL_CNT_VER_7_T(prq_bad_entries),
+	IDX_IN_WL_CNT_VER_7_T(atim_suppress_count),
+	IDX_IN_WL_CNT_VER_7_T(bcn_template_not_ready),
+	IDX_IN_WL_CNT_VER_7_T(bcn_template_not_ready_done),
+	IDX_IN_WL_CNT_VER_7_T(late_tbtt_dpc),
+	IDX_IN_WL_CNT_VER_7_T(rx1mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx2mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx5mbps5),
+	IDX_IN_WL_CNT_VER_7_T(rx6mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx9mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx11mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx12mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx18mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx24mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx36mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx48mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx54mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx108mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx162mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx216mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx270mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx324mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx378mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx432mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx486mbps),
+	IDX_IN_WL_CNT_VER_7_T(rx540mbps),
+	IDX_IN_WL_CNT_VER_7_T(rfdisable),
+	IDX_IN_WL_CNT_VER_7_T(txexptime),
+	IDX_IN_WL_CNT_VER_7_T(txmpdu_sgi),
+	IDX_IN_WL_CNT_VER_7_T(rxmpdu_sgi),
+	IDX_IN_WL_CNT_VER_7_T(txmpdu_stbc),
+	IDX_IN_WL_CNT_VER_7_T(rxmpdu_stbc),
+	IDX_IN_WL_CNT_VER_7_T(rxundec_mcst),
+	IDX_IN_WL_CNT_VER_7_T(tkipmicfaill_mcst),
+	IDX_IN_WL_CNT_VER_7_T(tkipcntrmsr_mcst),
+	IDX_IN_WL_CNT_VER_7_T(tkipreplay_mcst),
+	IDX_IN_WL_CNT_VER_7_T(ccmpfmterr_mcst),
+	IDX_IN_WL_CNT_VER_7_T(ccmpreplay_mcst),
+	IDX_IN_WL_CNT_VER_7_T(ccmpundec_mcst),
+	IDX_IN_WL_CNT_VER_7_T(fourwayfail_mcst),
+	IDX_IN_WL_CNT_VER_7_T(wepundec_mcst),
+	IDX_IN_WL_CNT_VER_7_T(wepicverr_mcst),
+	IDX_IN_WL_CNT_VER_7_T(decsuccess_mcst),
+	IDX_IN_WL_CNT_VER_7_T(tkipicverr_mcst),
+	IDX_IN_WL_CNT_VER_7_T(wepexcluded_mcst)
+};
+
+/* Index conversion table from wl_cnt_ver_11_t to wl_cnt_wlc_t */
+static const uint8 wlcntver11t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T] = {
+	IDX_IN_WL_CNT_VER_11_T(txframe),
+	IDX_IN_WL_CNT_VER_11_T(txbyte),
+	IDX_IN_WL_CNT_VER_11_T(txretrans),
+	IDX_IN_WL_CNT_VER_11_T(txerror),
+	IDX_IN_WL_CNT_VER_11_T(txctl),
+	IDX_IN_WL_CNT_VER_11_T(txprshort),
+	IDX_IN_WL_CNT_VER_11_T(txserr),
+	IDX_IN_WL_CNT_VER_11_T(txnobuf),
+	IDX_IN_WL_CNT_VER_11_T(txnoassoc),
+	IDX_IN_WL_CNT_VER_11_T(txrunt),
+	IDX_IN_WL_CNT_VER_11_T(txchit),
+	IDX_IN_WL_CNT_VER_11_T(txcmiss),
+	IDX_IN_WL_CNT_VER_11_T(txuflo),
+	IDX_IN_WL_CNT_VER_11_T(txphyerr),
+	IDX_IN_WL_CNT_VER_11_T(txphycrs),
+	IDX_IN_WL_CNT_VER_11_T(rxframe),
+	IDX_IN_WL_CNT_VER_11_T(rxbyte),
+	IDX_IN_WL_CNT_VER_11_T(rxerror),
+	IDX_IN_WL_CNT_VER_11_T(rxctl),
+	IDX_IN_WL_CNT_VER_11_T(rxnobuf),
+	IDX_IN_WL_CNT_VER_11_T(rxnondata),
+	IDX_IN_WL_CNT_VER_11_T(rxbadds),
+	IDX_IN_WL_CNT_VER_11_T(rxbadcm),
+	IDX_IN_WL_CNT_VER_11_T(rxfragerr),
+	IDX_IN_WL_CNT_VER_11_T(rxrunt),
+	IDX_IN_WL_CNT_VER_11_T(rxgiant),
+	IDX_IN_WL_CNT_VER_11_T(rxnoscb),
+	IDX_IN_WL_CNT_VER_11_T(rxbadproto),
+	IDX_IN_WL_CNT_VER_11_T(rxbadsrcmac),
+	IDX_IN_WL_CNT_VER_11_T(rxbadda),
+	IDX_IN_WL_CNT_VER_11_T(rxfilter),
+	IDX_IN_WL_CNT_VER_11_T(rxoflo),
+	IDX_IN_WL_CNT_VER_11_T(rxuflo),
+	IDX_IN_WL_CNT_VER_11_T(rxuflo) + 1,
+	IDX_IN_WL_CNT_VER_11_T(rxuflo) + 2,
+	IDX_IN_WL_CNT_VER_11_T(rxuflo) + 3,
+	IDX_IN_WL_CNT_VER_11_T(rxuflo) + 4,
+	IDX_IN_WL_CNT_VER_11_T(rxuflo) + 5,
+	IDX_IN_WL_CNT_VER_11_T(d11cnt_txrts_off),
+	IDX_IN_WL_CNT_VER_11_T(d11cnt_rxcrc_off),
+	IDX_IN_WL_CNT_VER_11_T(d11cnt_txnocts_off),
+	IDX_IN_WL_CNT_VER_11_T(dmade),
+	IDX_IN_WL_CNT_VER_11_T(dmada),
+	IDX_IN_WL_CNT_VER_11_T(dmape),
+	IDX_IN_WL_CNT_VER_11_T(reset),
+	IDX_IN_WL_CNT_VER_11_T(tbtt),
+	IDX_IN_WL_CNT_VER_11_T(txdmawar),
+	IDX_IN_WL_CNT_VER_11_T(pkt_callback_reg_fail),
+	IDX_IN_WL_CNT_VER_11_T(txfrag),
+	IDX_IN_WL_CNT_VER_11_T(txmulti),
+	IDX_IN_WL_CNT_VER_11_T(txfail),
+	IDX_IN_WL_CNT_VER_11_T(txretry),
+	IDX_IN_WL_CNT_VER_11_T(txretrie),
+	IDX_IN_WL_CNT_VER_11_T(rxdup),
+	IDX_IN_WL_CNT_VER_11_T(txrts),
+	IDX_IN_WL_CNT_VER_11_T(txnocts),
+	IDX_IN_WL_CNT_VER_11_T(txnoack),
+	IDX_IN_WL_CNT_VER_11_T(rxfrag),
+	IDX_IN_WL_CNT_VER_11_T(rxmulti),
+	IDX_IN_WL_CNT_VER_11_T(rxcrc),
+	IDX_IN_WL_CNT_VER_11_T(txfrmsnt),
+	IDX_IN_WL_CNT_VER_11_T(rxundec),
+	IDX_IN_WL_CNT_VER_11_T(tkipmicfaill),
+	IDX_IN_WL_CNT_VER_11_T(tkipcntrmsr),
+	IDX_IN_WL_CNT_VER_11_T(tkipreplay),
+	IDX_IN_WL_CNT_VER_11_T(ccmpfmterr),
+	IDX_IN_WL_CNT_VER_11_T(ccmpreplay),
+	IDX_IN_WL_CNT_VER_11_T(ccmpundec),
+	IDX_IN_WL_CNT_VER_11_T(fourwayfail),
+	IDX_IN_WL_CNT_VER_11_T(wepundec),
+	IDX_IN_WL_CNT_VER_11_T(wepicverr),
+	IDX_IN_WL_CNT_VER_11_T(decsuccess),
+	IDX_IN_WL_CNT_VER_11_T(tkipicverr),
+	IDX_IN_WL_CNT_VER_11_T(wepexcluded),
+	IDX_IN_WL_CNT_VER_11_T(txchanrej),
+	IDX_IN_WL_CNT_VER_11_T(psmwds),
+	IDX_IN_WL_CNT_VER_11_T(phywatchdog),
+	IDX_IN_WL_CNT_VER_11_T(prq_entries_handled),
+	IDX_IN_WL_CNT_VER_11_T(prq_undirected_entries),
+	IDX_IN_WL_CNT_VER_11_T(prq_bad_entries),
+	IDX_IN_WL_CNT_VER_11_T(atim_suppress_count),
+	IDX_IN_WL_CNT_VER_11_T(bcn_template_not_ready),
+	IDX_IN_WL_CNT_VER_11_T(bcn_template_not_ready_done),
+	IDX_IN_WL_CNT_VER_11_T(late_tbtt_dpc),
+	IDX_IN_WL_CNT_VER_11_T(rx1mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx2mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx5mbps5),
+	IDX_IN_WL_CNT_VER_11_T(rx6mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx9mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx11mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx12mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx18mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx24mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx36mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx48mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx54mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx108mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx162mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx216mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx270mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx324mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx378mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx432mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx486mbps),
+	IDX_IN_WL_CNT_VER_11_T(rx540mbps),
+	IDX_IN_WL_CNT_VER_11_T(rfdisable),
+	IDX_IN_WL_CNT_VER_11_T(txexptime),
+	IDX_IN_WL_CNT_VER_11_T(txmpdu_sgi),
+	IDX_IN_WL_CNT_VER_11_T(rxmpdu_sgi),
+	IDX_IN_WL_CNT_VER_11_T(txmpdu_stbc),
+	IDX_IN_WL_CNT_VER_11_T(rxmpdu_stbc),
+	IDX_IN_WL_CNT_VER_11_T(rxundec_mcst),
+	IDX_IN_WL_CNT_VER_11_T(tkipmicfaill_mcst),
+	IDX_IN_WL_CNT_VER_11_T(tkipcntrmsr_mcst),
+	IDX_IN_WL_CNT_VER_11_T(tkipreplay_mcst),
+	IDX_IN_WL_CNT_VER_11_T(ccmpfmterr_mcst),
+	IDX_IN_WL_CNT_VER_11_T(ccmpreplay_mcst),
+	IDX_IN_WL_CNT_VER_11_T(ccmpundec_mcst),
+	IDX_IN_WL_CNT_VER_11_T(fourwayfail_mcst),
+	IDX_IN_WL_CNT_VER_11_T(wepundec_mcst),
+	IDX_IN_WL_CNT_VER_11_T(wepicverr_mcst),
+	IDX_IN_WL_CNT_VER_11_T(decsuccess_mcst),
+	IDX_IN_WL_CNT_VER_11_T(tkipicverr_mcst),
+	IDX_IN_WL_CNT_VER_11_T(wepexcluded_mcst),
+	IDX_IN_WL_CNT_VER_11_T(dma_hang),
+	IDX_IN_WL_CNT_VER_11_T(reinit),
+	IDX_IN_WL_CNT_VER_11_T(pstatxucast),
+	IDX_IN_WL_CNT_VER_11_T(pstatxnoassoc),
+	IDX_IN_WL_CNT_VER_11_T(pstarxucast),
+	IDX_IN_WL_CNT_VER_11_T(pstarxbcmc),
+	IDX_IN_WL_CNT_VER_11_T(pstatxbcmc),
+	IDX_IN_WL_CNT_VER_11_T(cso_passthrough),
+	IDX_IN_WL_CNT_VER_11_T(cso_normal),
+	IDX_IN_WL_CNT_VER_11_T(chained),
+	IDX_IN_WL_CNT_VER_11_T(chainedsz1),
+	IDX_IN_WL_CNT_VER_11_T(unchained),
+	IDX_IN_WL_CNT_VER_11_T(maxchainsz),
+	IDX_IN_WL_CNT_VER_11_T(currchainsz),
+	IDX_IN_WL_CNT_VER_11_T(pciereset),
+	IDX_IN_WL_CNT_VER_11_T(cfgrestore),
+	IDX_IN_WL_CNT_VER_11_T(reinitreason),
+	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 1,
+	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 2,
+	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 3,
+	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 4,
+	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 5,
+	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 6,
+	IDX_IN_WL_CNT_VER_11_T(reinitreason) + 7,
+	IDX_IN_WL_CNT_VER_11_T(rxrtry),
+	IDX_IN_WL_CNT_VER_11_T(rxmpdu_mu),
+	IDX_IN_WL_CNT_VER_11_T(txbar),
+	IDX_IN_WL_CNT_VER_11_T(rxbar),
+	IDX_IN_WL_CNT_VER_11_T(txpspoll),
+	IDX_IN_WL_CNT_VER_11_T(rxpspoll),
+	IDX_IN_WL_CNT_VER_11_T(txnull),
+	IDX_IN_WL_CNT_VER_11_T(rxnull),
+	IDX_IN_WL_CNT_VER_11_T(txqosnull),
+	IDX_IN_WL_CNT_VER_11_T(rxqosnull),
+	IDX_IN_WL_CNT_VER_11_T(txassocreq),
+	IDX_IN_WL_CNT_VER_11_T(rxassocreq),
+	IDX_IN_WL_CNT_VER_11_T(txreassocreq),
+	IDX_IN_WL_CNT_VER_11_T(rxreassocreq),
+	IDX_IN_WL_CNT_VER_11_T(txdisassoc),
+	IDX_IN_WL_CNT_VER_11_T(rxdisassoc),
+	IDX_IN_WL_CNT_VER_11_T(txassocrsp),
+	IDX_IN_WL_CNT_VER_11_T(rxassocrsp),
+	IDX_IN_WL_CNT_VER_11_T(txreassocrsp),
+	IDX_IN_WL_CNT_VER_11_T(rxreassocrsp),
+	IDX_IN_WL_CNT_VER_11_T(txauth),
+	IDX_IN_WL_CNT_VER_11_T(rxauth),
+	IDX_IN_WL_CNT_VER_11_T(txdeauth),
+	IDX_IN_WL_CNT_VER_11_T(rxdeauth),
+	IDX_IN_WL_CNT_VER_11_T(txprobereq),
+	IDX_IN_WL_CNT_VER_11_T(rxprobereq),
+	IDX_IN_WL_CNT_VER_11_T(txprobersp),
+	IDX_IN_WL_CNT_VER_11_T(rxprobersp),
+	IDX_IN_WL_CNT_VER_11_T(txaction),
+	IDX_IN_WL_CNT_VER_11_T(rxaction),
+	IDX_IN_WL_CNT_VER_11_T(ampdu_wds),
+	IDX_IN_WL_CNT_VER_11_T(txlost),
+	IDX_IN_WL_CNT_VER_11_T(txdatamcast),
+	IDX_IN_WL_CNT_VER_11_T(txdatabcast)
+};
+
+/* Index conversion table from wl_cnt_ver_11_t to
+ * either wl_cnt_ge40mcst_v1_t or wl_cnt_lt40mcst_v1_t
+ */
+static const uint8 wlcntver11t_to_wlcntXX40mcstv1t[WL_CNT_MCST_VAR_NUM] = {
+	IDX_IN_WL_CNT_VER_11_T(txallfrm),
+	IDX_IN_WL_CNT_VER_11_T(txrtsfrm),
+	IDX_IN_WL_CNT_VER_11_T(txctsfrm),
+	IDX_IN_WL_CNT_VER_11_T(txackfrm),
+	IDX_IN_WL_CNT_VER_11_T(txdnlfrm),
+	IDX_IN_WL_CNT_VER_11_T(txbcnfrm),
+	IDX_IN_WL_CNT_VER_11_T(txfunfl),
+	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 1,
+	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 2,
+	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 3,
+	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 4,
+	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 5,
+	IDX_IN_WL_CNT_VER_11_T(txfbw),
+	IDX_IN_WL_CNT_VER_11_T(txmpdu),
+	IDX_IN_WL_CNT_VER_11_T(txtplunfl),
+	IDX_IN_WL_CNT_VER_11_T(txphyerror),
+	IDX_IN_WL_CNT_VER_11_T(pktengrxducast),
+	IDX_IN_WL_CNT_VER_11_T(pktengrxdmcast),
+	IDX_IN_WL_CNT_VER_11_T(rxfrmtoolong),
+	IDX_IN_WL_CNT_VER_11_T(rxfrmtooshrt),
+	IDX_IN_WL_CNT_VER_11_T(rxinvmachdr),
+	IDX_IN_WL_CNT_VER_11_T(rxbadfcs),
+	IDX_IN_WL_CNT_VER_11_T(rxbadplcp),
+	IDX_IN_WL_CNT_VER_11_T(rxcrsglitch),
+	IDX_IN_WL_CNT_VER_11_T(rxstrt),
+	IDX_IN_WL_CNT_VER_11_T(rxdfrmucastmbss),
+	IDX_IN_WL_CNT_VER_11_T(rxmfrmucastmbss),
+	IDX_IN_WL_CNT_VER_11_T(rxcfrmucast),
+	IDX_IN_WL_CNT_VER_11_T(rxrtsucast),
+	IDX_IN_WL_CNT_VER_11_T(rxctsucast),
+	IDX_IN_WL_CNT_VER_11_T(rxackucast),
+	IDX_IN_WL_CNT_VER_11_T(rxdfrmocast),
+	IDX_IN_WL_CNT_VER_11_T(rxmfrmocast),
+	IDX_IN_WL_CNT_VER_11_T(rxcfrmocast),
+	IDX_IN_WL_CNT_VER_11_T(rxrtsocast),
+	IDX_IN_WL_CNT_VER_11_T(rxctsocast),
+	IDX_IN_WL_CNT_VER_11_T(rxdfrmmcast),
+	IDX_IN_WL_CNT_VER_11_T(rxmfrmmcast),
+	IDX_IN_WL_CNT_VER_11_T(rxcfrmmcast),
+	IDX_IN_WL_CNT_VER_11_T(rxbeaconmbss),
+	IDX_IN_WL_CNT_VER_11_T(rxdfrmucastobss),
+	IDX_IN_WL_CNT_VER_11_T(rxbeaconobss),
+	IDX_IN_WL_CNT_VER_11_T(rxrsptmout),
+	IDX_IN_WL_CNT_VER_11_T(bcntxcancl),
+	IDX_IN_WL_CNT_VER_11_T(rxnodelim),
+	IDX_IN_WL_CNT_VER_11_T(rxf0ovfl),
+	IDX_IN_WL_CNT_VER_11_T(rxf1ovfl),
+	IDX_IN_WL_CNT_VER_11_T(rxf2ovfl),
+	IDX_IN_WL_CNT_VER_11_T(txsfovfl),
+	IDX_IN_WL_CNT_VER_11_T(pmqovfl),
+	IDX_IN_WL_CNT_VER_11_T(rxcgprqfrm),
+	IDX_IN_WL_CNT_VER_11_T(rxcgprsqovfl),
+	IDX_IN_WL_CNT_VER_11_T(txcgprsfail),
+	IDX_IN_WL_CNT_VER_11_T(txcgprssuc),
+	IDX_IN_WL_CNT_VER_11_T(prs_timeout),
+	IDX_IN_WL_CNT_VER_11_T(rxnack),
+	IDX_IN_WL_CNT_VER_11_T(frmscons),
+	IDX_IN_WL_CNT_VER_11_T(txnack),
+	IDX_IN_WL_CNT_VER_11_T(rxback),
+	IDX_IN_WL_CNT_VER_11_T(txback),
+	IDX_IN_WL_CNT_VER_11_T(bphy_rxcrsglitch),
+	IDX_IN_WL_CNT_VER_11_T(rxdrop20s),
+	IDX_IN_WL_CNT_VER_11_T(rxtoolate),
+	IDX_IN_WL_CNT_VER_11_T(bphy_badplcp)
+};
+
+/* For mcst offsets that were not used. (2 Pads) */
+#define INVALID_MCST_IDX ((uint8)(-1))
+/* Index conversion table from wl_cnt_ver_11_t to wl_cnt_v_le10_mcst_t */
+static const uint8 wlcntver11t_to_wlcntvle10mcstt[WL_CNT_MCST_VAR_NUM] = {
+	IDX_IN_WL_CNT_VER_11_T(txallfrm),
+	IDX_IN_WL_CNT_VER_11_T(txrtsfrm),
+	IDX_IN_WL_CNT_VER_11_T(txctsfrm),
+	IDX_IN_WL_CNT_VER_11_T(txackfrm),
+	IDX_IN_WL_CNT_VER_11_T(txdnlfrm),
+	IDX_IN_WL_CNT_VER_11_T(txbcnfrm),
+	IDX_IN_WL_CNT_VER_11_T(txfunfl),
+	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 1,
+	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 2,
+	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 3,
+	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 4,
+	IDX_IN_WL_CNT_VER_11_T(txfunfl) + 5,
+	IDX_IN_WL_CNT_VER_11_T(txfbw),
+	INVALID_MCST_IDX,
+	IDX_IN_WL_CNT_VER_11_T(txtplunfl),
+	IDX_IN_WL_CNT_VER_11_T(txphyerror),
+	IDX_IN_WL_CNT_VER_11_T(pktengrxducast),
+	IDX_IN_WL_CNT_VER_11_T(pktengrxdmcast),
+	IDX_IN_WL_CNT_VER_11_T(rxfrmtoolong),
+	IDX_IN_WL_CNT_VER_11_T(rxfrmtooshrt),
+	IDX_IN_WL_CNT_VER_11_T(rxinvmachdr),
+	IDX_IN_WL_CNT_VER_11_T(rxbadfcs),
+	IDX_IN_WL_CNT_VER_11_T(rxbadplcp),
+	IDX_IN_WL_CNT_VER_11_T(rxcrsglitch),
+	IDX_IN_WL_CNT_VER_11_T(rxstrt),
+	IDX_IN_WL_CNT_VER_11_T(rxdfrmucastmbss),
+	IDX_IN_WL_CNT_VER_11_T(rxmfrmucastmbss),
+	IDX_IN_WL_CNT_VER_11_T(rxcfrmucast),
+	IDX_IN_WL_CNT_VER_11_T(rxrtsucast),
+	IDX_IN_WL_CNT_VER_11_T(rxctsucast),
+	IDX_IN_WL_CNT_VER_11_T(rxackucast),
+	IDX_IN_WL_CNT_VER_11_T(rxdfrmocast),
+	IDX_IN_WL_CNT_VER_11_T(rxmfrmocast),
+	IDX_IN_WL_CNT_VER_11_T(rxcfrmocast),
+	IDX_IN_WL_CNT_VER_11_T(rxrtsocast),
+	IDX_IN_WL_CNT_VER_11_T(rxctsocast),
+	IDX_IN_WL_CNT_VER_11_T(rxdfrmmcast),
+	IDX_IN_WL_CNT_VER_11_T(rxmfrmmcast),
+	IDX_IN_WL_CNT_VER_11_T(rxcfrmmcast),
+	IDX_IN_WL_CNT_VER_11_T(rxbeaconmbss),
+	IDX_IN_WL_CNT_VER_11_T(rxdfrmucastobss),
+	IDX_IN_WL_CNT_VER_11_T(rxbeaconobss),
+	IDX_IN_WL_CNT_VER_11_T(rxrsptmout),
+	IDX_IN_WL_CNT_VER_11_T(bcntxcancl),
+	INVALID_MCST_IDX,
+	IDX_IN_WL_CNT_VER_11_T(rxf0ovfl),
+	IDX_IN_WL_CNT_VER_11_T(rxf1ovfl),
+	IDX_IN_WL_CNT_VER_11_T(rxf2ovfl),
+	IDX_IN_WL_CNT_VER_11_T(txsfovfl),
+	IDX_IN_WL_CNT_VER_11_T(pmqovfl),
+	IDX_IN_WL_CNT_VER_11_T(rxcgprqfrm),
+	IDX_IN_WL_CNT_VER_11_T(rxcgprsqovfl),
+	IDX_IN_WL_CNT_VER_11_T(txcgprsfail),
+	IDX_IN_WL_CNT_VER_11_T(txcgprssuc),
+	IDX_IN_WL_CNT_VER_11_T(prs_timeout),
+	IDX_IN_WL_CNT_VER_11_T(rxnack),
+	IDX_IN_WL_CNT_VER_11_T(frmscons),
+	IDX_IN_WL_CNT_VER_11_T(txnack),
+	IDX_IN_WL_CNT_VER_11_T(rxback),
+	IDX_IN_WL_CNT_VER_11_T(txback),
+	IDX_IN_WL_CNT_VER_11_T(bphy_rxcrsglitch),
+	IDX_IN_WL_CNT_VER_11_T(rxdrop20s),
+	IDX_IN_WL_CNT_VER_11_T(rxtoolate),
+	IDX_IN_WL_CNT_VER_11_T(bphy_badplcp)
+};
+
+/* Index conversion table from wl_cnt_ver_7_t to wl_cnt_v_le10_mcst_t */
+static const uint8 wlcntver7t_to_wlcntvle10mcstt[WL_CNT_MCST_VAR_NUM] = {
+	IDX_IN_WL_CNT_VER_7_T(txallfrm),
+	IDX_IN_WL_CNT_VER_7_T(txrtsfrm),
+	IDX_IN_WL_CNT_VER_7_T(txctsfrm),
+	IDX_IN_WL_CNT_VER_7_T(txackfrm),
+	IDX_IN_WL_CNT_VER_7_T(txdnlfrm),
+	IDX_IN_WL_CNT_VER_7_T(txbcnfrm),
+	IDX_IN_WL_CNT_VER_7_T(txfunfl),
+	IDX_IN_WL_CNT_VER_7_T(txfunfl) + 1,
+	IDX_IN_WL_CNT_VER_7_T(txfunfl) + 2,
+	IDX_IN_WL_CNT_VER_7_T(txfunfl) + 3,
+	IDX_IN_WL_CNT_VER_7_T(txfunfl) + 4,
+	IDX_IN_WL_CNT_VER_7_T(txfunfl) + 5,
+	INVALID_MCST_IDX,
+	INVALID_MCST_IDX,
+	IDX_IN_WL_CNT_VER_7_T(txtplunfl),
+	IDX_IN_WL_CNT_VER_7_T(txphyerror),
+	IDX_IN_WL_CNT_VER_7_T(pktengrxducast),
+	IDX_IN_WL_CNT_VER_7_T(pktengrxdmcast),
+	IDX_IN_WL_CNT_VER_7_T(rxfrmtoolong),
+	IDX_IN_WL_CNT_VER_7_T(rxfrmtooshrt),
+	IDX_IN_WL_CNT_VER_7_T(rxinvmachdr),
+	IDX_IN_WL_CNT_VER_7_T(rxbadfcs),
+	IDX_IN_WL_CNT_VER_7_T(rxbadplcp),
+	IDX_IN_WL_CNT_VER_7_T(rxcrsglitch),
+	IDX_IN_WL_CNT_VER_7_T(rxstrt),
+	IDX_IN_WL_CNT_VER_7_T(rxdfrmucastmbss),
+	IDX_IN_WL_CNT_VER_7_T(rxmfrmucastmbss),
+	IDX_IN_WL_CNT_VER_7_T(rxcfrmucast),
+	IDX_IN_WL_CNT_VER_7_T(rxrtsucast),
+	IDX_IN_WL_CNT_VER_7_T(rxctsucast),
+	IDX_IN_WL_CNT_VER_7_T(rxackucast),
+	IDX_IN_WL_CNT_VER_7_T(rxdfrmocast),
+	IDX_IN_WL_CNT_VER_7_T(rxmfrmocast),
+	IDX_IN_WL_CNT_VER_7_T(rxcfrmocast),
+	IDX_IN_WL_CNT_VER_7_T(rxrtsocast),
+	IDX_IN_WL_CNT_VER_7_T(rxctsocast),
+	IDX_IN_WL_CNT_VER_7_T(rxdfrmmcast),
+	IDX_IN_WL_CNT_VER_7_T(rxmfrmmcast),
+	IDX_IN_WL_CNT_VER_7_T(rxcfrmmcast),
+	IDX_IN_WL_CNT_VER_7_T(rxbeaconmbss),
+	IDX_IN_WL_CNT_VER_7_T(rxdfrmucastobss),
+	IDX_IN_WL_CNT_VER_7_T(rxbeaconobss),
+	IDX_IN_WL_CNT_VER_7_T(rxrsptmout),
+	IDX_IN_WL_CNT_VER_7_T(bcntxcancl),
+	INVALID_MCST_IDX,
+	IDX_IN_WL_CNT_VER_7_T(rxf0ovfl),
+	IDX_IN_WL_CNT_VER_7_T(rxf1ovfl),
+	IDX_IN_WL_CNT_VER_7_T(rxf2ovfl),
+	IDX_IN_WL_CNT_VER_7_T(txsfovfl),
+	IDX_IN_WL_CNT_VER_7_T(pmqovfl),
+	IDX_IN_WL_CNT_VER_7_T(rxcgprqfrm),
+	IDX_IN_WL_CNT_VER_7_T(rxcgprsqovfl),
+	IDX_IN_WL_CNT_VER_7_T(txcgprsfail),
+	IDX_IN_WL_CNT_VER_7_T(txcgprssuc),
+	IDX_IN_WL_CNT_VER_7_T(prs_timeout),
+	IDX_IN_WL_CNT_VER_7_T(rxnack),
+	IDX_IN_WL_CNT_VER_7_T(frmscons),
+	IDX_IN_WL_CNT_VER_7_T(txnack),
+	INVALID_MCST_IDX,
+	INVALID_MCST_IDX,
+	IDX_IN_WL_CNT_VER_7_T(bphy_rxcrsglitch),
+	INVALID_MCST_IDX,
+	INVALID_MCST_IDX,
+	INVALID_MCST_IDX
+};
+
+/* Index conversion table from wl_cnt_ver_6_t to wl_cnt_v_le10_mcst_t */
+static const uint8 wlcntver6t_to_wlcntvle10mcstt[WL_CNT_MCST_VAR_NUM] = {
+	IDX_IN_WL_CNT_VER_6_T(txallfrm),
+	IDX_IN_WL_CNT_VER_6_T(txrtsfrm),
+	IDX_IN_WL_CNT_VER_6_T(txctsfrm),
+	IDX_IN_WL_CNT_VER_6_T(txackfrm),
+	IDX_IN_WL_CNT_VER_6_T(txdnlfrm),
+	IDX_IN_WL_CNT_VER_6_T(txbcnfrm),
+	IDX_IN_WL_CNT_VER_6_T(txfunfl),
+	IDX_IN_WL_CNT_VER_6_T(txfunfl) + 1,
+	IDX_IN_WL_CNT_VER_6_T(txfunfl) + 2,
+	IDX_IN_WL_CNT_VER_6_T(txfunfl) + 3,
+	IDX_IN_WL_CNT_VER_6_T(txfunfl) + 4,
+	IDX_IN_WL_CNT_VER_6_T(txfunfl) + 5,
+	IDX_IN_WL_CNT_VER_6_T(txfbw),
+	INVALID_MCST_IDX,
+	IDX_IN_WL_CNT_VER_6_T(txtplunfl),
+	IDX_IN_WL_CNT_VER_6_T(txphyerror),
+	IDX_IN_WL_CNT_VER_6_T(pktengrxducast),
+	IDX_IN_WL_CNT_VER_6_T(pktengrxdmcast),
+	IDX_IN_WL_CNT_VER_6_T(rxfrmtoolong),
+	IDX_IN_WL_CNT_VER_6_T(rxfrmtooshrt),
+	IDX_IN_WL_CNT_VER_6_T(rxinvmachdr),
+	IDX_IN_WL_CNT_VER_6_T(rxbadfcs),
+	IDX_IN_WL_CNT_VER_6_T(rxbadplcp),
+	IDX_IN_WL_CNT_VER_6_T(rxcrsglitch),
+	IDX_IN_WL_CNT_VER_6_T(rxstrt),
+	IDX_IN_WL_CNT_VER_6_T(rxdfrmucastmbss),
+	IDX_IN_WL_CNT_VER_6_T(rxmfrmucastmbss),
+	IDX_IN_WL_CNT_VER_6_T(rxcfrmucast),
+	IDX_IN_WL_CNT_VER_6_T(rxrtsucast),
+	IDX_IN_WL_CNT_VER_6_T(rxctsucast),
+	IDX_IN_WL_CNT_VER_6_T(rxackucast),
+	IDX_IN_WL_CNT_VER_6_T(rxdfrmocast),
+	IDX_IN_WL_CNT_VER_6_T(rxmfrmocast),
+	IDX_IN_WL_CNT_VER_6_T(rxcfrmocast),
+	IDX_IN_WL_CNT_VER_6_T(rxrtsocast),
+	IDX_IN_WL_CNT_VER_6_T(rxctsocast),
+	IDX_IN_WL_CNT_VER_6_T(rxdfrmmcast),
+	IDX_IN_WL_CNT_VER_6_T(rxmfrmmcast),
+	IDX_IN_WL_CNT_VER_6_T(rxcfrmmcast),
+	IDX_IN_WL_CNT_VER_6_T(rxbeaconmbss),
+	IDX_IN_WL_CNT_VER_6_T(rxdfrmucastobss),
+	IDX_IN_WL_CNT_VER_6_T(rxbeaconobss),
+	IDX_IN_WL_CNT_VER_6_T(rxrsptmout),
+	IDX_IN_WL_CNT_VER_6_T(bcntxcancl),
+	INVALID_MCST_IDX,
+	IDX_IN_WL_CNT_VER_6_T(rxf0ovfl),
+	IDX_IN_WL_CNT_VER_6_T(rxf1ovfl),
+	IDX_IN_WL_CNT_VER_6_T(rxf2ovfl),
+	IDX_IN_WL_CNT_VER_6_T(txsfovfl),
+	IDX_IN_WL_CNT_VER_6_T(pmqovfl),
+	IDX_IN_WL_CNT_VER_6_T(rxcgprqfrm),
+	IDX_IN_WL_CNT_VER_6_T(rxcgprsqovfl),
+	IDX_IN_WL_CNT_VER_6_T(txcgprsfail),
+	IDX_IN_WL_CNT_VER_6_T(txcgprssuc),
+	IDX_IN_WL_CNT_VER_6_T(prs_timeout),
+	IDX_IN_WL_CNT_VER_6_T(rxnack),
+	IDX_IN_WL_CNT_VER_6_T(frmscons),
+	IDX_IN_WL_CNT_VER_6_T(txnack),
+	IDX_IN_WL_CNT_VER_6_T(rxback),
+	IDX_IN_WL_CNT_VER_6_T(txback),
+	IDX_IN_WL_CNT_VER_6_T(bphy_rxcrsglitch),
+	IDX_IN_WL_CNT_VER_6_T(rxdrop20s),
+	IDX_IN_WL_CNT_VER_6_T(rxtoolate),
+	IDX_IN_WL_CNT_VER_6_T(bphy_badplcp)
+};
+
+/* copy wlc layer counters from old type cntbuf to wl_cnt_wlc_t type. */
+static int
+wl_copy_wlccnt(uint16 cntver, uint32 *dst, uint32 *src, uint8 src_max_idx)
+{
+	uint i;
+	if (dst == NULL || src == NULL) {
+		return BCME_ERROR;
+	}
+
+	/* Init wlccnt with invalid value. Unchanged value will not be printed out */
+	for (i = 0; i < (sizeof(wl_cnt_wlc_t) / sizeof(uint32)); i++) {
+		dst[i] = INVALID_CNT_VAL;
+	}
+
+	if (cntver == WL_CNT_VERSION_6) {
+		for (i = 0; i < NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T; i++) {
+			if (wlcntver6t_to_wlcntwlct[i] >= src_max_idx) {
+				/* src buffer does not have counters from here */
+				break;
+			}
+			dst[i] = src[wlcntver6t_to_wlcntwlct[i]];
+		}
+	} else if (cntver == WL_CNT_VERSION_7 || cntver == WL_CNT_VERSION_7001) {
+		for (i = 0; i < NUM_OF_WLCCNT_IN_WL_CNT_VER_7_T; i++) {
+			if (wlcntver7t_to_wlcntwlct[i] >= src_max_idx) {
+				/* src buffer does not have counters from here */
+				break;
+			}
+			dst[i] = src[wlcntver7t_to_wlcntwlct[i]];
+		}
+	} else {
+		for (i = 0; i < NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T; i++) {
+			if (wlcntver11t_to_wlcntwlct[i] >= src_max_idx) {
+				/* src buffer does not have counters from here */
+				break;
+			}
+			dst[i] = src[wlcntver11t_to_wlcntwlct[i]];
+		}
+	}
+	return BCME_OK;
+}
+
+/* copy macstat counters from old type cntbuf to wl_cnt_v_le10_mcst_t type. */
+static int
+wl_copy_macstat_upto_ver10(uint16 cntver, uint32 *dst, uint32 *src)
+{
+	uint i;
+
+	if (dst == NULL || src == NULL) {
+		return BCME_ERROR;
+	}
+
+	if (cntver == WL_CNT_VERSION_7 || cntver == WL_CNT_VERSION_7001) {
+		for (i = 0; i < WL_CNT_MCST_VAR_NUM; i++) {
+			if (wlcntver7t_to_wlcntvle10mcstt[i] == INVALID_MCST_IDX) {
+				/* This mcst counter does not exist in wl_cnt_ver_7_t */
+				dst[i] = INVALID_CNT_VAL;
+			} else {
+				dst[i] = src[wlcntver7t_to_wlcntvle10mcstt[i]];
+			}
+		}
+	} else if (cntver == WL_CNT_VERSION_6) {
+		for (i = 0; i < WL_CNT_MCST_VAR_NUM; i++) {
+			if (wlcntver6t_to_wlcntvle10mcstt[i] == INVALID_MCST_IDX) {
+				/* This mcst counter does not exist in wl_cnt_ver_6_t */
+				dst[i] = INVALID_CNT_VAL;
+			} else {
+				dst[i] = src[wlcntver6t_to_wlcntvle10mcstt[i]];
+			}
+		}
+	} else {
+		for (i = 0; i < WL_CNT_MCST_VAR_NUM; i++) {
+			if (wlcntver11t_to_wlcntvle10mcstt[i] == INVALID_MCST_IDX) {
+				/* This mcst counter does not exist in wl_cnt_ver_11_t */
+				dst[i] = INVALID_CNT_VAL;
+			} else {
+				dst[i] = src[wlcntver11t_to_wlcntvle10mcstt[i]];
+			}
+		}
+	}
+	return BCME_OK;
+}
+
+static int
+wl_copy_macstat_ver11(uint32 *dst, uint32 *src)
+{
+	uint i;
+
+	if (dst == NULL || src == NULL) {
+		return BCME_ERROR;
+	}
+
+	for (i = 0; i < WL_CNT_MCST_VAR_NUM; i++) {
+		dst[i] = src[wlcntver11t_to_wlcntXX40mcstv1t[i]];
+	}
+	return BCME_OK;
+}
+
+/**
+ * Translate non-xtlv 'wl counters' IOVar buffer received by old driver/FW to xtlv format.
+ * Parameters:
+ *	cntbuf: pointer to non-xtlv 'wl counters' IOVar buffer received by old driver/FW.
+ *		Newly translated xtlv format is written to this pointer.
+ *	buflen: length of the "cntbuf" without any padding.
+ *	corerev: chip core revision of the driver/FW.
+ */
+int
+wl_cntbuf_to_xtlv_format(void *ctx, void *cntbuf, int buflen, uint32 corerev)
+{
+	wl_cnt_wlc_t *wlccnt = NULL;
+	uint32 *macstat = NULL;
+	xtlv_desc_t xtlv_desc[3];
+	uint16 mcst_xtlv_id;
+	int res = BCME_OK;
+	wl_cnt_info_t *cntinfo = cntbuf;
+	uint8 *xtlvbuf_p = cntinfo->data;
+	uint16 ver = cntinfo->version;
+	uint16 xtlvbuflen = (uint16)buflen;
+	uint16 src_max_idx;
+#ifdef BCMDRIVER
+	osl_t *osh = ctx;
+#else
+	BCM_REFERENCE(ctx);
+#endif
+
+	if (ver >= WL_CNT_VERSION_XTLV && ver != WL_CNT_VERSION_7001) {
+		/* Already in xtlv format. */
+		goto exit;
+	}
+
+#ifdef BCMDRIVER
+	wlccnt = MALLOC(osh, sizeof(*wlccnt));
+	macstat = MALLOC(osh, WL_CNT_MCST_STRUCT_SZ);
+#else
+	wlccnt = (wl_cnt_wlc_t *)malloc(sizeof(*wlccnt));
+	macstat = (uint32 *)malloc(WL_CNT_MCST_STRUCT_SZ);
+#endif
+	if (!wlccnt || !macstat) {
+		printf("%s: malloc fail!\n", __FUNCTION__);
+		res = BCME_NOMEM;
+		goto exit;
+	}
+
+	/* Check if the max idx in the struct exceeds the boundary of uint8 */
+	if (NUM_OF_CNT_IN_WL_CNT_VER_6_T > ((uint8)(-1) + 1) ||
+		NUM_OF_CNT_IN_WL_CNT_VER_7_T > ((uint8)(-1) + 1) ||
+		NUM_OF_CNT_IN_WL_CNT_VER_11_T > ((uint8)(-1) + 1)) {
+		printf("wlcntverXXt_to_wlcntwlct and src_max_idx need"
+			" to be of uint16 instead of uint8\n");
+		res = BCME_ERROR;
+		goto exit;
+	}
+
+	/* Exclude version and length fields in either wlc_cnt_ver_6_t or wlc_cnt_ver_11_t */
+	src_max_idx = (cntinfo->datalen - OFFSETOF(wl_cnt_info_t, data)) / sizeof(uint32);
+	if (src_max_idx > (uint8)(-1)) {
+		printf("wlcntverXXt_to_wlcntwlct and src_max_idx need"
+			" to be of uint16 instead of uint8\n"
+			"Try updating wl utility to the latest.\n");
+		src_max_idx = (uint8)(-1);
+	}
+
+	/* Copy wlc layer counters to wl_cnt_wlc_t */
+	res = wl_copy_wlccnt(ver, (uint32 *)wlccnt, (uint32 *)cntinfo->data, (uint8)src_max_idx);
+	if (res != BCME_OK) {
+		printf("wl_copy_wlccnt fail!\n");
+		goto exit;
+	}
+
+	/* Copy macstat counters to wl_cnt_wlc_t */
+	if (ver == WL_CNT_VERSION_11) {
+		res = wl_copy_macstat_ver11(macstat, (uint32 *)cntinfo->data);
+		if (res != BCME_OK) {
+			printf("wl_copy_macstat_ver11 fail!\n");
+			goto exit;
+		}
+		if (corerev >= 40) {
+			mcst_xtlv_id = WL_CNT_XTLV_GE40_UCODE_V1;
+		} else {
+			mcst_xtlv_id = WL_CNT_XTLV_LT40_UCODE_V1;
+		}
+	} else {
+		res = wl_copy_macstat_upto_ver10(ver, macstat, (uint32 *)cntinfo->data);
+		if (res != BCME_OK) {
+			printf("wl_copy_macstat_upto_ver10 fail!\n");
+			goto exit;
+		}
+		mcst_xtlv_id = WL_CNT_XTLV_CNTV_LE10_UCODE;
+	}
+
+	xtlv_desc[0].type = WL_CNT_XTLV_WLC;
+	xtlv_desc[0].len = sizeof(*wlccnt);
+	xtlv_desc[0].ptr = wlccnt;
+
+	xtlv_desc[1].type = mcst_xtlv_id;
+	xtlv_desc[1].len = WL_CNT_MCST_STRUCT_SZ;
+	xtlv_desc[1].ptr = macstat;
+
+	xtlv_desc[2].type = 0;
+	xtlv_desc[2].len = 0;
+	xtlv_desc[2].ptr = NULL;
+
+	memset(cntbuf, 0, buflen);
+
+	res = bcm_pack_xtlv_buf_from_mem(&xtlvbuf_p, &xtlvbuflen,
+		xtlv_desc, BCM_XTLV_OPTION_ALIGN32);
+	cntinfo->datalen = (buflen - xtlvbuflen);
+exit:
+#ifdef BCMDRIVER
+	if (wlccnt) {
+		MFREE(osh, wlccnt, sizeof(*wlccnt));
+	}
+	if (macstat) {
+		MFREE(osh, macstat, WL_CNT_MCST_STRUCT_SZ);
+	}
+#else
+	if (wlccnt) {
+		free(wlccnt);
+	}
+	if (macstat) {
+		free(macstat);
+	}
+#endif
+	return res;
+}
diff --git a/wl/src/shared/bcmbloom.c b/wl/src/shared/bcmbloom.c
new file mode 100644
index 0000000..51425e1
--- /dev/null
+++ b/wl/src/shared/bcmbloom.c
@@ -0,0 +1,230 @@
+/*
+ * Bloom filter support
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: bcmbloom.c 525587 2015-01-10 05:24:58Z $
+ */
+
+
+#include <typedefs.h>
+#include <bcmdefs.h>
+
+#if defined(__FreeBSD__)
+#include <machine/stdarg.h>
+#else
+#include <stdarg.h>
+#endif /* __FreeBSD__ */
+
+#ifdef BCMDRIVER
+#include <osl.h>
+#include <bcmutils.h>
+#else /* !BCMDRIVER */
+#include <stdio.h>
+#include <string.h>
+#ifndef ASSERT
+#define ASSERT(exp)
+#endif
+#endif /* !BCMDRIVER */
+#include <bcmutils.h>
+
+#include <bcmbloom.h>
+
+#define BLOOM_BIT_LEN(_x) ((_x) << 3)
+
+struct bcm_bloom_filter {
+	void *cb_ctx;
+	uint max_hash;
+	bcm_bloom_hash_t *hash;	/* array of hash functions */
+	uint filter_size; 		/* in bytes */
+	uint8 *filter; 			/* can be NULL for validate only */
+};
+
+/* public interface */
+int
+bcm_bloom_create(bcm_bloom_alloc_t alloc_cb,
+	bcm_bloom_free_t free_cb, void *cb_ctx, uint max_hash,
+	uint filter_size, bcm_bloom_filter_t **bloom)
+{
+	int err = BCME_OK;
+	bcm_bloom_filter_t *bp = NULL;
+
+	if (!bloom || !alloc_cb || (max_hash == 0)) {
+		err = BCME_BADARG;
+		goto done;
+	}
+
+	bp = (*alloc_cb)(cb_ctx, sizeof(*bp));
+	if (!bp) {
+		err = BCME_NOMEM;
+		goto done;
+	}
+
+	memset(bp, 0, sizeof(*bp));
+	bp->cb_ctx = cb_ctx;
+	bp->max_hash = max_hash;
+	bp->hash = (*alloc_cb)(cb_ctx, sizeof(*bp->hash) * max_hash);
+	if (!bp->hash) {
+		err = BCME_NOMEM;
+		goto done;
+	}
+
+	if (filter_size > 0) {
+		bp->filter = (*alloc_cb)(cb_ctx, filter_size);
+		if (!bp->filter) {
+			err = BCME_NOMEM;
+			goto done;
+		}
+		bp->filter_size = filter_size;
+		memset(bp->filter, 0, filter_size);
+	}
+
+	*bloom = bp;
+
+done:
+	if (err != BCME_OK)
+		bcm_bloom_destroy(&bp, free_cb);
+
+	return err;
+}
+
+int
+bcm_bloom_destroy(bcm_bloom_filter_t **bloom, bcm_bloom_free_t free_cb)
+{
+	int err = BCME_OK;
+	bcm_bloom_filter_t *bp;
+
+	if (!bloom || !*bloom || !free_cb)
+		goto done;
+
+	bp = *bloom;
+	*bloom = NULL;
+
+	if (bp->filter)
+		(*free_cb)(bp->cb_ctx, bp->filter, bp->filter_size);
+	if (bp->hash)
+		(*free_cb)(bp->cb_ctx, bp->hash,
+			sizeof(*bp->hash) * bp->max_hash);
+	(*free_cb)(bp->cb_ctx, bp, sizeof(*bp));
+
+done:
+	return err;
+}
+
+int
+bcm_bloom_add_hash(bcm_bloom_filter_t *bp, bcm_bloom_hash_t hash, uint *idx)
+{
+	uint i;
+
+	if (!bp || !hash || !idx)
+		return BCME_BADARG;
+
+	for (i = 0; i < bp->max_hash; ++i) {
+		if (bp->hash[i] == NULL)
+			break;
+	}
+
+	if (i >= bp->max_hash)
+		return BCME_NORESOURCE;
+
+	bp->hash[i] = hash;
+	*idx = i;
+	return BCME_OK;
+}
+
+int
+bcm_bloom_remove_hash(bcm_bloom_filter_t *bp, uint idx)
+{
+	if (!bp)
+		return BCME_BADARG;
+
+	if (idx >= bp->max_hash)
+		return BCME_NOTFOUND;
+
+	bp->hash[idx] = NULL;
+	return BCME_OK;
+}
+
+bool
+bcm_bloom_is_member(bcm_bloom_filter_t *bp,
+	const uint8 *tag, uint tag_len, const uint8 *buf, uint buf_len)
+{
+	uint i;
+	int err = BCME_OK;
+
+	if (!tag || (tag_len == 0)) /* empty tag is always a member */
+		goto done;
+
+	/* use internal buffer if none was specified */
+	if (!buf || (buf_len == 0)) {
+		if (!bp->filter)	/* every one is a member of empty filter */
+			goto done;
+
+		buf = bp->filter;
+		buf_len = bp->filter_size;
+	}
+
+	for (i = 0; i < bp->max_hash; ++i) {
+		uint pos;
+		if (!bp->hash[i])
+			continue;
+		pos = (*bp->hash[i])(bp->cb_ctx, i, tag, tag_len);
+
+		/* all bits must be set for a match */
+		if (isclr(buf, pos % BLOOM_BIT_LEN(buf_len))) {
+			err = BCME_NOTFOUND;
+			break;
+		}
+	}
+
+done:
+	return err;
+}
+
+int
+bcm_bloom_add_member(bcm_bloom_filter_t *bp, const uint8 *tag, uint tag_len)
+{
+	uint i;
+
+	if (!bp || !tag || (tag_len == 0))
+		return BCME_BADARG;
+
+	if (!bp->filter)		/* validate only */
+		return BCME_UNSUPPORTED;
+
+	for (i = 0; i < bp->max_hash; ++i) {
+		uint pos;
+		if (!bp->hash[i])
+			continue;
+		pos = (*bp->hash[i])(bp->cb_ctx, i, tag, tag_len);
+		setbit(bp->filter, pos % BLOOM_BIT_LEN(bp->filter_size));
+	}
+
+	return BCME_OK;
+}
+
+int bcm_bloom_get_filter_data(bcm_bloom_filter_t *bp,
+	uint buf_size, uint8 *buf, uint *buf_len)
+{
+	if (!bp)
+		return BCME_BADARG;
+
+	if (buf_len)
+		*buf_len = bp->filter_size;
+
+	if (buf_size < bp->filter_size)
+		return BCME_BUFTOOSHORT;
+
+	if (bp->filter && bp->filter_size)
+		memcpy(buf, bp->filter, bp->filter_size);
+
+	return BCME_OK;
+}
diff --git a/wl/src/shared/bcmutils.c b/wl/src/shared/bcmutils.c
new file mode 100644
index 0000000..ac05dd7
--- /dev/null
+++ b/wl/src/shared/bcmutils.c
@@ -0,0 +1,5217 @@
+/*
+ * Driver O/S-independent utility routines
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmutils.c 661946 2016-09-27 21:47:25Z $
+ */
+
+#include <bcm_cfg.h>
+#include <typedefs.h>
+#include <bcmdefs.h>
+#if defined(__FreeBSD__)
+#include <machine/stdarg.h>
+#include <stdbool.h>
+#else
+#include <stdarg.h>
+#endif
+#ifdef BCMDRIVER
+
+#include <osl.h>
+#include <bcmutils.h>
+#if !defined(BCMDONGLEHOST) || defined(BCMNVRAM)
+#include <siutils.h>
+#include <bcmnvram.h>
+#endif
+
+#else /* !BCMDRIVER */
+
+#include <stdio.h>
+#include <string.h>
+#include <bcmutils.h>
+
+#if defined(BCMEXTSUP)
+#include <bcm_osl.h>
+#endif
+
+#ifndef ASSERT
+#define ASSERT(exp)
+#endif
+
+#endif /* !BCMDRIVER */
+
+#if defined(_WIN32)
+/* Debatable */
+#include <bcmstdlib.h>
+#endif
+#include <bcmendian.h>
+#include <bcmdevs.h>
+#include <proto/ethernet.h>
+#include <proto/vlan.h>
+#include <proto/bcmip.h>
+#include <proto/802.1d.h>
+#include <proto/802.11.h>
+#include <proto/bcmip.h>
+#include <proto/bcmipv6.h>
+#include <proto/bcmtcp.h>
+#ifdef BCMPERFSTATS
+#include <bcmperf.h>
+#endif
+
+
+#ifdef CUSTOM_DSCP_TO_PRIO_MAPPING
+#define CUST_IPV4_TOS_PREC_MASK 0x3F
+#define DCSP_MAX_VALUE 64
+extern uint dhd_dscpmap_enable;
+/* 0:BE,1:BK,2:RESV(BK):,3:EE,:4:CL,5:VI,6:VO,7:NC */
+int dscp2priomap[DCSP_MAX_VALUE]=
+{
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, /* BK->BE */
+	2, 0, 0, 0, 0, 0, 0, 0,
+	3, 0, 0, 0, 0, 0, 0, 0,
+	4, 0, 0, 0, 0, 0, 0, 0,
+	5, 0, 0, 0, 0, 0, 0, 0,
+	6, 0, 0, 0, 0, 0, 0, 0,
+	7, 0, 0, 0, 0, 0, 0, 0
+};
+#endif /* CUSTOM_DSCP_TO_PRIO_MAPPING */
+
+
+#ifdef BCMDRIVER
+
+#if !defined(BCMDONGLEHOST)
+/* Forward declarations */
+char * getvar_internal(char *vars, const char *name);
+int getintvar_internal(char *vars, const char *name);
+int getintvararray_internal(char *vars, const char *name, int index);
+int getintvararraysize_internal(char *vars, const char *name);
+
+/* nvram vars cache */
+static char *nvram_vars = NULL;
+static int vars_len = -1;
+
+/*
+ * Search the name=value vars for a specific one and return its value.
+ * Returns NULL if not found.
+ */
+char *
+getvar(char *vars, const char *name)
+{
+	NVRAM_RECLAIM_CHECK(name);
+	return getvar_internal(vars, name);
+}
+
+char *
+getvar_internal(char *vars, const char *name)
+{
+	char *s;
+	int len;
+
+	if (!name)
+		return NULL;
+
+	len = strlen(name);
+	if (len == 0)
+		return NULL;
+
+	/* first look in vars[] */
+	for (s = vars; s && *s;) {
+		if ((bcmp(s, name, len) == 0) && (s[len] == '=')) {
+			return (&s[len+1]);
+		}
+		while (*s++)
+			;
+	}
+
+	/* then query nvram */
+	return (nvram_get(name));
+}
+
+/*
+ * Search the vars for a specific one and return its value as
+ * an integer. Returns 0 if not found.
+ */
+int
+getintvar(char *vars, const char *name)
+{
+	NVRAM_RECLAIM_CHECK(name);
+	return getintvar_internal(vars, name);
+}
+
+int
+getintvar_internal(char *vars, const char *name)
+{
+	char *val;
+
+	if ((val = getvar_internal(vars, name)) == NULL)
+		return (0);
+
+	return (bcm_strtoul(val, NULL, 0));
+}
+
+int
+getintvararray(char *vars, const char *name, int index)
+{
+	NVRAM_RECLAIM_CHECK(name);
+	return getintvararray_internal(vars, name, index);
+}
+
+int
+getintvararray_internal(char *vars, const char *name, int index)
+{
+	char *buf, *endp;
+	int i = 0;
+	int val = 0;
+
+	if ((buf = getvar_internal(vars, name)) == NULL) {
+		return (0);
+	}
+
+	/* table values are always separated by "," or " " */
+	while (*buf != '\0') {
+		val = bcm_strtoul(buf, &endp, 0);
+		if (i == index) {
+			return val;
+		}
+		buf = endp;
+		/* delimiter is ',' */
+		if (*buf == ',')
+			buf++;
+		i++;
+	}
+	return (0);
+}
+
+int
+getintvararraysize(char *vars, const char *name)
+{
+	NVRAM_RECLAIM_CHECK(name);
+	return getintvararraysize_internal(vars, name);
+}
+
+int
+getintvararraysize_internal(char *vars, const char *name)
+{
+	char *buf, *endp;
+	int count = 0;
+	int val = 0;
+
+	if ((buf = getvar_internal(vars, name)) == NULL) {
+		return (0);
+	}
+
+	/* table values are always separated by "," or " " */
+	while (*buf != '\0') {
+		val = bcm_strtoul(buf, &endp, 0);
+		buf = endp;
+		/* delimiter is ',' */
+		if (*buf == ',')
+			buf++;
+		count++;
+	}
+	BCM_REFERENCE(val);
+	return count;
+}
+
+/* Search for token in comma separated token-string */
+static int
+findmatch(const char *string, const char *name)
+{
+	uint len;
+	char *c;
+
+	len = strlen(name);
+	while ((c = strchr(string, ',')) != NULL) {
+		if (len == (uint)(c - string) && !strncmp(string, name, len))
+			return 1;
+		string = c + 1;
+	}
+
+	return (!strcmp(string, name));
+}
+
+/* Return gpio pin number assigned to the named pin
+ *
+ * Variable should be in format:
+ *
+ *	gpio<N>=pin_name,pin_name
+ *
+ * This format allows multiple features to share the gpio with mutual
+ * understanding.
+ *
+ * 'def_pin' is returned if a specific gpio is not defined for the requested functionality
+ * and if def_pin is not used by others.
+ */
+uint
+getgpiopin(char *vars, char *pin_name, uint def_pin)
+{
+	char name[] = "gpioXXXX";
+	char *val;
+	uint pin;
+
+	/* Go thru all possibilities till a match in pin name */
+	for (pin = 0; pin < GPIO_NUMPINS; pin ++) {
+		snprintf(name, sizeof(name), "gpio%d", pin);
+		val = getvar(vars, name);
+		if (val && findmatch(val, pin_name))
+			return pin;
+	}
+
+	if (def_pin != GPIO_PIN_NOTDEFINED) {
+		/* make sure the default pin is not used by someone else */
+		snprintf(name, sizeof(name), "gpio%d", def_pin);
+		if (getvar(vars, name)) {
+			def_pin =  GPIO_PIN_NOTDEFINED;
+		}
+	}
+	return def_pin;
+}
+
+static void
+BCMATTACHFN(bcm_nvram_refresh)(char *flash)
+{
+	int i;
+	int ret = 0;
+
+	ASSERT(flash != NULL);
+
+	/* default "empty" vars cache */
+	bzero(flash, 2);
+
+	if ((ret = nvram_getall(flash, MAX_NVRAM_SPACE)))
+		return;
+
+	/* determine nvram length */
+	for (i = 0; i < MAX_NVRAM_SPACE; i++) {
+		if (flash[i] == '\0' && flash[i+1] == '\0')
+			break;
+	}
+
+	if (i > 1)
+		vars_len = i + 2;
+	else
+		vars_len = 0;
+}
+
+char *
+BCMATTACHFN(bcm_nvram_vars)(uint *length)
+{
+#ifndef BCMNVRAMR
+	/* cache may be stale if nvram is read/write */
+	if (nvram_vars) {
+		ASSERT(!bcm_reclaimed);
+		bcm_nvram_refresh(nvram_vars);
+	}
+#endif
+	if (length)
+		*length = vars_len;
+	return nvram_vars;
+}
+
+/* copy nvram vars into locally-allocated multi-string array */
+int
+BCMATTACHFN(bcm_nvram_cache)(void *sih)
+{
+	int ret = 0;
+	void *osh;
+	char *flash = NULL;
+
+	if (vars_len >= 0) {
+#ifndef BCMNVRAMR
+		bcm_nvram_refresh(nvram_vars);
+#endif
+		return 0;
+	}
+
+	osh = si_osh((si_t *)sih);
+
+	/* allocate memory and read in flash */
+	/* freed in same function */
+	if (!(flash = MALLOC_NOPERSIST(osh, MAX_NVRAM_SPACE))) {
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+
+	bcm_nvram_refresh(flash);
+
+#ifdef BCMNVRAMR
+	if (vars_len > 3) {
+		/* freed on nvram_exit */
+		/* copy into a properly-sized buffer */
+		if (!(nvram_vars = MALLOC_NOPERSIST(osh, vars_len))) {
+			ret = BCME_NOMEM;
+		} else
+			bcopy(flash, nvram_vars, vars_len);
+	}
+	MFREE(osh, flash, MAX_NVRAM_SPACE);
+#else
+	/* cache must be full size of nvram if read/write */
+	nvram_vars = flash;
+#endif	/* BCMNVRAMR */
+
+exit:
+	return ret;
+}
+#endif /* !BCMDONGLEHOST */
+
+
+/* return total length of buffer chain */
+uint BCMFASTPATH
+pkttotlen(osl_t *osh, void *p)
+{
+	uint total;
+	int len;
+
+	total = 0;
+	for (; p; p = PKTNEXT(osh, p)) {
+		len = PKTLEN(osh, p);
+		total += len;
+#ifdef BCMLFRAG
+		if (BCMLFRAG_ENAB()) {
+			if (PKTISFRAG(osh, p)) {
+				total += PKTFRAGTOTLEN(osh, p);
+			}
+		}
+#endif
+	}
+
+	return (total);
+}
+
+/* return the last buffer of chained pkt */
+void *
+pktlast(osl_t *osh, void *p)
+{
+	for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p))
+		;
+
+	return (p);
+}
+
+/* count segments of a chained packet */
+uint BCMFASTPATH
+pktsegcnt(osl_t *osh, void *p)
+{
+	uint cnt;
+
+	for (cnt = 0; p; p = PKTNEXT(osh, p)) {
+		cnt++;
+#ifdef BCMLFRAG
+		if (BCMLFRAG_ENAB()) {
+			if (PKTISFRAG(osh, p)) {
+				cnt += PKTFRAGTOTNUM(osh, p);
+			}
+		}
+#endif
+	}
+
+	return cnt;
+}
+
+#ifdef DONGLEBUILD
+/**
+ * Takes in a lbuf/lfrag and no of bytes to be trimmed from tail.
+ * trim bytes  could be spread out in below 3 formats
+ *     1. entirely in dongle
+ *     2. entirely in host
+ *     3. split between host-dongle
+ */
+void
+pktfrag_trim_tailbytes(osl_t * osh, void* p, uint16 trim_len, uint8 type)
+{
+	uint16 tcmseg_len = PKTLEN(osh, p);	/* TCM segment length */
+	uint16 hostseg_len = PKTFRAGUSEDLEN(osh, p);	/* HOST segment length */
+
+	/* return if zero trim length- Nothing to do */
+	if (trim_len == 0)
+		return;
+
+	/* if header conv is on, there is no fcs at the end */
+	if (PKTISHDRCONVTD(osh, p))
+		return;
+
+	/* if pktfetched, then its already trimmed */
+	if (PKTISPKTFETCHED(osh, p))
+		return;
+
+	if (PKTFRAGUSEDLEN(osh, p) >= trim_len) {
+		/* TRIM bytes entirely in host */
+		ASSERT(PKTISRXFRAG(osh, p));
+
+		PKTSETFRAGUSEDLEN(osh, p, (hostseg_len - trim_len));
+	} else {
+		/* trim bytes either in dongle or split between dongle-host */
+		PKTSETLEN(osh, p, (tcmseg_len - (trim_len - hostseg_len)));
+
+		/* No more contents in host; reset length to zero */
+		if (PKTFRAGUSEDLEN(osh, p))
+			PKTSETFRAGUSEDLEN(osh, p, 0);
+	}
+}
+#endif /* DONGLEBUILD */
+
+/* copy a pkt buffer chain into a buffer */
+uint
+pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf)
+{
+	uint n, ret = 0;
+
+	if (len < 0)
+		len = 4096;	/* "infinite" */
+
+	/* skip 'offset' bytes */
+	for (; p && offset; p = PKTNEXT(osh, p)) {
+		if (offset < (uint)PKTLEN(osh, p))
+			break;
+		offset -= PKTLEN(osh, p);
+	}
+
+	if (!p)
+		return 0;
+
+	/* copy the data */
+	for (; p && len; p = PKTNEXT(osh, p)) {
+		n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
+		bcopy(PKTDATA(osh, p) + offset, buf, n);
+		buf += n;
+		len -= n;
+		ret += n;
+		offset = 0;
+	}
+
+	return ret;
+}
+
+/* copy a buffer into a pkt buffer chain */
+uint
+pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf)
+{
+	uint n, ret = 0;
+
+
+	/* skip 'offset' bytes */
+	for (; p && offset; p = PKTNEXT(osh, p)) {
+		if (offset < (uint)PKTLEN(osh, p))
+			break;
+		offset -= PKTLEN(osh, p);
+	}
+
+	if (!p)
+		return 0;
+
+	/* copy the data */
+	for (; p && len; p = PKTNEXT(osh, p)) {
+		n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
+		bcopy(buf, PKTDATA(osh, p) + offset, n);
+		buf += n;
+		len -= n;
+		ret += n;
+		offset = 0;
+	}
+
+	return ret;
+}
+
+#ifdef NOTYET
+/* copy data from one pkt buffer (chain) to another */
+uint
+pkt2pktcopy(osl_t *osh, void *p1, uint offs1, void *p2, uint offs2, int maxlen)
+{
+	uint8 *dp1, *dp2;
+	uint len1, len2, copylen, totallen;
+
+	for (; p1 && offs; p1 = PKTNEXT(osh, p1)) {
+		if (offs1 < (uint)PKTLEN(osh, p1))
+			break;
+		offs1 -= PKTLEN(osh, p1);
+	}
+	for (; p2 && offs; p2 = PKTNEXT(osh, p2)) {
+		if (offs2 < (uint)PKTLEN(osh, p2))
+			break;
+		offs2 -= PKTLEN(osh, p2);
+	}
+
+	/* Heck w/it, only need the above for now */
+}
+#endif /* NOTYET */
+
+/* count segments of a chained packet */
+uint BCMFASTPATH
+pktsegcnt_war(osl_t *osh, void *p)
+{
+	uint cnt;
+	uint8 *pktdata;
+	uint len, remain, align64;
+
+	for (cnt = 0; p; p = PKTNEXT(osh, p)) {
+		cnt++;
+		len = PKTLEN(osh, p);
+		if (len > 128) {
+			pktdata = (uint8 *)PKTDATA(osh, p);	/* starting address of data */
+			/* Check for page boundary straddle (2048B) */
+			if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff))
+				cnt++;
+
+			align64 = (uint)((uintptr)pktdata & 0x3f);	/* aligned to 64B */
+			align64 = (64 - align64) & 0x3f;
+			len -= align64;		/* bytes from aligned 64B to end */
+			/* if aligned to 128B, check for MOD 128 between 1 to 4B */
+			remain = len % 128;
+			if (remain > 0 && remain <= 4)
+				cnt++;		/* add extra seg */
+		}
+	}
+
+	return cnt;
+}
+
+uint8 * BCMFASTPATH
+pktdataoffset(osl_t *osh, void *p,  uint offset)
+{
+	uint total = pkttotlen(osh, p);
+	uint pkt_off = 0, len = 0;
+	uint8 *pdata = (uint8 *) PKTDATA(osh, p);
+
+	if (offset > total)
+		return NULL;
+
+	for (; p; p = PKTNEXT(osh, p)) {
+		pdata = (uint8 *) PKTDATA(osh, p);
+		pkt_off = offset - len;
+		len += PKTLEN(osh, p);
+		if (len > offset)
+			break;
+	}
+	return (uint8*) (pdata+pkt_off);
+}
+
+
+/* given a offset in pdata, find the pkt seg hdr */
+void *
+pktoffset(osl_t *osh, void *p,  uint offset)
+{
+	uint total = pkttotlen(osh, p);
+	uint len = 0;
+
+	if (offset > total)
+		return NULL;
+
+	for (; p; p = PKTNEXT(osh, p)) {
+		len += PKTLEN(osh, p);
+		if (len > offset)
+			break;
+	}
+	return p;
+}
+
+void
+bcm_mdelay(uint ms)
+{
+	uint i;
+
+	for (i = 0; i < ms; i++) {
+		OSL_DELAY(1000);
+	}
+}
+
+#if defined(BCMPERFSTATS) || defined(BCMTSTAMPEDLOGS)
+
+#if defined(__ARM_ARCH_7R__)
+#define BCMLOG_CYCLE_OVERHEAD	54	/* Number of CPU cycle overhead due to bcmlog().
+					 * This is to compensate CPU cycle incurred by
+					 * added bcmlog() function call for profiling.
+					 */
+#else
+#define BCMLOG_CYCLE_OVERHEAD	0
+#endif
+
+#define	LOGSIZE	256			/* should be power of 2 to avoid div below */
+static struct {
+	uint	cycles;
+	const char	*fmt;
+	uint	a1;
+	uint	a2;
+	uchar   indent;		/* track indent level for nice printing */
+} logtab[LOGSIZE];
+
+/* last entry logged  */
+static uint logi = 0;
+/* next entry to read */
+static uint volatile readi = 0;
+#endif	/* defined(BCMPERFSTATS) || defined(BCMTSTAMPEDLOGS) */
+
+#ifdef BCMPERFSTATS
+/* TODO: make the utility configurable (choose between icache, dcache, hits, misses ...)  */
+void
+bcm_perf_enable()
+{
+	BCMPERF_ENABLE_INSTRCOUNT();
+	BCMPERF_ENABLE_ICACHE_MISS();
+	BCMPERF_ENABLE_ICACHE_HIT();
+}
+
+/* WARNING:  This routine uses OSL_GETCYCLES(), which can give unexpected results on
+ * modern speed stepping CPUs.  Use bcmtslog() instead in combination with TSF counter.
+ */
+void
+bcmlog(char *fmt, uint a1, uint a2)
+{
+	static uint last = 0;
+	uint cycles, i, elapsed;
+	OSL_GETCYCLES(cycles);
+
+	i = logi;
+
+	elapsed = cycles - last;
+	if (elapsed > BCMLOG_CYCLE_OVERHEAD)
+		logtab[i].cycles = elapsed - BCMLOG_CYCLE_OVERHEAD;
+	else
+		logtab[i].cycles = 0;
+	logtab[i].fmt = fmt;
+	logtab[i].a1 = a1;
+	logtab[i].a2 = a2;
+
+	logi = (i + 1) % LOGSIZE;
+	last = cycles;
+
+	/* if log buffer is overflowing, readi should be advanced.
+	 * Otherwise logi and readi will become out of sync.
+	 */
+	if (logi == readi) {
+		readi = (readi + 1) % LOGSIZE;
+	} else {
+		/* This redundant else is to make CPU cycles of bcmlog() function to be uniform,
+		 * so that the cycle compensation with BCMLOG_CYCLE_OVERHEAD is more accurate.
+		 */
+		readi = readi % LOGSIZE;
+	}
+}
+
+/* Same as bcmlog but specializes the use of a1 and a2 to
+ * store icache misses and instruction count.
+ *  TODO : make this use a configuration array to decide what counter to read.
+ * We are limited to 2 numbers but it seems it is the most we can get anyway
+ * since dcache and icache cannot be enabled at the same time. Recording
+ * both the hits and misses at the same time for a given cache is not that useful either.
+*/
+
+void
+bcmstats(char *fmt)
+{
+	static uint last = 0;
+	static uint32 ic_miss = 0;
+	static uint32 instr_count = 0;
+	uint32 ic_miss_cur;
+	uint32 instr_count_cur;
+	uint cycles, i;
+
+	OSL_GETCYCLES(cycles);
+	BCMPERF_GETICACHE_MISS(ic_miss_cur);
+	BCMPERF_GETINSTRCOUNT(instr_count_cur);
+
+	i = logi;
+
+	logtab[i].cycles = cycles - last;
+	logtab[i].a1 = ic_miss_cur - ic_miss;
+	logtab[i].a2 = instr_count_cur - instr_count;
+	logtab[i].fmt = fmt;
+
+	logi = (i + 1) % LOGSIZE;
+
+	last = cycles;
+	instr_count = instr_count_cur;
+	ic_miss = ic_miss_cur;
+
+	/* if log buffer is overflowing, readi should be advanced.
+	 * Otherwise logi and readi will become out of sync.
+	 */
+	if (logi == readi) {
+		readi = (readi + 1) % LOGSIZE;
+	} else {
+		/* This redundant else is to make CPU cycles of bcmstats() function to be uniform
+		 */
+		readi = readi % LOGSIZE;
+	}
+}
+
+/*
+ * TODO (linux version): a "proc" version where the log would be dumped
+ * on the proc file directly.
+ */
+
+void
+bcmdumplog(char *buf, int size)
+{
+	char *limit;
+	int j = 0;
+	int num;
+
+	limit = buf + size - 80;
+	*buf = '\0';
+
+	num = logi - readi;
+
+	if (num < 0)
+		num += LOGSIZE;
+
+	/* print in chronological order */
+
+	for (j = 0; j < num && (buf < limit); readi = (readi + 1) % LOGSIZE, j++) {
+		if (logtab[readi].fmt == NULL)
+		    continue;
+		buf += snprintf(buf, (limit - buf), "%d\t", logtab[readi].cycles);
+		buf += snprintf(buf, (limit - buf), logtab[readi].fmt, logtab[readi].a1,
+			logtab[readi].a2);
+		buf += snprintf(buf, (limit - buf), "\n");
+	}
+
+}
+
+
+/*
+ * Dump one log entry at a time.
+ * Return index of next entry or -1 when no more .
+ */
+int
+bcmdumplogent(char *buf, uint i)
+{
+	bool hit;
+
+	/*
+	 * If buf is NULL, return the starting index,
+	 * interpreting i as the indicator of last 'i' entries to dump.
+	 */
+	if (buf == NULL) {
+		i = ((i > 0) && (i < (LOGSIZE - 1))) ? i : (LOGSIZE - 1);
+		return ((logi - i) % LOGSIZE);
+	}
+
+	*buf = '\0';
+
+	ASSERT(i < LOGSIZE);
+
+	if (i == logi)
+		return (-1);
+
+	hit = FALSE;
+	for (; (i != logi) && !hit; i = (i + 1) % LOGSIZE) {
+		if (logtab[i].fmt == NULL)
+			continue;
+		buf += snprintf(buf, LOGSIZE, "%d: %d\t", i, logtab[i].cycles);
+		buf += snprintf(buf, LOGSIZE, logtab[i].fmt, logtab[i].a1, logtab[i].a2);
+		buf += snprintf(buf, LOGSIZE, "\n");
+		hit = TRUE;
+	}
+
+	return (i);
+}
+
+#endif	/* BCMPERFSTATS */
+
+#if defined(BCMTSTAMPEDLOGS)
+/* Store a TSF timestamp and a log line in the log buffer */
+/*
+	a1 is used to signify entering/exiting a routine.  When entering
+	the indent level is increased.  When exiting, the delta since entering
+	is printed and the indent level is bumped back out.
+	Nesting can go up to level MAX_TS_INDENTS deep.
+*/
+#define MAX_TS_INDENTS 20
+void
+bcmtslog(uint32 tstamp, const char *fmt, uint a1, uint a2)
+{
+	uint i = logi;
+	bool use_delta = TRUE;
+	static uint32 last = 0;	/* used only when use_delta is true */
+	static uchar indent = 0;
+	static uint32 indents[MAX_TS_INDENTS];
+
+	logtab[i].cycles = tstamp;
+	if (use_delta)
+		logtab[i].cycles -= last;
+
+	logtab[i].a2 = a2;
+
+	if (a1 == TS_EXIT && indent) {
+		indent--;
+		logtab[i].a2 = tstamp - indents[indent];
+	}
+
+	logtab[i].fmt = fmt;
+	logtab[i].a1 = a1;
+	logtab[i].indent = indent;
+
+	if (a1 == TS_ENTER) {
+		indents[indent] = tstamp;
+		if (indent < MAX_TS_INDENTS - 1)
+			indent++;
+	}
+
+	if (use_delta)
+		last = tstamp;
+	logi = (i + 1) % LOGSIZE;
+}
+
+/* Print out a microsecond timestamp as "sec.ms.us " */
+void
+bcmprinttstamp(uint32 ticks)
+{
+	uint us, ms, sec;
+
+	us = (ticks % TSF_TICKS_PER_MS) * 1000 / TSF_TICKS_PER_MS;
+	ms = ticks / TSF_TICKS_PER_MS;
+	sec = ms / 1000;
+	ms -= sec * 1000;
+	printf("%04u.%03u.%03u ", sec, ms, us);
+}
+
+/* Print out the log buffer with timestamps */
+void
+bcmprinttslogs(void)
+{
+	int j = 0;
+	int num;
+
+	num = logi - readi;
+	if (num < 0)
+		num += LOGSIZE;
+
+	/* Format and print the log entries directly in chronological order */
+	for (j = 0; j < num; readi = (readi + 1) % LOGSIZE, j++) {
+		if (logtab[readi].fmt == NULL)
+		    continue;
+		bcmprinttstamp(logtab[readi].cycles);
+		printf(logtab[readi].fmt, logtab[readi].a1, logtab[readi].a2);
+		printf("\n");
+	}
+}
+
+/*
+	Identical to bcmdumplog, but output is based on tsf instead of cycles.
+
+	a1 is used to signify entering/exiting a routine.  When entering
+	the indent level is increased.  When exiting, the delta since entering
+	is printed and the indent level is bumped back out.
+*/
+void
+bcmdumptslog(struct bcmstrbuf *b)
+{
+	char *limit;
+	int j = 0;
+	int num;
+	uint us, ms, sec;
+	int skip;
+	char *lines = "| | | | | | | | | | | | | | | | | | | |";
+
+	limit = BCMSTRBUF_BUF(b) + BCMSTRBUF_LEN(b) - 80;
+
+	num = logi - readi;
+
+	if (num < 0)
+		num += LOGSIZE;
+
+	/* print in chronological order */
+	for (j = 0; j < num && (BCMSTRBUF_BUF(b) < limit); readi = (readi + 1) % LOGSIZE, j++) {
+		char *last_buf = BCMSTRBUF_BUF(b);
+		if (logtab[readi].fmt == NULL)
+			continue;
+
+		us = (logtab[readi].cycles % TSF_TICKS_PER_MS) * 1000 / TSF_TICKS_PER_MS;
+		ms = logtab[readi].cycles / TSF_TICKS_PER_MS;
+		sec = ms / 1000;
+		ms -= sec * 1000;
+
+		bcm_bprintf(b, "%04u.%03u.%03u ", sec, ms, us);
+
+		/* 2 spaces for each indent level */
+		bcm_bprintf(b, "%.*s", logtab[readi].indent * 2, lines);
+
+		/*
+		 * The following call to snprintf generates a compiler warning
+		 * due to -Wformat-security. However, the format string is coming
+		 * from internal callers rather than external data input, and is a
+		 * useful debugging tool serving a variety of diagnostics. Rather
+		 * than expand code size by replicating multiple functions with different
+		 * argument lists, or disabling the warning globally, let's consider
+		 * if we can just disable the warning for this one instance.
+		 */
+		bcm_bprintf(b, logtab[readi].fmt);
+
+		/* If a1 is ENTER or EXIT, print the + or - */
+		skip = 0;
+		if (logtab[readi].a1 == TS_ENTER) {
+			bcm_bprintf(b, " +");
+			skip++;
+		}
+		if (logtab[readi].a1 == TS_EXIT) {
+			bcm_bprintf(b, " -");
+			skip++;
+		}
+
+		/* else print the real a1 */
+		if (logtab[readi].a1 && !skip)
+			bcm_bprintf(b, "   %d", logtab[readi].a1);
+
+		/*
+		   If exiting routine, print a nicely formatted delta since entering.
+		   Otherwise, just print a2 normally.
+		*/
+		if (logtab[readi].a2) {
+			if (logtab[readi].a1 == TS_EXIT) {
+				int num_space = 75 - (BCMSTRBUF_BUF(b) - last_buf);
+				bcm_bprintf(b, "%*.s", num_space, "");
+				bcm_bprintf(b, "%5d usecs", logtab[readi].a2);
+			} else
+				bcm_bprintf(b, "  %d", logtab[readi].a2);
+		}
+		bcm_bprintf(b, "\n");
+		last_buf = BCMSTRBUF_BUF(b);
+	}
+}
+
+#endif	/* BCMTSTAMPEDLOGS */
+
+#if defined(BCMDBG) || defined(DHD_DEBUG)
+/* pretty hex print a pkt buffer chain */
+void
+prpkt(const char *msg, osl_t *osh, void *p0)
+{
+	void *p;
+
+	if (msg && (msg[0] != '\0'))
+		printf("%s:\n", msg);
+
+	for (p = p0; p; p = PKTNEXT(osh, p))
+		prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p));
+}
+#endif	/* BCMDBG || DHD_DEBUG */
+
+/* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
+ * Also updates the inplace vlan tag if requested.
+ * For debugging, it returns an indication of what it did.
+ */
+uint BCMFASTPATH
+pktsetprio(void *pkt, bool update_vtag)
+{
+	struct ether_header *eh;
+	struct ethervlan_header *evh;
+	uint8 *pktdata;
+	int priority = 0;
+	int rc = 0;
+
+	pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
+	ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
+
+	eh = (struct ether_header *) pktdata;
+
+	if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) {
+		uint16 vlan_tag;
+		int vlan_prio, dscp_prio = 0;
+
+		evh = (struct ethervlan_header *)eh;
+
+		vlan_tag = ntoh16(evh->vlan_tag);
+		vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
+
+		if ((evh->ether_type == hton16(ETHER_TYPE_IP)) ||
+			(evh->ether_type == hton16(ETHER_TYPE_IPV6))) {
+			uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
+			uint8 tos_tc = IP_TOS46(ip_body);
+			dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+		}
+
+		/* DSCP priority gets precedence over 802.1P (vlan tag) */
+		if (dscp_prio != 0) {
+			priority = dscp_prio;
+			rc |= PKTPRIO_VDSCP;
+		} else {
+			priority = vlan_prio;
+			rc |= PKTPRIO_VLAN;
+		}
+		/*
+		 * If the DSCP priority is not the same as the VLAN priority,
+		 * then overwrite the priority field in the vlan tag, with the
+		 * DSCP priority value. This is required for Linux APs because
+		 * the VLAN driver on Linux, overwrites the skb->priority field
+		 * with the priority value in the vlan tag
+		 */
+		if (update_vtag && (priority != vlan_prio)) {
+			vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
+			vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
+			evh->vlan_tag = hton16(vlan_tag);
+			rc |= PKTPRIO_UPD;
+		}
+#if defined(EAPOL_PKT_PRIO) || defined(DHD_LOSSLESS_ROAMING)
+	} else if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
+		priority = PRIO_8021D_NC;
+		rc = PKTPRIO_DSCP;
+#endif /* EAPOL_PKT_PRIO || DHD_LOSSLESS_ROAMING */
+	} else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) ||
+		(eh->ether_type == hton16(ETHER_TYPE_IPV6))) {
+		uint8 *ip_body = pktdata + sizeof(struct ether_header);
+		uint8 tos_tc = IP_TOS46(ip_body);
+		uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT;
+		switch (dscp) {
+		case DSCP_EF:
+			priority = PRIO_8021D_VO;
+			break;
+		case DSCP_AF31:
+		case DSCP_AF32:
+		case DSCP_AF33:
+			priority = PRIO_8021D_CL;
+			break;
+		case DSCP_AF21:
+		case DSCP_AF22:
+		case DSCP_AF23:
+		case DSCP_AF11:
+		case DSCP_AF12:
+		case DSCP_AF13:
+			priority = PRIO_8021D_EE;
+			break;
+		default:
+#ifndef CUSTOM_DSCP_TO_PRIO_MAPPING
+			priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+#else
+			if (dhd_dscpmap_enable) {
+				priority = (int)dscp2priomap[((tos_tc >> IPV4_TOS_DSCP_SHIFT)
+					& CUST_IPV4_TOS_PREC_MASK)];
+			}
+			else {
+				priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
+			}
+#endif /* CUSTOM_DSCP_TO_PRIO_MAPPING */
+			break;
+		}
+
+		rc |= PKTPRIO_DSCP;
+	}
+
+	ASSERT(priority >= 0 && priority <= MAXPRIO);
+	PKTSETPRIO(pkt, priority);
+	return (rc | priority);
+}
+
+/* lookup user priority for specified DSCP */
+static uint8
+dscp2up(uint8 *up_table, uint8 dscp)
+{
+	uint8 user_priority = 255;
+
+	/* lookup up from table if parameters valid */
+	if (up_table != NULL && dscp < UP_TABLE_MAX) {
+		user_priority = up_table[dscp];
+	}
+
+	/* 255 is unused value so return up from dscp */
+	if (user_priority == 255) {
+		user_priority = dscp >> (IPV4_TOS_PREC_SHIFT - IPV4_TOS_DSCP_SHIFT);
+	}
+
+	return user_priority;
+}
+
+/* set user priority by QoS Map Set table (UP table), table size is UP_TABLE_MAX */
+uint BCMFASTPATH
+pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag)
+{
+	if (up_table) {
+		uint8 *pktdata;
+		uint pktlen;
+		uint8 dscp;
+		uint user_priority = 0;
+		uint rc = 0;
+
+		pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
+		pktlen = PKTLEN(OSH_NULL, pkt);
+
+		if (pktgetdscp(pktdata, pktlen, &dscp)) {
+			rc = PKTPRIO_DSCP;
+			user_priority = dscp2up(up_table, dscp);
+			PKTSETPRIO(pkt, user_priority);
+		}
+
+		return (rc | user_priority);
+	} else {
+		return pktsetprio(pkt, update_vtag);
+	}
+}
+
+/* Returns TRUE and DSCP if IP header found, FALSE otherwise.
+ */
+bool BCMFASTPATH
+pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp)
+{
+	struct ether_header *eh;
+	struct ethervlan_header *evh;
+	uint8 *ip_body;
+	bool rc = FALSE;
+
+	/* minimum length is ether header and IP header */
+	if (pktlen < sizeof(struct ether_header) + IPV4_MIN_HEADER_LEN)
+		return FALSE;
+
+	eh = (struct ether_header *) pktdata;
+
+	if (eh->ether_type == HTON16(ETHER_TYPE_IP)) {
+		ip_body = pktdata + sizeof(struct ether_header);
+		*dscp = IP_DSCP46(ip_body);
+		rc = TRUE;
+	}
+	else if (eh->ether_type == HTON16(ETHER_TYPE_8021Q)) {
+		evh = (struct ethervlan_header *)eh;
+
+		/* minimum length is ethervlan header and IP header */
+		if (pktlen >= sizeof(struct ethervlan_header) + IPV4_MIN_HEADER_LEN &&
+			evh->ether_type == HTON16(ETHER_TYPE_IP)) {
+			ip_body = pktdata + sizeof(struct ethervlan_header);
+			*dscp = IP_DSCP46(ip_body);
+			rc = TRUE;
+		}
+	}
+
+	return rc;
+}
+
+/* usr_prio range from low to high with usr_prio value */
+static bool
+up_table_set(uint8 *up_table, uint8 usr_prio, uint8 low, uint8 high)
+{
+	int i;
+
+	if (usr_prio > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) {
+		return FALSE;
+	}
+
+	for (i = low; i <= high; i++) {
+		up_table[i] = usr_prio;
+	}
+
+	return TRUE;
+}
+
+/* set user priority table */
+int BCMFASTPATH
+wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie)
+{
+	uint8 len;
+
+	if (up_table == NULL || qos_map_ie == NULL) {
+		return BCME_ERROR;
+	}
+
+	/* clear table to check table was set or not */
+	memset(up_table, 0xff, UP_TABLE_MAX);
+
+	/* length of QoS Map IE must be 16+n*2, n is number of exceptions */
+	if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID &&
+			(len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH &&
+			(len % 2) == 0) {
+		uint8 *except_ptr = (uint8 *)qos_map_ie->data;
+		uint8 except_len = len - QOS_MAP_FIXED_LENGTH;
+		uint8 *range_ptr = except_ptr + except_len;
+		int i;
+
+		/* fill in ranges */
+		for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) {
+			uint8 low = range_ptr[i];
+			uint8 high = range_ptr[i + 1];
+			if (low == 255 && high == 255) {
+				continue;
+			}
+
+			if (!up_table_set(up_table, i / 2, low, high)) {
+				/* clear the table on failure */
+				memset(up_table, 0xff, UP_TABLE_MAX);
+				return BCME_ERROR;
+			}
+		}
+
+		/* update exceptions */
+		for (i = 0; i < except_len; i += 2) {
+			uint8 dscp = except_ptr[i];
+			uint8 usr_prio = except_ptr[i+1];
+
+			/* exceptions with invalid dscp/usr_prio are ignored */
+			up_table_set(up_table, usr_prio, dscp, dscp);
+		}
+	}
+
+	return BCME_OK;
+}
+
+#ifndef BCM_BOOTLOADER
+/* The 0.5KB string table is not removed by compiler even though it's unused */
+
+static char bcm_undeferrstr[32];
+static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
+
+/* Convert the error codes into related error strings  */
+const char *
+BCMRAMFN(bcmerrorstr)(int bcmerror)
+{
+	/* check if someone added a bcmerror code but forgot to add errorstring */
+	ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1));
+
+	if (bcmerror > 0 || bcmerror < BCME_LAST) {
+		snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror);
+		return bcm_undeferrstr;
+	}
+
+	ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN);
+
+	return bcmerrorstrtable[-bcmerror];
+}
+
+#endif /* !BCM_BOOTLOADER */
+
+#ifdef BCMDBG_PKT   /* pkt logging for debugging */
+/* Add a packet to the pktlist */
+static void
+_pktlist_add(pktlist_info_t *pktlist, void *pkt, int line, char *file)
+{
+	uint16 i;
+	char *basename;
+#ifdef BCMDBG_PTRACE
+	uint16 *idx = PKTLIST_IDX(pkt);
+#endif /* BCMDBG_PTRACE */
+
+	ASSERT(pktlist->count < PKTLIST_SIZE);
+
+	/* Verify the packet is not already part of the list */
+	for (i = 0; i < pktlist->count; i++) {
+		if (pktlist->list[i].pkt == pkt)
+			ASSERT(0);
+	}
+	pktlist->list[pktlist->count].pkt = pkt;
+	pktlist->list[pktlist->count].line = line;
+
+	basename = strrchr(file, '/');
+	if (basename)
+		basename++;
+	else
+		basename = file;
+	pktlist->list[pktlist->count].file = basename;
+#ifdef BCMDBG_PTRACE
+	*idx = pktlist->count;
+	bzero(pktlist->list[pktlist->count].pkt_trace, PKTTRACE_MAX_BYTES);
+#endif /* BCMDBG_PTRACE */
+	pktlist->count++;
+
+	return;
+}
+
+void
+pktlist_add(pktlist_info_t *pktlist, void *pkt, int line, char *file)
+{
+	void *p;
+	for (p = pkt; p != NULL; p = PKTCLINK(p))
+		_pktlist_add(pktlist, p, line, file);
+}
+
+/* Remove a packet from the pktlist */
+static void
+_pktlist_remove(pktlist_info_t *pktlist, void *pkt)
+{
+	uint16 i;
+	uint16 num = pktlist->count;
+#ifdef BCMDBG_PTRACE
+	uint16 *idx = PKTLIST_IDX(pkt);
+
+	ASSERT((*idx) < pktlist->count);
+#endif /* BCMDBG_PTRACE */
+
+	/* find the index where pkt exists */
+	for (i = 0; i < num; i++) {
+		/* check for the existence of pkt in the list */
+		if (pktlist->list[i].pkt == pkt) {
+#ifdef BCMDBG_PTRACE
+			ASSERT((*idx) == i);
+#endif /* BCMDBG_PTRACE */
+			/* replace with the last element */
+			pktlist->list[i].pkt = pktlist->list[num-1].pkt;
+			pktlist->list[i].line = pktlist->list[num-1].line;
+			pktlist->list[i].file = pktlist->list[num-1].file;
+#ifdef BCMDBG_PTRACE
+			memcpy(pktlist->list[i].pkt_trace, pktlist->list[num-1].pkt_trace,
+				PKTTRACE_MAX_BYTES);
+			idx = PKTLIST_IDX(pktlist->list[i].pkt);
+			*idx = i;
+#endif /* BCMDBG_PTRACE */
+			pktlist->count--;
+			return;
+		}
+	}
+	ASSERT(0);
+}
+
+void
+pktlist_remove(pktlist_info_t *pktlist, void *pkt)
+{
+	void *p;
+	for (p = pkt; p != NULL; p = PKTCLINK(p))
+		_pktlist_remove(pktlist, p);
+}
+
+#ifdef BCMDBG_PTRACE
+static void
+_pktlist_trace(pktlist_info_t *pktlist, void *pkt, uint16 bit)
+{
+	uint16 *idx = PKTLIST_IDX(pkt);
+
+	ASSERT(((*idx) < pktlist->count) && (bit < PKTTRACE_MAX_BITS));
+	ASSERT(pktlist->list[(*idx)].pkt == pkt);
+
+	pktlist->list[(*idx)].pkt_trace[bit/NBBY] |= (1 << ((bit)%NBBY));
+
+}
+void
+pktlist_trace(pktlist_info_t *pktlist, void *pkt, uint16 bit)
+{
+	void *p;
+	for (p = pkt; p != NULL; p = PKTCLINK(p))
+		_pktlist_trace(pktlist, p, bit);
+}
+#endif /* BCMDBG_PTRACE */
+
+/* Dump the pktlist (and the contents of each packet if 'data'
+ * is set). 'buf' should be large enough
+ */
+
+char *
+pktlist_dump(pktlist_info_t *pktlist, char *buf)
+{
+	char *obuf = buf;
+	uint16 i;
+
+	if (buf != NULL)
+		buf += sprintf(buf, "Packet list dump:\n");
+	else
+		printf("Packet list dump:\n");
+
+	for (i = 0; i < (pktlist->count); i++) {
+		if (buf != NULL)
+			buf += sprintf(buf, "Pkt_addr: 0x%p Line: %d File: %s\t",
+				OSL_OBFUSCATE_BUF(pktlist->list[i].pkt), pktlist->list[i].line,
+				pktlist->list[i].file);
+		else
+			printf("Pkt_addr: 0x%p Line: %d File: %s\t",
+				OSL_OBFUSCATE_BUF(pktlist->list[i].pkt),
+				pktlist->list[i].line, pktlist->list[i].file);
+
+/* #ifdef NOTDEF  Remove this ifdef to print pkttag and pktdata */
+		if (buf != NULL) {
+			if (PKTTAG(pktlist->list[i].pkt)) {
+				/* Print pkttag */
+				buf += sprintf(buf, "Pkttag(in hex): ");
+				buf += bcm_format_hex(buf, PKTTAG(pktlist->list[i].pkt),
+					OSL_PKTTAG_SZ);
+			}
+			buf += sprintf(buf, "Pktdata(in hex): ");
+			buf += bcm_format_hex(buf, PKTDATA(OSH_NULL, pktlist->list[i].pkt),
+			                      PKTLEN(OSH_NULL, pktlist->list[i].pkt));
+		} else {
+			void *pkt = pktlist->list[i].pkt, *npkt;
+
+			printf("Pkt[%d] Dump:\n", i);
+			while (pkt) {
+				int hroom, pktlen;
+				uchar *src;
+#ifdef BCMDBG_PTRACE
+				uint16 *idx = PKTLIST_IDX(pkt);
+
+				ASSERT((*idx) < pktlist->count);
+				prhex("Pkt Trace (in hex):", pktlist->list[(*idx)].pkt_trace,
+					PKTTRACE_MAX_BYTES);
+#endif /* BCMDBG_PTRACE */
+				npkt = (void *)PKTNEXT(OSH_NULL, pkt);
+				PKTSETNEXT(OSH_NULL, pkt, NULL);
+
+				src = (uchar *)(PKTTAG(pkt));
+				pktlen = PKTLEN(OSH_NULL, pkt);
+				hroom = PKTHEADROOM(OSH_NULL, pkt);
+
+				printf("Pkttag_addr: %p\n", OSL_OBFUSCATE_BUF(src));
+				if (src)
+					prhex("Pkttag(in hex): ", src, OSL_PKTTAG_SZ);
+				src = (uchar *) (PKTDATA(OSH_NULL, pkt));
+				printf("Pkthead_addr: %p len: %d\n",
+					OSL_OBFUSCATE_BUF(src - hroom), hroom);
+				prhex("Pkt headroom content(in hex): ", src - hroom, hroom);
+				printf("Pktdata_addr: %p len: %d\n",
+					OSL_OBFUSCATE_BUF(src), pktlen);
+				prhex("Pktdata(in hex): ", src, pktlen);
+
+				pkt = npkt;
+			}
+		}
+/* #endif  NOTDEF */
+
+		if (buf != NULL)
+			buf += sprintf(buf, "\n");
+		else
+			printf("\n");
+	}
+	return obuf;
+}
+#endif  /* BCMDBG_PKT */
+
+/* iovar table lookup */
+/* could mandate sorted tables and do a binary search */
+const bcm_iovar_t*
+bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
+{
+	const bcm_iovar_t *vi;
+	const char *lookup_name;
+
+	/* skip any ':' delimited option prefixes */
+	lookup_name = strrchr(name, ':');
+	if (lookup_name != NULL)
+		lookup_name++;
+	else
+		lookup_name = name;
+
+	ASSERT(table != NULL);
+
+	for (vi = table; vi->name; vi++) {
+		if (!strcmp(vi->name, lookup_name))
+			return vi;
+	}
+	/* ran to end of table */
+
+	return NULL; /* var name not found */
+}
+
+int
+bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
+{
+	int bcmerror = 0;
+	BCM_REFERENCE(arg);
+
+	/* length check on io buf */
+	switch (vi->type) {
+	case IOVT_BOOL:
+	case IOVT_INT8:
+	case IOVT_INT16:
+	case IOVT_INT32:
+	case IOVT_UINT8:
+	case IOVT_UINT16:
+	case IOVT_UINT32:
+		/* all integers are int32 sized args at the ioctl interface */
+		if (len < (int)sizeof(int)) {
+			bcmerror = BCME_BUFTOOSHORT;
+		}
+		break;
+
+	case IOVT_BUFFER:
+		/* buffer must meet minimum length requirement */
+		if (len < vi->minlen) {
+			bcmerror = BCME_BUFTOOSHORT;
+		}
+		break;
+
+	case IOVT_VOID:
+		if (!set) {
+			/* Cannot return nil... */
+			bcmerror = BCME_UNSUPPORTED;
+		} else if (len) {
+			/* Set is an action w/o parameters */
+			bcmerror = BCME_BUFTOOLONG;
+		}
+		break;
+
+	default:
+		/* unknown type for length check in iovar info */
+		ASSERT(0);
+		bcmerror = BCME_UNSUPPORTED;
+	}
+
+	return bcmerror;
+}
+
+#if !defined(_CFEZ_)
+/*
+ * Hierarchical Multiword bitmap based small id allocator.
+ *
+ * Multilevel hierarchy bitmap. (maximum 2 levels)
+ * First hierarchy uses a multiword bitmap to identify 32bit words in the
+ * second hierarchy that have at least a single bit set. Each bit in a word of
+ * the second hierarchy represents a unique ID that may be allocated.
+ *
+ * BCM_MWBMAP_ITEMS_MAX: Maximum number of IDs managed.
+ * BCM_MWBMAP_BITS_WORD: Number of bits in a bitmap word word
+ * BCM_MWBMAP_WORDS_MAX: Maximum number of bitmap words needed for free IDs.
+ * BCM_MWBMAP_WDMAP_MAX: Maximum number of bitmap wordss identifying first non
+ *                       non-zero bitmap word carrying at least one free ID.
+ * BCM_MWBMAP_SHIFT_OP:  Used in MOD, DIV and MUL operations.
+ * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID
+ *
+ * Design Notes:
+ * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many
+ * bits are computed each time on allocation and deallocation, requiring 4
+ * array indexed access and 3 arithmetic operations. When not defined, a runtime
+ * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed.
+ * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation.
+ * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may
+ * be used by defining BCM_MWBMAP_USE_CNTSETBITS.
+ *
+ * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array
+ * size is fixed. No intention to support larger than 4K indice allocation. ID
+ * allocators for ranges smaller than 4K will have a wastage of only 12Bytes
+ * with savings in not having to use an indirect access, had it been dynamically
+ * allocated.
+ */
+#if defined(DONGLEBUILD)
+#define BCM_MWBMAP_USE_CNTSETBITS	        /* runtime count set bits */
+#define BCM_MWBMAP_ITEMS_MAX	(4 * 1024)
+#else  /* ! DONGLEBUILD */
+#define BCM_MWBMAP_ITEMS_MAX    (64 * 1024)  /* May increase to 64K */
+#endif /*   DONGLEBUILD */
+
+#define BCM_MWBMAP_BITS_WORD    (NBITS(uint32))
+#define BCM_MWBMAP_WORDS_MAX    (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD)
+#define BCM_MWBMAP_WDMAP_MAX    (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD)
+#define BCM_MWBMAP_SHIFT_OP     (5)
+#define BCM_MWBMAP_MODOP(ix)    ((ix) & (BCM_MWBMAP_BITS_WORD - 1))
+#define BCM_MWBMAP_DIVOP(ix)    ((ix) >> BCM_MWBMAP_SHIFT_OP)
+#define BCM_MWBMAP_MULOP(ix)    ((ix) << BCM_MWBMAP_SHIFT_OP)
+
+/* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */
+#define BCM_MWBMAP_PTR(hdl)		((struct bcm_mwbmap *)(hdl))
+#define BCM_MWBMAP_HDL(ptr)		((void *)(ptr))
+
+#if defined(BCM_MWBMAP_DEBUG)
+#define BCM_MWBMAP_AUDIT(mwb) \
+	do { \
+		ASSERT((mwb != NULL) && \
+		       (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \
+		bcm_mwbmap_audit(mwb); \
+	} while (0)
+#define MWBMAP_ASSERT(exp)		ASSERT(exp)
+#define MWBMAP_DBG(x)           printf x
+#else   /* !BCM_MWBMAP_DEBUG */
+#define BCM_MWBMAP_AUDIT(mwb)   do {} while (0)
+#define MWBMAP_ASSERT(exp)		do {} while (0)
+#define MWBMAP_DBG(x)
+#endif  /* !BCM_MWBMAP_DEBUG */
+
+
+typedef struct bcm_mwbmap {     /* Hierarchical multiword bitmap allocator    */
+	uint16 wmaps;               /* Total number of words in free wd bitmap    */
+	uint16 imaps;               /* Total number of words in free id bitmap    */
+	int32  ifree;               /* Count of free indices. Used only in audits */
+	uint16 total;               /* Total indices managed by multiword bitmap  */
+
+	void * magic;               /* Audit handle parameter from user           */
+
+	uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of            */
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+	int8   wd_count[BCM_MWBMAP_WORDS_MAX];  /* free id running count, 1st lvl */
+#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
+
+	uint32 id_bitmap[0];        /* Second level bitmap                        */
+} bcm_mwbmap_t;
+
+/* Incarnate a hierarchical multiword bitmap based small index allocator. */
+struct bcm_mwbmap *
+BCMATTACHFN(bcm_mwbmap_init)(osl_t *osh, uint32 items_max)
+{
+	struct bcm_mwbmap * mwbmap_p;
+	uint32 wordix, size, words, extra;
+
+	/* Implementation Constraint: Uses 32bit word bitmap */
+	MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U);
+	MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U);
+	MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX));
+	MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U);
+
+	ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX);
+
+	/* Determine the number of words needed in the multiword bitmap */
+	extra = BCM_MWBMAP_MODOP(items_max);
+	words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U);
+
+	/* Allocate runtime state of multiword bitmap */
+	/* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */
+	size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words);
+	mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size);
+	if (mwbmap_p == (bcm_mwbmap_t *)NULL) {
+		ASSERT(0);
+		goto error1;
+	}
+	memset(mwbmap_p, 0, size);
+
+	/* Initialize runtime multiword bitmap state */
+	mwbmap_p->imaps = (uint16)words;
+	mwbmap_p->ifree = (int32)items_max;
+	mwbmap_p->total = (uint16)items_max;
+
+	/* Setup magic, for use in audit of handle */
+	mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p);
+
+	/* Setup the second level bitmap of free indices */
+	/* Mark all indices as available */
+	for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) {
+		mwbmap_p->id_bitmap[wordix] = (uint32)(~0U);
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+		mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD;
+#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
+	}
+
+	/* Ensure that extra indices are tagged as un-available */
+	if (extra) { /* fixup the free ids in last bitmap and wd_count */
+		uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1];
+		*bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+		mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */
+#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
+	}
+
+	/* Setup the first level bitmap hierarchy */
+	extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps);
+	words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U);
+
+	mwbmap_p->wmaps = (uint16)words;
+
+	for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++)
+		mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U);
+	if (extra) {
+		uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1];
+		*bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
+	}
+
+	return mwbmap_p;
+
+error1:
+	return BCM_MWBMAP_INVALID_HDL;
+}
+
+/* Release resources used by multiword bitmap based small index allocator. */
+void
+BCMATTACHFN(bcm_mwbmap_fini)(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl)
+{
+	bcm_mwbmap_t * mwbmap_p;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap)
+	                     + (sizeof(uint32) * mwbmap_p->imaps));
+	return;
+}
+
+/* Allocate a unique small index using a multiword bitmap index allocator.    */
+uint32 BCMFASTPATH
+bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl)
+{
+	bcm_mwbmap_t * mwbmap_p;
+	uint32 wordix, bitmap;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	/* Start with the first hierarchy */
+	for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) {
+
+		bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */
+
+		if (bitmap != 0U) {
+
+			uint32 count, bitix, *bitmap_p;
+
+			bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+			/* clear all except trailing 1 */
+			bitmap   = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
+			MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
+			              bcm_count_leading_zeros(bitmap));
+			bitix    = (BCM_MWBMAP_BITS_WORD - 1)
+			         - bcm_count_leading_zeros(bitmap); /* use asm clz */
+			wordix   = BCM_MWBMAP_MULOP(wordix) + bitix;
+
+			/* Clear bit if wd count is 0, without conditional branch */
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+			count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1;
+#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
+			mwbmap_p->wd_count[wordix]--;
+			count = mwbmap_p->wd_count[wordix];
+			MWBMAP_ASSERT(count ==
+			              (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+			MWBMAP_ASSERT(count >= 0);
+
+			/* clear wd_bitmap bit if id_map count is 0 */
+			bitmap = (count == 0) << bitix;
+
+			MWBMAP_DBG((
+			    "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
+			    bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count));
+
+			*bitmap_p ^= bitmap;
+
+			/* Use bitix in the second hierarchy */
+			bitmap_p = &mwbmap_p->id_bitmap[wordix];
+
+			bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */
+			MWBMAP_ASSERT(bitmap != 0U);
+
+			/* clear all except trailing 1 */
+			bitmap   = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
+			MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
+			              bcm_count_leading_zeros(bitmap));
+			bitix    = BCM_MWBMAP_MULOP(wordix)
+			         + (BCM_MWBMAP_BITS_WORD - 1)
+			         - bcm_count_leading_zeros(bitmap); /* use asm clz */
+
+			mwbmap_p->ifree--; /* decrement system wide free count */
+			MWBMAP_ASSERT(mwbmap_p->ifree >= 0);
+
+			MWBMAP_DBG((
+			    "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d",
+			    bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
+			    mwbmap_p->ifree));
+
+			*bitmap_p ^= bitmap; /* mark as allocated = 1b0 */
+
+			return bitix;
+		}
+	}
+
+	ASSERT(mwbmap_p->ifree == 0);
+
+	return BCM_MWBMAP_INVALID_IDX;
+}
+
+/* Force an index at a specified position to be in use */
+void
+bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
+{
+	bcm_mwbmap_t * mwbmap_p;
+	uint32 count, wordix, bitmap, *bitmap_p;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	ASSERT(bitix < mwbmap_p->total);
+
+	/* Start with second hierarchy */
+	wordix   = BCM_MWBMAP_DIVOP(bitix);
+	bitmap   = (uint32)(1U << BCM_MWBMAP_MODOP(bitix));
+	bitmap_p = &mwbmap_p->id_bitmap[wordix];
+
+	ASSERT((*bitmap_p & bitmap) == bitmap);
+
+	mwbmap_p->ifree--; /* update free count */
+	ASSERT(mwbmap_p->ifree >= 0);
+
+	MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d",
+	           bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
+	           mwbmap_p->ifree));
+
+	*bitmap_p ^= bitmap; /* mark as in use */
+
+	/* Update first hierarchy */
+	bitix    = wordix;
+
+	wordix   = BCM_MWBMAP_DIVOP(bitix);
+	bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+	count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
+#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
+	mwbmap_p->wd_count[bitix]--;
+	count = mwbmap_p->wd_count[bitix];
+	MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+	MWBMAP_ASSERT(count >= 0);
+
+	bitmap   = (count == 0) << BCM_MWBMAP_MODOP(bitix);
+
+	MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
+	           BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap,
+	           (*bitmap_p) ^ bitmap, count));
+
+	*bitmap_p ^= bitmap; /* mark as in use */
+
+	return;
+}
+
+/* Free a previously allocated index back into the multiword bitmap allocator */
+void BCMFASTPATH
+bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
+{
+	bcm_mwbmap_t * mwbmap_p;
+	uint32 wordix, bitmap, *bitmap_p;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	ASSERT(bitix < mwbmap_p->total);
+
+	/* Start with second level hierarchy */
+	wordix   = BCM_MWBMAP_DIVOP(bitix);
+	bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
+	bitmap_p = &mwbmap_p->id_bitmap[wordix];
+
+	ASSERT((*bitmap_p & bitmap) == 0U);	/* ASSERT not a double free */
+
+	mwbmap_p->ifree++; /* update free count */
+	ASSERT(mwbmap_p->ifree <= mwbmap_p->total);
+
+	MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d",
+	           bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap,
+	           mwbmap_p->ifree));
+
+	*bitmap_p |= bitmap; /* mark as available */
+
+	/* Now update first level hierarchy */
+
+	bitix    = wordix;
+
+	wordix   = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */
+	bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
+	bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
+	mwbmap_p->wd_count[bitix]++;
+#endif
+
+#if defined(BCM_MWBMAP_DEBUG)
+	{
+		uint32 count;
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+		count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
+#else  /*  ! BCM_MWBMAP_USE_CNTSETBITS */
+		count = mwbmap_p->wd_count[bitix];
+		MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
+#endif /*  ! BCM_MWBMAP_USE_CNTSETBITS */
+
+		MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD);
+
+		MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d",
+		            bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count));
+	}
+#endif /* BCM_MWBMAP_DEBUG */
+
+	*bitmap_p |= bitmap;
+
+	return;
+}
+
+/* Fetch the toal number of free indices in the multiword bitmap allocator */
+uint32
+bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl)
+{
+	bcm_mwbmap_t * mwbmap_p;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	ASSERT(mwbmap_p->ifree >= 0);
+
+	return mwbmap_p->ifree;
+}
+
+/* Determine whether an index is inuse or free */
+bool
+bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
+{
+	bcm_mwbmap_t * mwbmap_p;
+	uint32 wordix, bitmap;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	ASSERT(bitix < mwbmap_p->total);
+
+	wordix   = BCM_MWBMAP_DIVOP(bitix);
+	bitmap   = (1U << BCM_MWBMAP_MODOP(bitix));
+
+	return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U);
+}
+
+/* Debug dump a multiword bitmap allocator */
+void
+bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl)
+{
+	uint32 ix, count;
+	bcm_mwbmap_t * mwbmap_p;
+
+	BCM_MWBMAP_AUDIT(mwbmap_hdl);
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n",
+		OSL_OBFUSCATE_BUF((void *)mwbmap_p),
+	       mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total);
+	for (ix = 0U; ix < mwbmap_p->wmaps; ix++) {
+		printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]);
+		bcm_bitprint32(mwbmap_p->wd_bitmap[ix]);
+		printf("\n");
+	}
+	for (ix = 0U; ix < mwbmap_p->imaps; ix++) {
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+		count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]);
+#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
+		count = mwbmap_p->wd_count[ix];
+		MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix]));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+		printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count);
+		bcm_bitprint32(mwbmap_p->id_bitmap[ix]);
+		printf("\n");
+	}
+
+	return;
+}
+
+/* Audit a hierarchical multiword bitmap */
+void
+bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl)
+{
+	bcm_mwbmap_t * mwbmap_p;
+	uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p;
+
+	mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
+
+	for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) {
+
+		bitmap_p = &mwbmap_p->wd_bitmap[wordix];
+
+		for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) {
+			if ((*bitmap_p) & (1 << bitix)) {
+				idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix;
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
+				count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]);
+#else  /* ! BCM_MWBMAP_USE_CNTSETBITS */
+				count = mwbmap_p->wd_count[idmap_ix];
+				ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]));
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
+				ASSERT(count != 0U);
+				free_cnt += count;
+			}
+		}
+	}
+
+	ASSERT((int)free_cnt == mwbmap_p->ifree);
+}
+/* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */
+
+/* Simple 16bit Id allocator using a stack implementation. */
+typedef struct id16_map {
+	uint32  failures;  /* count of failures */
+	void    *dbg;      /* debug placeholder */
+	uint16  total;     /* total number of ids managed by allocator */
+	uint16  start;     /* start value of 16bit ids to be managed */
+	int     stack_idx; /* index into stack of available ids */
+	uint16  stack[0];  /* stack of 16 bit ids */
+} id16_map_t;
+
+#define ID16_MAP_SZ(items)      (sizeof(id16_map_t) + \
+	                             (sizeof(uint16) * (items)))
+
+#if defined(BCM_DBG)
+
+/* Uncomment BCM_DBG_ID16 to debug double free */
+/* #define BCM_DBG_ID16 */
+
+typedef struct id16_map_dbg {
+	uint16  total;
+	bool    avail[0];
+} id16_map_dbg_t;
+#define ID16_MAP_DBG_SZ(items)  (sizeof(id16_map_dbg_t) + \
+	                             (sizeof(bool) * (items)))
+#define ID16_MAP_MSG(x)         print x
+#else
+#define ID16_MAP_MSG(x)
+#endif /* BCM_DBG */
+
+void * /* Construct an id16 allocator: [start_val16 .. start_val16+total_ids) */
+id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16)
+{
+	uint16 idx, val16;
+	id16_map_t * id16_map;
+
+	ASSERT(total_ids > 0);
+
+	/* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
+	 * with random values.
+	 */
+	ASSERT((start_val16 == ID16_UNDEFINED) ||
+	       (start_val16 + total_ids) < ID16_INVALID);
+
+	id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids));
+	if (id16_map == NULL) {
+		return NULL;
+	}
+
+	id16_map->total = total_ids;
+	id16_map->start = start_val16;
+	id16_map->failures = 0;
+	id16_map->dbg = NULL;
+
+	/*
+	 * Populate stack with 16bit id values, commencing with start_val16.
+	 * if start_val16 is ID16_UNDEFINED, then do not populate the id16 map.
+	 */
+	id16_map->stack_idx = -1;
+
+	if (id16_map->start != ID16_UNDEFINED) {
+		val16 = start_val16;
+
+		for (idx = 0; idx < total_ids; idx++, val16++) {
+			id16_map->stack_idx = idx;
+			id16_map->stack[id16_map->stack_idx] = val16;
+		}
+	}
+
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
+	if (id16_map->start != ID16_UNDEFINED) {
+		id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids));
+
+		if (id16_map->dbg) {
+			id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
+
+			id16_map_dbg->total = total_ids;
+			for (idx = 0; idx < total_ids; idx++) {
+				id16_map_dbg->avail[idx] = TRUE;
+			}
+		}
+	}
+#endif /* BCM_DBG && BCM_DBG_ID16 */
+
+	return (void *)id16_map;
+}
+
+void * /* Destruct an id16 allocator instance */
+id16_map_fini(osl_t *osh, void * id16_map_hndl)
+{
+	uint16 total_ids;
+	id16_map_t * id16_map;
+
+	if (id16_map_hndl == NULL)
+		return NULL;
+
+	id16_map = (id16_map_t *)id16_map_hndl;
+
+	total_ids = id16_map->total;
+	ASSERT(total_ids > 0);
+
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
+	if (id16_map->dbg) {
+		MFREE(osh, id16_map->dbg, ID16_MAP_DBG_SZ(total_ids));
+		id16_map->dbg = NULL;
+	}
+#endif /* BCM_DBG && BCM_DBG_ID16 */
+
+	id16_map->total = 0;
+	MFREE(osh, id16_map, ID16_MAP_SZ(total_ids));
+
+	return NULL;
+}
+
+void
+id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16)
+{
+	uint16 idx, val16;
+	id16_map_t * id16_map;
+
+	ASSERT(total_ids > 0);
+	/* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
+	 * with random values.
+	 */
+	ASSERT((start_val16 == ID16_UNDEFINED) ||
+	       (start_val16 + total_ids) < ID16_INVALID);
+
+	id16_map = (id16_map_t *)id16_map_hndl;
+	if (id16_map == NULL) {
+		return;
+	}
+
+	id16_map->total = total_ids;
+	id16_map->start = start_val16;
+	id16_map->failures = 0;
+
+	/* Populate stack with 16bit id values, commencing with start_val16 */
+	id16_map->stack_idx = -1;
+
+	if (id16_map->start != ID16_UNDEFINED) {
+		val16 = start_val16;
+
+		for (idx = 0; idx < total_ids; idx++, val16++) {
+			id16_map->stack_idx = idx;
+			id16_map->stack[id16_map->stack_idx] = val16;
+		}
+	}
+
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
+	if (id16_map->start != ID16_UNDEFINED) {
+		if (id16_map->dbg) {
+			id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
+
+			id16_map_dbg->total = total_ids;
+			for (idx = 0; idx < total_ids; idx++) {
+				id16_map_dbg->avail[idx] = TRUE;
+			}
+		}
+	}
+#endif /* BCM_DBG && BCM_DBG_ID16 */
+}
+
+uint16 BCMFASTPATH /* Allocate a unique 16bit id */
+id16_map_alloc(void * id16_map_hndl)
+{
+	uint16 val16;
+	id16_map_t * id16_map;
+
+	ASSERT(id16_map_hndl != NULL);
+
+	id16_map = (id16_map_t *)id16_map_hndl;
+
+	ASSERT(id16_map->total > 0);
+
+	if (id16_map->stack_idx < 0) {
+		id16_map->failures++;
+		return ID16_INVALID;
+	}
+
+	val16 = id16_map->stack[id16_map->stack_idx];
+	id16_map->stack_idx--;
+
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
+	ASSERT((id16_map->start == ID16_UNDEFINED) ||
+	       (val16 < (id16_map->start + id16_map->total)));
+
+	if (id16_map->dbg) { /* Validate val16 */
+		id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
+
+		ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == TRUE);
+		id16_map_dbg->avail[val16 - id16_map->start] = FALSE;
+	}
+#endif /* BCM_DBG && BCM_DBG_ID16 */
+
+	return val16;
+}
+
+
+void BCMFASTPATH /* Free a 16bit id value into the id16 allocator */
+id16_map_free(void * id16_map_hndl, uint16 val16)
+{
+	id16_map_t * id16_map;
+
+	ASSERT(id16_map_hndl != NULL);
+
+	id16_map = (id16_map_t *)id16_map_hndl;
+
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
+	ASSERT((id16_map->start == ID16_UNDEFINED) ||
+	       (val16 < (id16_map->start + id16_map->total)));
+
+	if (id16_map->dbg) { /* Validate val16 */
+		id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
+
+		ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == FALSE);
+		id16_map_dbg->avail[val16 - id16_map->start] = TRUE;
+	}
+#endif /* BCM_DBG && BCM_DBG_ID16 */
+
+	id16_map->stack_idx++;
+	id16_map->stack[id16_map->stack_idx] = val16;
+}
+
+uint32 /* Returns number of failures to allocate an unique id16 */
+id16_map_failures(void * id16_map_hndl)
+{
+	ASSERT(id16_map_hndl != NULL);
+	return ((id16_map_t *)id16_map_hndl)->failures;
+}
+
+bool
+id16_map_audit(void * id16_map_hndl)
+{
+	int idx;
+	int insane = 0;
+	id16_map_t * id16_map;
+
+	ASSERT(id16_map_hndl != NULL);
+
+	id16_map = (id16_map_t *)id16_map_hndl;
+
+	ASSERT(id16_map->stack_idx >= -1);
+	ASSERT(id16_map->stack_idx < (int)id16_map->total);
+
+	if (id16_map->start == ID16_UNDEFINED)
+		goto done;
+
+	for (idx = 0; idx <= id16_map->stack_idx; idx++) {
+		ASSERT(id16_map->stack[idx] >= id16_map->start);
+		ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total));
+
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
+		if (id16_map->dbg) {
+			uint16 val16 = id16_map->stack[idx];
+			if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) {
+				insane |= 1;
+				ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n",
+				              OSL_OBFUSATE_BUF(id16_map_hndl), idx, val16));
+			}
+		}
+#endif /* BCM_DBG && BCM_DBG_ID16 */
+	}
+
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
+	if (id16_map->dbg) {
+		uint16 avail = 0; /* Audit available ids counts */
+		for (idx = 0; idx < id16_map_dbg->total; idx++) {
+			if (((id16_map_dbg_t *)(id16_map->dbg))->avail[idx16] == TRUE)
+				avail++;
+		}
+		if (avail && (avail != (id16_map->stack_idx + 1))) {
+			insane |= 1;
+			ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n",
+			              OSL_OBFUSCATE_BUF(id16_map_hndl),
+					avail, id16_map->stack_idx));
+		}
+	}
+#endif /* BCM_DBG && BCM_DBG_ID16 */
+
+done:
+	/* invoke any other system audits */
+	return (!!insane);
+}
+/* END: Simple id16 allocator */
+
+void
+BCMATTACHFN(dll_pool_detach)(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size)
+{
+	uint32 mem_size;
+	mem_size = sizeof(dll_pool_t) + (elems_max * elem_size);
+	if (pool)
+		MFREE(osh, pool, mem_size);
+}
+dll_pool_t *
+BCMATTACHFN(dll_pool_init)(void * osh, uint16 elems_max, uint16 elem_size)
+{
+	uint32 mem_size, i;
+	dll_pool_t * dll_pool_p;
+	dll_t * elem_p;
+
+	ASSERT(elem_size > sizeof(dll_t));
+
+	mem_size = sizeof(dll_pool_t) + (elems_max * elem_size);
+
+	if ((dll_pool_p = (dll_pool_t *)MALLOCZ(osh, mem_size)) == NULL) {
+		printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n",
+			elems_max, elem_size);
+		ASSERT(0);
+		return dll_pool_p;
+	}
+
+	dll_init(&dll_pool_p->free_list);
+	dll_pool_p->elems_max = elems_max;
+	dll_pool_p->elem_size = elem_size;
+
+	elem_p = dll_pool_p->elements;
+	for (i = 0; i < elems_max; i++) {
+		dll_append(&dll_pool_p->free_list, elem_p);
+		elem_p = (dll_t *)((uintptr)elem_p + elem_size);
+	}
+
+	dll_pool_p->free_count = elems_max;
+
+	return dll_pool_p;
+}
+
+
+void *
+dll_pool_alloc(dll_pool_t * dll_pool_p)
+{
+	dll_t * elem_p;
+
+	if (dll_pool_p->free_count == 0) {
+		ASSERT(dll_empty(&dll_pool_p->free_list));
+		return NULL;
+	}
+
+	elem_p = dll_head_p(&dll_pool_p->free_list);
+	dll_delete(elem_p);
+	dll_pool_p->free_count -= 1;
+
+	return (void *)elem_p;
+}
+
+void
+dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p)
+{
+	dll_t * node_p = (dll_t *)elem_p;
+	dll_prepend(&dll_pool_p->free_list, node_p);
+	dll_pool_p->free_count += 1;
+}
+
+
+void
+dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p)
+{
+	dll_t * node_p = (dll_t *)elem_p;
+	dll_append(&dll_pool_p->free_list, node_p);
+	dll_pool_p->free_count += 1;
+}
+
+#ifdef BCMDBG
+void
+dll_pool_dump(dll_pool_t * dll_pool_p, dll_elem_dump elem_dump)
+{
+	dll_t * elem_p;
+	dll_t * next_p;
+	printf("dll_pool<%p> free_count<%u> elems_max<%u> elem_size<%u>\n",
+		OSL_OBFUSCATE_BUF(dll_pool_p), dll_pool_p->free_count,
+		dll_pool_p->elems_max, dll_pool_p->elem_size);
+
+	for (elem_p = dll_head_p(&dll_pool_p->free_list);
+		 !dll_end(&dll_pool_p->free_list, elem_p); elem_p = next_p) {
+
+		next_p = dll_next_p(elem_p);
+		printf("\telem<%p>\n", OSL_OBFUSCATE_BUF(elem_p));
+		if (elem_dump != NULL)
+			elem_dump((void *)elem_p);
+	}
+}
+#endif /* BCMDBG */
+
+#endif 
+
+#endif /* BCMDRIVER */
+
+
+#if defined(BCMDRIVER) || defined(WL_UNITTEST)
+
+/* triggers bcm_bprintf to print to kernel log */
+bool bcm_bprintf_bypass = FALSE;
+
+/* Initialization of bcmstrbuf structure */
+void
+bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
+{
+	b->origsize = b->size = size;
+	b->origbuf = b->buf = buf;
+}
+
+/* Buffer sprintf wrapper to guard against buffer overflow */
+int
+bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
+{
+	va_list ap;
+	int r;
+
+	va_start(ap, fmt);
+
+	r = vsnprintf(b->buf, b->size, fmt, ap);
+	if (bcm_bprintf_bypass == TRUE) {
+		printf(b->buf);
+		goto exit;
+	}
+
+	/* Non Ansi C99 compliant returns -1,
+	 * Ansi compliant return r >= b->size,
+	 * bcmstdlib returns 0, handle all
+	 */
+	/* r == 0 is also the case when strlen(fmt) is zero.
+	 * typically the case when "" is passed as argument.
+	 */
+	if ((r == -1) || (r >= (int)b->size)) {
+		b->size = 0;
+	} else {
+		b->size -= r;
+		b->buf += r;
+	}
+
+exit:
+	va_end(ap);
+
+	return r;
+}
+
+void
+bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, const uint8 *buf, int len)
+{
+	int i;
+
+	if (msg != NULL && msg[0] != '\0')
+		bcm_bprintf(b, "%s", msg);
+	for (i = 0; i < len; i ++)
+		bcm_bprintf(b, "%02X", buf[i]);
+	if (newline)
+		bcm_bprintf(b, "\n");
+}
+
+void
+bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount)
+{
+	int i;
+
+	for (i = 0; i < num_bytes; i++) {
+		num[i] += amount;
+		if (num[i] >= amount)
+			break;
+		amount = 1;
+	}
+}
+
+int
+bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes)
+{
+	int i;
+
+	for (i = nbytes - 1; i >= 0; i--) {
+		if (arg1[i] != arg2[i])
+			return (arg1[i] - arg2[i]);
+	}
+	return 0;
+}
+
+void
+bcm_print_bytes(const char *name, const uchar *data, int len)
+{
+	int i;
+	int per_line = 0;
+
+	printf("%s: %d \n", name ? name : "", len);
+	for (i = 0; i < len; i++) {
+		printf("%02x ", *data++);
+		per_line++;
+		if (per_line == 16) {
+			per_line = 0;
+			printf("\n");
+		}
+	}
+	printf("\n");
+}
+
+/* Look for vendor-specific IE with specified OUI and optional type */
+bcm_tlv_t *
+bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type, int type_len)
+{
+	bcm_tlv_t *ie;
+	uint8 ie_len;
+
+	ie = (bcm_tlv_t*)tlvs;
+
+	/* make sure we are looking at a valid IE */
+	if (ie == NULL || !bcm_valid_tlv(ie, tlvs_len)) {
+		return NULL;
+	}
+
+	/* Walk through the IEs looking for an OUI match */
+	do {
+		ie_len = ie->len;
+		if ((ie->id == DOT11_MNG_VS_ID) &&
+		    (ie_len >= (DOT11_OUI_LEN + type_len)) &&
+		    !bcmp(ie->data, voui, DOT11_OUI_LEN))
+		{
+			/* compare optional type */
+			if (type_len == 0 ||
+			    !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) {
+				return (ie);		/* a match */
+			}
+		}
+	} while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL);
+
+	return NULL;
+}
+
+#if defined(WLTINYDUMP) || defined(BCMDBG) || defined(WLMSG_INFORM) || \
+	defined(WLMSG_ASSOC) || defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
+#define SSID_FMT_BUF_LEN	((4 * DOT11_MAX_SSID_LEN) + 1)
+
+int
+bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len)
+{
+	uint i, c;
+	char *p = buf;
+	char *endp = buf + SSID_FMT_BUF_LEN;
+
+	if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN;
+
+	for (i = 0; i < ssid_len; i++) {
+		c = (uint)ssid[i];
+		if (c == '\\') {
+			*p++ = '\\';
+			*p++ = '\\';
+		} else if (bcm_isprint((uchar)c)) {
+			*p++ = (char)c;
+		} else {
+			p += snprintf(p, (endp - p), "\\x%02X", c);
+		}
+	}
+	*p = '\0';
+	ASSERT(p < endp);
+
+	return (int)(p - buf);
+}
+#endif /* WLTINYDUMP || BCMDBG || WLMSG_INFORM || WLMSG_ASSOC || WLMSG_PRPKT */
+
+#endif /* BCMDRIVER || WL_UNITTEST */
+
+char *
+bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
+{
+	static const char hex[] =
+	  {
+		  '0', '1', '2', '3', '4', '5', '6', '7',
+		  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+	  };
+	const uint8 *octet = ea->octet;
+	char *p = buf;
+	int i;
+
+	for (i = 0; i < 6; i++, octet++) {
+		*p++ = hex[(*octet >> 4) & 0xf];
+		*p++ = hex[*octet & 0xf];
+		*p++ = ':';
+	}
+
+	*(p-1) = '\0';
+
+	return (buf);
+}
+
+/* Find the position of first bit set
+ * in the given number.
+ */
+int
+bcm_find_fsb(uint32 num)
+{
+	uint8 pos = 0;
+	if (!num)
+		return pos;
+	while (!(num & 1)) {
+		num >>= 1;
+		pos++;
+	}
+	return (pos+1);
+}
+
+char *
+bcm_ip_ntoa(struct ipv4_addr *ia, char *buf)
+{
+	snprintf(buf, 16, "%d.%d.%d.%d",
+	         ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]);
+	return (buf);
+}
+
+char *
+bcm_ipv6_ntoa(void *ipv6, char *buf)
+{
+	/* Implementing RFC 5952 Sections 4 + 5 */
+	/* Not thoroughly tested */
+	uint16 tmp[8];
+	uint16 *a = &tmp[0];
+	char *p = buf;
+	int i, i_max = -1, cnt = 0, cnt_max = 1;
+	uint8 *a4 = NULL;
+	memcpy((uint8 *)&tmp[0], (uint8 *)ipv6, IPV6_ADDR_LEN);
+
+	for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
+		if (a[i]) {
+			if (cnt > cnt_max) {
+				cnt_max = cnt;
+				i_max = i - cnt;
+			}
+			cnt = 0;
+		} else
+			cnt++;
+	}
+	if (cnt > cnt_max) {
+		cnt_max = cnt;
+		i_max = i - cnt;
+	}
+	if (i_max == 0 &&
+		/* IPv4-translated: ::ffff:0:a.b.c.d */
+		((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) ||
+		/* IPv4-mapped: ::ffff:a.b.c.d */
+		(cnt_max == 5 && a[5] == 0xffff)))
+		a4 = (uint8*) (a + 6);
+
+	for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
+		if ((uint8*) (a + i) == a4) {
+			snprintf(p, 16, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]);
+			break;
+		} else if (i == i_max) {
+			*p++ = ':';
+			i += cnt_max - 1;
+			p[0] = ':';
+			p[1] = '\0';
+		} else {
+			if (i)
+				*p++ = ':';
+			p += snprintf(p, 8, "%x", ntoh16(a[i]));
+		}
+	}
+
+	return buf;
+}
+
+#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
+const unsigned char bcm_ctype[] = {
+
+	_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,			/* 0-7 */
+	_BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C,
+	_BCM_C,	/* 8-15 */
+	_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,			/* 16-23 */
+	_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,			/* 24-31 */
+	_BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,		/* 32-39 */
+	_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,			/* 40-47 */
+	_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,			/* 48-55 */
+	_BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,			/* 56-63 */
+	_BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X,
+	_BCM_U|_BCM_X, _BCM_U, /* 64-71 */
+	_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,			/* 72-79 */
+	_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,			/* 80-87 */
+	_BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,			/* 88-95 */
+	_BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X,
+	_BCM_L|_BCM_X, _BCM_L, /* 96-103 */
+	_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */
+	_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */
+	_BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		/* 128-143 */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,		/* 144-159 */
+	_BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
+	_BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,	/* 160-175 */
+	_BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,
+	_BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P,	/* 176-191 */
+	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,
+	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U,	/* 192-207 */
+	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U,
+	_BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L,	/* 208-223 */
+	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,
+	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L,	/* 224-239 */
+	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L,
+	_BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */
+};
+
+uint64
+bcm_strtoull(const char *cp, char **endp, uint base)
+{
+	uint64 result, last_result = 0, value;
+	bool minus;
+
+	minus = FALSE;
+
+	while (bcm_isspace(*cp))
+		cp++;
+
+	if (cp[0] == '+')
+		cp++;
+	else if (cp[0] == '-') {
+		minus = TRUE;
+		cp++;
+	}
+
+	if (base == 0) {
+		if (cp[0] == '0') {
+			if ((cp[1] == 'x') || (cp[1] == 'X')) {
+				base = 16;
+				cp = &cp[2];
+			} else {
+				base = 8;
+				cp = &cp[1];
+			}
+		} else
+			base = 10;
+	} else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) {
+		cp = &cp[2];
+	}
+
+	result = 0;
+
+	while (bcm_isxdigit(*cp) &&
+	       (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
+		result = result*base + value;
+		/* Detected overflow */
+		if (result < last_result && !minus) {
+			if (endp) {
+				/* Go to the end of current number */
+				while (bcm_isxdigit(*cp)) {
+					cp++;
+				}
+				*endp = DISCARD_QUAL(cp, char);
+			}
+			return (ulong)-1;
+		}
+		last_result = result;
+		cp++;
+	}
+
+	if (minus)
+		result = (ulong)(-(long)result);
+
+	if (endp)
+		*endp = DISCARD_QUAL(cp, char);
+
+	return (result);
+}
+
+ulong
+bcm_strtoul(const char *cp, char **endp, uint base)
+{
+	return (ulong) bcm_strtoull(cp, endp, base);
+}
+
+int
+bcm_atoi(const char *s)
+{
+	return (int)bcm_strtoul(s, NULL, 10);
+}
+
+/* return pointer to location of substring 'needle' in 'haystack' */
+char *
+bcmstrstr(const char *haystack, const char *needle)
+{
+	int len, nlen;
+	int i;
+
+	if ((haystack == NULL) || (needle == NULL))
+		return DISCARD_QUAL(haystack, char);
+
+	nlen = (int)strlen(needle);
+	len = (int)strlen(haystack) - nlen + 1;
+
+	for (i = 0; i < len; i++)
+		if (memcmp(needle, &haystack[i], nlen) == 0)
+			return DISCARD_QUAL(&haystack[i], char);
+	return (NULL);
+}
+
+char *
+bcmstrnstr(const char *s, uint s_len, const char *substr, uint substr_len)
+{
+	for (; s_len >= substr_len; s++, s_len--)
+		if (strncmp(s, substr, substr_len) == 0)
+			return DISCARD_QUAL(s, char);
+
+	return NULL;
+}
+
+char *
+bcmstrcat(char *dest, const char *src)
+{
+	char *p;
+
+	p = dest + strlen(dest);
+
+	while ((*p++ = *src++) != '\0')
+		;
+
+	return (dest);
+}
+
+char *
+bcmstrncat(char *dest, const char *src, uint size)
+{
+	char *endp;
+	char *p;
+
+	p = dest + strlen(dest);
+	endp = p + size;
+
+	while (p != endp && (*p++ = *src++) != '\0')
+		;
+
+	return (dest);
+}
+
+
+/****************************************************************************
+* Function:   bcmstrtok
+*
+* Purpose:
+*  Tokenizes a string. This function is conceptually similiar to ANSI C strtok(),
+*  but allows strToken() to be used by different strings or callers at the same
+*  time. Each call modifies '*string' by substituting a NULL character for the
+*  first delimiter that is encountered, and updates 'string' to point to the char
+*  after the delimiter. Leading delimiters are skipped.
+*
+* Parameters:
+*  string      (mod) Ptr to string ptr, updated by token.
+*  delimiters  (in)  Set of delimiter characters.
+*  tokdelim    (out) Character that delimits the returned token. (May
+*                    be set to NULL if token delimiter is not required).
+*
+* Returns:  Pointer to the next token found. NULL when no more tokens are found.
+*****************************************************************************
+*/
+char *
+bcmstrtok(char **string, const char *delimiters, char *tokdelim)
+{
+	unsigned char *str;
+	unsigned long map[8];
+	int count;
+	char *nextoken;
+
+	if (tokdelim != NULL) {
+		/* Prime the token delimiter */
+		*tokdelim = '\0';
+	}
+
+	/* Clear control map */
+	for (count = 0; count < 8; count++) {
+		map[count] = 0;
+	}
+
+	/* Set bits in delimiter table */
+	do {
+		map[*delimiters >> 5] |= (1 << (*delimiters & 31));
+	}
+	while (*delimiters++);
+
+	str = (unsigned char*)*string;
+
+	/* Find beginning of token (skip over leading delimiters). Note that
+	 * there is no token iff this loop sets str to point to the terminal
+	 * null (*str == '\0')
+	 */
+	while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) {
+		str++;
+	}
+
+	nextoken = (char*)str;
+
+	/* Find the end of the token. If it is not the end of the string,
+	 * put a null there.
+	 */
+	for (; *str; str++) {
+		if (map[*str >> 5] & (1 << (*str & 31))) {
+			if (tokdelim != NULL) {
+				*tokdelim = *str;
+			}
+
+			*str++ = '\0';
+			break;
+		}
+	}
+
+	*string = (char*)str;
+
+	/* Determine if a token has been found. */
+	if (nextoken == (char *) str) {
+		return NULL;
+	}
+	else {
+		return nextoken;
+	}
+}
+
+
+#define xToLower(C) \
+	((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C)
+
+
+/****************************************************************************
+* Function:   bcmstricmp
+*
+* Purpose:    Compare to strings case insensitively.
+*
+* Parameters: s1 (in) First string to compare.
+*             s2 (in) Second string to compare.
+*
+* Returns:    Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
+*             t1 > t2, when ignoring case sensitivity.
+*****************************************************************************
+*/
+int
+bcmstricmp(const char *s1, const char *s2)
+{
+	char dc, sc;
+
+	while (*s2 && *s1) {
+		dc = xToLower(*s1);
+		sc = xToLower(*s2);
+		if (dc < sc) return -1;
+		if (dc > sc) return 1;
+		s1++;
+		s2++;
+	}
+
+	if (*s1 && !*s2) return 1;
+	if (!*s1 && *s2) return -1;
+	return 0;
+}
+
+
+/****************************************************************************
+* Function:   bcmstrnicmp
+*
+* Purpose:    Compare to strings case insensitively, upto a max of 'cnt'
+*             characters.
+*
+* Parameters: s1  (in) First string to compare.
+*             s2  (in) Second string to compare.
+*             cnt (in) Max characters to compare.
+*
+* Returns:    Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if
+*             t1 > t2, when ignoring case sensitivity.
+*****************************************************************************
+*/
+int
+bcmstrnicmp(const char* s1, const char* s2, int cnt)
+{
+	char dc, sc;
+
+	while (*s2 && *s1 && cnt) {
+		dc = xToLower(*s1);
+		sc = xToLower(*s2);
+		if (dc < sc) return -1;
+		if (dc > sc) return 1;
+		s1++;
+		s2++;
+		cnt--;
+	}
+
+	if (!cnt) return 0;
+	if (*s1 && !*s2) return 1;
+	if (!*s1 && *s2) return -1;
+	return 0;
+}
+
+/* parse a xx:xx:xx:xx:xx:xx format ethernet address */
+int
+bcm_ether_atoe(const char *p, struct ether_addr *ea)
+{
+	int i = 0;
+	char *ep;
+
+	for (;;) {
+		ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16);
+		p = ep;
+		if (!*p++ || i == 6)
+			break;
+	}
+
+	return (i == 6);
+}
+
+int
+bcm_atoipv4(const char *p, struct ipv4_addr *ip)
+{
+
+	int i = 0;
+	char *c;
+	for (;;) {
+		ip->addr[i++] = (uint8)bcm_strtoul(p, &c, 0);
+		if (*c++ != '.' || i == IPV4_ADDR_LEN)
+			break;
+		p = c;
+	}
+	return (i == IPV4_ADDR_LEN);
+}
+#endif	/* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
+
+#ifdef DONGLEBUILD
+
+const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}};
+const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}};
+const struct ether_addr ether_ipv6_mcast = {{0x33, 0x33, 0x00, 0x00, 0x00, 0x01}};
+
+int
+ether_isbcast(const void *ea)
+{
+	return (memcmp(ea, &ether_bcast, sizeof(struct ether_addr)) == 0);
+}
+
+int
+ether_isnulladdr(const void *ea)
+{
+	uint8 *u8 = (uint8*)ea;
+	return !(u8[5] || u8[4] || u8[3] || u8[2] || u8[1] || u8[0]);
+}
+
+#endif /* DONGLEBUILD */
+
+#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER)
+/* registry routine buffer preparation utility functions:
+ * parameter order is like strncpy, but returns count
+ * of bytes copied. Minimum bytes copied is null char(1)/wchar(2)
+ */
+ulong
+wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen)
+{
+	ulong copyct = 1;
+	ushort i;
+
+	if (abuflen == 0)
+		return 0;
+
+	/* wbuflen is in bytes */
+	wbuflen /= sizeof(ushort);
+
+	for (i = 0; i < wbuflen; ++i) {
+		if (--abuflen == 0)
+			break;
+		*abuf++ = (char) *wbuf++;
+		++copyct;
+	}
+	*abuf = '\0';
+
+	return copyct;
+}
+#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */
+
+#ifdef BCM_OBJECT_TRACE
+
+#define BCM_OBJECT_MERGE_SAME_OBJ	0
+
+/* some place may add / remove the object to trace list for Linux: */
+/* add:    osl_alloc_skb dev_alloc_skb skb_realloc_headroom dhd_start_xmit */
+/* remove: osl_pktfree dev_kfree_skb netif_rx */
+
+#if defined(linux)
+#define BCM_OBJDBG_COUNT          (1024 * 100)
+static spinlock_t dbgobj_lock;
+#define	BCM_OBJDBG_LOCK_INIT()    spin_lock_init(&dbgobj_lock)
+#define	BCM_OBJDBG_LOCK_DESTROY()
+#define	BCM_OBJDBG_LOCK           spin_lock_irqsave
+#define	BCM_OBJDBG_UNLOCK         spin_unlock_irqrestore
+#elif defined(__FreeBSD__)
+#define BCM_OBJDBG_COUNT          (1024 * 100)
+struct mtx dbgobj_lock;
+#define	BCM_OBJDBG_LOCK_INIT()    MTX_INIT(&dbgobj_lock, "objdbg", NULL, MTX_DEF)
+#define	BCM_OBJDBG_LOCK_DESTROY() MTX_DESTROY(&dbgobj_lock)
+#define	BCM_OBJDBG_LOCK(x, y)     MTX_LOCK(x)
+#define	BCM_OBJDBG_UNLOCK(x, y)   MTX_UNLOCK(x)
+#else
+#define BCM_OBJDBG_COUNT          (256)
+#define BCM_OBJDBG_LOCK_INIT()
+#define	BCM_OBJDBG_LOCK_DESTROY()
+#define BCM_OBJDBG_LOCK(x, y)
+#define BCM_OBJDBG_UNLOCK(x, y)
+#endif /* else OS */
+
+#define BCM_OBJDBG_ADDTOHEAD      0
+#define BCM_OBJDBG_ADDTOTAIL      1
+
+#define BCM_OBJDBG_CALLER_LEN     32
+struct bcm_dbgobj {
+	struct bcm_dbgobj *prior;
+	struct bcm_dbgobj *next;
+	uint32 flag;
+	void   *obj;
+	uint32 obj_sn;
+	uint32 obj_state;
+	uint32 line;
+	char   caller[BCM_OBJDBG_CALLER_LEN];
+};
+
+static struct bcm_dbgobj *dbgobj_freehead = NULL;
+static struct bcm_dbgobj *dbgobj_freetail = NULL;
+static struct bcm_dbgobj *dbgobj_objhead = NULL;
+static struct bcm_dbgobj *dbgobj_objtail = NULL;
+
+static uint32 dbgobj_sn = 0;
+static int dbgobj_count = 0;
+static struct bcm_dbgobj bcm_dbg_objs[BCM_OBJDBG_COUNT];
+
+void
+bcm_object_trace_init(void)
+{
+	int i = 0;
+	BCM_OBJDBG_LOCK_INIT();
+	memset(&bcm_dbg_objs, 0x00, sizeof(struct bcm_dbgobj) * BCM_OBJDBG_COUNT);
+	dbgobj_freehead = &bcm_dbg_objs[0];
+	dbgobj_freetail = &bcm_dbg_objs[BCM_OBJDBG_COUNT - 1];
+
+	for (i = 0; i < BCM_OBJDBG_COUNT; ++i) {
+		bcm_dbg_objs[i].next = (i == (BCM_OBJDBG_COUNT - 1)) ?
+			dbgobj_freehead : &bcm_dbg_objs[i + 1];
+		bcm_dbg_objs[i].prior = (i == 0) ?
+			dbgobj_freetail : &bcm_dbg_objs[i - 1];
+	}
+}
+
+void
+bcm_object_trace_deinit(void)
+{
+	if (dbgobj_objhead || dbgobj_objtail) {
+		printf("%s: not all objects are released\n", __FUNCTION__);
+		ASSERT(0);
+	}
+	BCM_OBJDBG_LOCK_DESTROY();
+}
+
+static void
+bcm_object_rm_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
+	struct bcm_dbgobj *dbgobj)
+{
+	if ((dbgobj == *head) && (dbgobj == *tail)) {
+		*head = NULL;
+		*tail = NULL;
+	} else if (dbgobj == *head) {
+		*head = (*head)->next;
+	} else if (dbgobj == *tail) {
+		*tail = (*tail)->prior;
+	}
+	dbgobj->next->prior = dbgobj->prior;
+	dbgobj->prior->next = dbgobj->next;
+}
+
+static void
+bcm_object_add_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
+	struct bcm_dbgobj *dbgobj, int addtotail)
+{
+	if (!(*head) && !(*tail)) {
+		*head = dbgobj;
+		*tail = dbgobj;
+		dbgobj->next = dbgobj;
+		dbgobj->prior = dbgobj;
+	} else if ((*head) && (*tail)) {
+		(*tail)->next = dbgobj;
+		(*head)->prior = dbgobj;
+		dbgobj->next = *head;
+		dbgobj->prior = *tail;
+		if (addtotail == BCM_OBJDBG_ADDTOTAIL)
+			*tail = dbgobj;
+		else
+			*head = dbgobj;
+	} else {
+		ASSERT(0); /* can't be this case */
+	}
+}
+
+static INLINE void
+bcm_object_movetoend(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
+	struct bcm_dbgobj *dbgobj, int movetotail)
+{
+	if ((*head) && (*tail)) {
+		if (movetotail == BCM_OBJDBG_ADDTOTAIL) {
+			if (dbgobj != (*tail)) {
+				bcm_object_rm_list(head, tail, dbgobj);
+				bcm_object_add_list(head, tail, dbgobj, movetotail);
+			}
+		} else {
+			if (dbgobj != (*head)) {
+				bcm_object_rm_list(head, tail, dbgobj);
+				bcm_object_add_list(head, tail, dbgobj, movetotail);
+			}
+		}
+	} else {
+		ASSERT(0); /* can't be this case */
+	}
+}
+
+void
+bcm_object_trace_opr(void *obj, uint32 opt, const char *caller, int line)
+{
+	struct bcm_dbgobj *dbgobj;
+	unsigned long flags;
+
+	BCM_REFERENCE(flags);
+	BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
+
+	if (opt == BCM_OBJDBG_ADD_PKT ||
+		opt == BCM_OBJDBG_ADD) {
+		dbgobj = dbgobj_objtail;
+		while (dbgobj) {
+			if (dbgobj->obj == obj) {
+				printf("%s: obj %p allocated from %s(%d),"
+					" allocate again from %s(%d)\n",
+					__FUNCTION__, dbgobj->obj,
+					dbgobj->caller, dbgobj->line,
+					caller, line);
+				ASSERT(0);
+				goto EXIT;
+			}
+			dbgobj = dbgobj->prior;
+			if (dbgobj == dbgobj_objtail)
+				break;
+		}
+
+#if BCM_OBJECT_MERGE_SAME_OBJ
+		dbgobj = dbgobj_freetail;
+		while (dbgobj) {
+			if (dbgobj->obj == obj) {
+				goto FREED_ENTRY_FOUND;
+			}
+			dbgobj = dbgobj->prior;
+			if (dbgobj == dbgobj_freetail)
+				break;
+		}
+#endif /* BCM_OBJECT_MERGE_SAME_OBJ */
+
+		dbgobj = dbgobj_freehead;
+#if BCM_OBJECT_MERGE_SAME_OBJ
+FREED_ENTRY_FOUND:
+#endif /* BCM_OBJECT_MERGE_SAME_OBJ */
+		if (!dbgobj) {
+			printf("%s: already got %d objects ?????????????????????\n",
+				__FUNCTION__, BCM_OBJDBG_COUNT);
+			ASSERT(0);
+			goto EXIT;
+		}
+
+		bcm_object_rm_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj);
+		dbgobj->obj = obj;
+		strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN);
+		dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0';
+		dbgobj->line = line;
+		dbgobj->flag = 0;
+		if (opt == BCM_OBJDBG_ADD_PKT) {
+			dbgobj->obj_sn = dbgobj_sn++;
+			dbgobj->obj_state = 0;
+			/* first 4 bytes is pkt sn */
+			if (((unsigned long)PKTTAG(obj)) & 0x3)
+				printf("pkt tag address not aligned by 4: %p\n", PKTTAG(obj));
+			*(uint32*)PKTTAG(obj) = dbgobj->obj_sn;
+		}
+		bcm_object_add_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj,
+			BCM_OBJDBG_ADDTOTAIL);
+
+		dbgobj_count++;
+
+	} else if (opt == BCM_OBJDBG_REMOVE) {
+		dbgobj = dbgobj_objtail;
+		while (dbgobj) {
+			if (dbgobj->obj == obj) {
+				if (dbgobj->flag) {
+					printf("%s: rm flagged obj %p flag 0x%08x from %s(%d)\n",
+						__FUNCTION__, obj, dbgobj->flag, caller, line);
+				}
+				bcm_object_rm_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj);
+				memset(dbgobj->caller, 0x00, BCM_OBJDBG_CALLER_LEN);
+				strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN);
+				dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0';
+				dbgobj->line = line;
+				bcm_object_add_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj,
+					BCM_OBJDBG_ADDTOTAIL);
+				dbgobj_count--;
+				goto EXIT;
+			}
+			dbgobj = dbgobj->prior;
+			if (dbgobj == dbgobj_objtail)
+				break;
+		}
+
+		dbgobj = dbgobj_freetail;
+		while (dbgobj && dbgobj->obj) {
+			if (dbgobj->obj == obj) {
+				printf("%s: obj %p already freed from from %s(%d),"
+					" try free again from %s(%d)\n",
+					__FUNCTION__, obj,
+					dbgobj->caller, dbgobj->line,
+					caller, line);
+				//ASSERT(0); /* release same obj more than one time? */
+				goto EXIT;
+			}
+			dbgobj = dbgobj->prior;
+			if (dbgobj == dbgobj_freetail)
+				break;
+		}
+
+		printf("%s: ################### release none-existing obj %p from %s(%d)\n",
+			__FUNCTION__, obj, caller, line);
+		//ASSERT(0); /* release same obj more than one time? */
+
+	}
+
+EXIT:
+	BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
+	return;
+}
+
+void
+bcm_object_trace_upd(void *obj, void *obj_new)
+{
+	struct bcm_dbgobj *dbgobj;
+	unsigned long flags;
+
+	BCM_REFERENCE(flags);
+	BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
+
+	dbgobj = dbgobj_objtail;
+	while (dbgobj) {
+		if (dbgobj->obj == obj) {
+			dbgobj->obj = obj_new;
+			if (dbgobj != dbgobj_objtail) {
+				bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
+					dbgobj, BCM_OBJDBG_ADDTOTAIL);
+			}
+			goto EXIT;
+		}
+		dbgobj = dbgobj->prior;
+		if (dbgobj == dbgobj_objtail)
+			break;
+	}
+
+EXIT:
+	BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
+	return;
+}
+
+void
+bcm_object_trace_chk(void *obj, uint32 chksn, uint32 sn,
+	const char *caller, int line)
+{
+	struct bcm_dbgobj *dbgobj;
+	unsigned long flags;
+
+	BCM_REFERENCE(flags);
+	BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
+
+	dbgobj = dbgobj_objtail;
+	while (dbgobj) {
+		if ((dbgobj->obj == obj) &&
+			((!chksn) || (dbgobj->obj_sn == sn))) {
+			if (dbgobj != dbgobj_objtail) {
+				bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
+					dbgobj, BCM_OBJDBG_ADDTOTAIL);
+			}
+			goto EXIT;
+		}
+		dbgobj = dbgobj->prior;
+		if (dbgobj == dbgobj_objtail)
+			break;
+	}
+
+	dbgobj = dbgobj_freetail;
+	while (dbgobj) {
+		if ((dbgobj->obj == obj) &&
+			((!chksn) || (dbgobj->obj_sn == sn))) {
+			printf("%s: (%s:%d) obj %p (sn %d state %d) was freed from %s(%d)\n",
+				__FUNCTION__, caller, line,
+				dbgobj->obj, dbgobj->obj_sn, dbgobj->obj_state,
+				dbgobj->caller, dbgobj->line);
+			goto EXIT;
+		}
+		else if (dbgobj->obj == NULL) {
+			break;
+		}
+		dbgobj = dbgobj->prior;
+		if (dbgobj == dbgobj_freetail)
+			break;
+	}
+
+	printf("%s: obj %p not found, check from %s(%d), chksn %s, sn %d\n",
+		__FUNCTION__, obj, caller, line, chksn ? "yes" : "no", sn);
+	dbgobj = dbgobj_objtail;
+	while (dbgobj) {
+		printf("%s: (%s:%d) obj %p sn %d was allocated from %s(%d)\n",
+				__FUNCTION__, caller, line,
+				dbgobj->obj, dbgobj->obj_sn, dbgobj->caller, dbgobj->line);
+		dbgobj = dbgobj->prior;
+		if (dbgobj == dbgobj_objtail)
+			break;
+	}
+
+EXIT:
+	BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
+	return;
+}
+
+void
+bcm_object_feature_set(void *obj, uint32 type, uint32 value)
+{
+	struct bcm_dbgobj *dbgobj;
+	unsigned long flags;
+
+	BCM_REFERENCE(flags);
+	BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
+
+	dbgobj = dbgobj_objtail;
+	while (dbgobj) {
+		if (dbgobj->obj == obj) {
+			if (type == BCM_OBJECT_FEATURE_FLAG) {
+				if (value & BCM_OBJECT_FEATURE_CLEAR)
+					dbgobj->flag &= ~(value);
+				else
+					dbgobj->flag |= (value);
+			} else if (type == BCM_OBJECT_FEATURE_PKT_STATE) {
+				dbgobj->obj_state = value;
+			}
+			if (dbgobj != dbgobj_objtail) {
+				bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
+					dbgobj, BCM_OBJDBG_ADDTOTAIL);
+			}
+			goto EXIT;
+		}
+		dbgobj = dbgobj->prior;
+		if (dbgobj == dbgobj_objtail)
+			break;
+	}
+
+	printf("%s: obj %p not found in active list\n", __FUNCTION__, obj);
+	ASSERT(0);
+
+EXIT:
+	BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
+	return;
+}
+
+int
+bcm_object_feature_get(void *obj, uint32 type, uint32 value)
+{
+	int rtn = 0;
+	struct bcm_dbgobj *dbgobj;
+	unsigned long flags;
+
+	BCM_REFERENCE(flags);
+	BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
+
+	dbgobj = dbgobj_objtail;
+	while (dbgobj) {
+		if (dbgobj->obj == obj) {
+			if (type == BCM_OBJECT_FEATURE_FLAG) {
+				rtn = (dbgobj->flag & value) & (~BCM_OBJECT_FEATURE_CLEAR);
+			}
+			if (dbgobj != dbgobj_objtail) {
+				bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
+					dbgobj, BCM_OBJDBG_ADDTOTAIL);
+			}
+			goto EXIT;
+		}
+		dbgobj = dbgobj->prior;
+		if (dbgobj == dbgobj_objtail)
+			break;
+	}
+
+	printf("%s: obj %p not found in active list\n", __FUNCTION__, obj);
+	ASSERT(0);
+
+EXIT:
+	BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
+	return rtn;
+}
+
+#endif /* BCM_OBJECT_TRACE */
+
+uint8 *
+bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst)
+{
+	uint8 *new_dst = dst;
+	bcm_tlv_t *dst_tlv = (bcm_tlv_t *)dst;
+
+	/* dst buffer should always be valid */
+	ASSERT(dst);
+
+	/* data len must be within valid range */
+	ASSERT((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE));
+
+	/* source data buffer pointer should be valid, unless datalen is 0
+	 * meaning no data with this TLV
+	 */
+	ASSERT((data != NULL) || (datalen == 0));
+
+	/* only do work if the inputs are valid
+	 * - must have a dst to write to AND
+	 * - datalen must be within range AND
+	 * - the source data pointer must be non-NULL if datalen is non-zero
+	 * (this last condition detects datalen > 0 with a NULL data pointer)
+	 */
+	if ((dst != NULL) &&
+	    ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) &&
+	    ((data != NULL) || (datalen == 0))) {
+
+	        /* write type, len fields */
+		dst_tlv->id = (uint8)type;
+	        dst_tlv->len = (uint8)datalen;
+
+		/* if data is present, copy to the output buffer and update
+		 * pointer to output buffer
+		 */
+		if (datalen > 0) {
+
+			memcpy(dst_tlv->data, data, datalen);
+		}
+
+		/* update the output destination poitner to point past
+		 * the TLV written
+		 */
+		new_dst = dst + BCM_TLV_HDR_SIZE + datalen;
+	}
+
+	return (new_dst);
+}
+
+uint8 *
+bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst, int dst_maxlen)
+{
+	uint8 *new_dst = dst;
+
+	if ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) {
+
+		/* if len + tlv hdr len is more than destlen, don't do anything
+		 * just return the buffer untouched
+		 */
+		if ((int)(datalen + BCM_TLV_HDR_SIZE) <= dst_maxlen) {
+
+			new_dst = bcm_write_tlv(type, data, datalen, dst);
+		}
+	}
+
+	return (new_dst);
+}
+
+uint8 *
+bcm_copy_tlv(const void *src, uint8 *dst)
+{
+	uint8 *new_dst = dst;
+	const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
+	uint totlen;
+
+	ASSERT(dst && src);
+	if (dst && src) {
+
+		totlen = BCM_TLV_HDR_SIZE + src_tlv->len;
+		memcpy(dst, src_tlv, totlen);
+		new_dst = dst + totlen;
+	}
+
+	return (new_dst);
+}
+
+
+uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen)
+{
+	uint8 *new_dst = dst;
+	const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src;
+
+	ASSERT(src);
+	if (src) {
+		if (bcm_valid_tlv(src_tlv, dst_maxlen)) {
+			new_dst = bcm_copy_tlv(src, dst);
+		}
+	}
+
+	return (new_dst);
+}
+
+
+#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
+/*******************************************************************************
+ * crc8
+ *
+ * Computes a crc8 over the input data using the polynomial:
+ *
+ *       x^8 + x^7 +x^6 + x^4 + x^2 + 1
+ *
+ * The caller provides the initial value (either CRC8_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data.  When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream.  When checking, a final
+ * return value of CRC8_GOOD_VALUE indicates a valid CRC.
+ *
+ * Reference: Dallas Semiconductor Application Note 27
+ *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
+ *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
+ *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
+ *
+ * ****************************************************************************
+ */
+
+static const uint8 crc8_table[256] = {
+    0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
+    0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
+    0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
+    0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
+    0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
+    0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
+    0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
+    0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
+    0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
+    0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
+    0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
+    0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
+    0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
+    0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
+    0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
+    0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
+    0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
+    0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
+    0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
+    0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
+    0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
+    0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
+    0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
+    0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
+    0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
+    0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
+    0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
+    0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
+    0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
+    0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
+    0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
+    0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
+};
+
+#define CRC_INNER_LOOP(n, c, x) \
+	(c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff]
+
+uint8
+hndcrc8(
+	uint8 *pdata,	/* pointer to array of data to process */
+	uint  nbytes,	/* number of input data bytes to process */
+	uint8 crc	/* either CRC8_INIT_VALUE or previous return value */
+)
+{
+	/* hard code the crc loop instead of using CRC_INNER_LOOP macro
+	 * to avoid the undefined and unnecessary (uint8 >> 8) operation.
+	 */
+	while (nbytes-- > 0)
+		crc = crc8_table[(crc ^ *pdata++) & 0xff];
+
+	return crc;
+}
+
+/*******************************************************************************
+ * crc16
+ *
+ * Computes a crc16 over the input data using the polynomial:
+ *
+ *       x^16 + x^12 +x^5 + 1
+ *
+ * The caller provides the initial value (either CRC16_INIT_VALUE
+ * or the previous returned value) to allow for processing of
+ * discontiguous blocks of data.  When generating the CRC the
+ * caller is responsible for complementing the final return value
+ * and inserting it into the byte stream.  When checking, a final
+ * return value of CRC16_GOOD_VALUE indicates a valid CRC.
+ *
+ * Reference: Dallas Semiconductor Application Note 27
+ *   Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
+ *     ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
+ *     ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
+ *
+ * ****************************************************************************
+ */
+
+static const uint16 crc16_table[256] = {
+    0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
+    0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
+    0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
+    0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
+    0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
+    0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
+    0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
+    0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
+    0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
+    0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
+    0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
+    0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
+    0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
+    0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
+    0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
+    0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
+    0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
+    0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
+    0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
+    0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
+    0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
+    0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
+    0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
+    0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
+    0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
+    0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
+    0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
+    0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
+    0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
+    0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
+    0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
+    0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
+};
+
+uint16
+hndcrc16(
+    uint8 *pdata,  /* pointer to array of data to process */
+    uint nbytes, /* number of input data bytes to process */
+    uint16 crc     /* either CRC16_INIT_VALUE or previous return value */
+)
+{
+	while (nbytes-- > 0)
+		CRC_INNER_LOOP(16, crc, *pdata++);
+	return crc;
+}
+
+static const uint32 crc32_table[256] = {
+    0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+    0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+    0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+    0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+    0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+    0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+    0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+    0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+    0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+    0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+    0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+    0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+    0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+    0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+    0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+    0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+    0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+    0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+    0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+    0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+    0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+    0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+    0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+    0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+    0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+    0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+    0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+    0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+    0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+    0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+    0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+    0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+    0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+    0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+    0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+    0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+    0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+    0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+    0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+    0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+    0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+    0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+    0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+    0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+    0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+    0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+    0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+    0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+    0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+    0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+    0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+    0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+    0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+    0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+    0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+    0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+    0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+    0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+    0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+    0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+    0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+    0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+    0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+    0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
+
+/*
+ * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if
+ * accumulating over multiple pieces.
+ */
+uint32
+hndcrc32(uint8 *pdata, uint nbytes, uint32 crc)
+{
+	uint8 *pend;
+#ifdef __mips__
+	uint8 tmp[4];
+	ulong *tptr = (ulong *)tmp;
+
+	if (nbytes > 3) {
+		/* in case the beginning of the buffer isn't aligned */
+		pend = (uint8 *)((uint)(pdata + 3) & ~0x3);
+		nbytes -= (pend - pdata);
+		while (pdata < pend)
+			CRC_INNER_LOOP(32, crc, *pdata++);
+	}
+
+	if (nbytes > 3) {
+		/* handle bulk of data as 32-bit words */
+		pend = pdata + (nbytes & ~0x3);
+		while (pdata < pend) {
+			*tptr = *(ulong *)pdata;
+			pdata += sizeof(ulong *);
+			CRC_INNER_LOOP(32, crc, tmp[0]);
+			CRC_INNER_LOOP(32, crc, tmp[1]);
+			CRC_INNER_LOOP(32, crc, tmp[2]);
+			CRC_INNER_LOOP(32, crc, tmp[3]);
+		}
+	}
+
+	/* 1-3 bytes at end of buffer */
+	pend = pdata + (nbytes & 0x03);
+	while (pdata < pend)
+		CRC_INNER_LOOP(32, crc, *pdata++);
+#else
+	pend = pdata + nbytes;
+	while (pdata < pend)
+		CRC_INNER_LOOP(32, crc, *pdata++);
+#endif /* __mips__ */
+
+	return crc;
+}
+
+#ifdef notdef
+#define CLEN 	1499 	/*  CRC Length */
+#define CBUFSIZ 	(CLEN+4)
+#define CNBUFS		5 /* # of bufs */
+
+void
+testcrc32(void)
+{
+	uint j, k, l;
+	uint8 *buf;
+	uint len[CNBUFS];
+	uint32 crcr;
+	uint32 crc32tv[CNBUFS] =
+		{0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110};
+
+	ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL);
+
+	/* step through all possible alignments */
+	for (l = 0; l <= 4; l++) {
+		for (j = 0; j < CNBUFS; j++) {
+			len[j] = CLEN;
+			for (k = 0; k < len[j]; k++)
+				*(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff;
+		}
+
+		for (j = 0; j < CNBUFS; j++) {
+			crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE);
+			ASSERT(crcr == crc32tv[j]);
+		}
+	}
+
+	MFREE(buf, CBUFSIZ*CNBUFS);
+	return;
+}
+#endif /* notdef */
+
+/*
+ * Advance from the current 1-byte tag/1-byte length/variable-length value
+ * triple, to the next, returning a pointer to the next.
+ * If the current or next TLV is invalid (does not fit in given buffer length),
+ * NULL is returned.
+ * *buflen is not modified if the TLV elt parameter is invalid, or is decremented
+ * by the TLV parameter's length if it is valid.
+ */
+bcm_tlv_t *
+bcm_next_tlv(bcm_tlv_t *elt, int *buflen)
+{
+	int len;
+
+	/* validate current elt */
+	if (!bcm_valid_tlv(elt, *buflen)) {
+		return NULL;
+	}
+
+	/* advance to next elt */
+	len = elt->len;
+	elt = (bcm_tlv_t*)(elt->data + len);
+	*buflen -= (TLV_HDR_LEN + len);
+
+	/* validate next elt */
+	if (!bcm_valid_tlv(elt, *buflen)) {
+		return NULL;
+	}
+
+	return elt;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+bcm_tlv_t *
+bcm_parse_tlvs(void *buf, int buflen, uint key)
+{
+	bcm_tlv_t *elt;
+	int totlen;
+
+	if ((elt = (bcm_tlv_t*)buf) == NULL) {
+		return NULL;
+	}
+	totlen = buflen;
+
+	/* find tagged parameter */
+	while (totlen >= TLV_HDR_LEN) {
+		int len = elt->len;
+
+		/* validate remaining totlen */
+		if ((elt->id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
+
+			return (elt);
+		}
+
+		elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
+		totlen -= (len + TLV_HDR_LEN);
+	}
+
+	return NULL;
+}
+
+bcm_tlv_t *
+bcm_parse_tlvs_dot11(void *buf, int buflen, uint key, bool id_ext)
+{
+	bcm_tlv_t *elt;
+	int totlen;
+
+	elt = (bcm_tlv_t*)buf;
+	totlen = buflen;
+
+	/* find tagged parameter */
+	while (totlen >= TLV_HDR_LEN) {
+		int len = elt->len;
+
+		do {
+			/* validate remaining totlen */
+			if (totlen <  (int)(len + TLV_HDR_LEN))
+				break;
+
+			if (id_ext) {
+				if (!DOT11_MNG_IE_ID_EXT_MATCH(elt, key))
+					break;
+			} else if (elt->id != key) {
+				break;
+			}
+
+			return (elt);
+		} while (0);
+
+		elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
+		totlen -= (len + TLV_HDR_LEN);
+	}
+
+	return NULL;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ * return NULL if not found or length field < min_varlen
+ */
+bcm_tlv_t *
+bcm_parse_tlvs_min_bodylen(void *buf, int buflen, uint key, int min_bodylen)
+{
+	bcm_tlv_t * ret;
+	ret = bcm_parse_tlvs(buf, buflen, key);
+	if (ret == NULL || ret->len < min_bodylen) {
+		return NULL;
+	}
+	return ret;
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag.  Stop parsing when we see an element whose ID is greater
+ * than the target key.
+ */
+bcm_tlv_t *
+bcm_parse_ordered_tlvs(void *buf, int buflen, uint key)
+{
+	bcm_tlv_t *elt;
+	int totlen;
+
+	elt = (bcm_tlv_t*)buf;
+	totlen = buflen;
+
+	/* find tagged parameter */
+	while (totlen >= TLV_HDR_LEN) {
+		uint id = elt->id;
+		int len = elt->len;
+
+		/* Punt if we start seeing IDs > than target key */
+		if (id > key) {
+			return (NULL);
+		}
+
+		/* validate remaining totlen */
+		if ((id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
+			return (elt);
+		}
+
+		elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
+		totlen -= (len + TLV_HDR_LEN);
+	}
+	return NULL;
+}
+#endif	/* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
+
+#if defined(BCMDBG) || defined(BCMDBG_ERR) || defined(WLMSG_PRHDRS) || \
+	defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || defined(BCMDBG_DUMP) || \
+	defined(DHD_DEBUG)
+int
+bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len)
+{
+	int i, slen = 0;
+	uint32 bit, mask;
+	const char *name;
+	mask = bd->mask;
+	if (len < 2 || !buf)
+		return 0;
+
+	buf[0] = '\0';
+
+	for (i = 0;  (name = bd->bitfield[i].name) != NULL; i++) {
+		bit = bd->bitfield[i].bit;
+		if ((flags & mask) == bit) {
+			if (len > (int)strlen(name)) {
+				slen = strlen(name);
+				strncpy(buf, name, slen+1);
+			}
+			break;
+		}
+	}
+	return slen;
+}
+
+int
+bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len)
+{
+	int i;
+	char* p = buf;
+	char hexstr[16];
+	int slen = 0, nlen = 0;
+	uint32 bit;
+	const char* name;
+
+	if (len < 2 || !buf)
+		return 0;
+
+	buf[0] = '\0';
+
+	for (i = 0; flags != 0; i++) {
+		bit = bd[i].bit;
+		name = bd[i].name;
+		if (bit == 0 && flags != 0) {
+			/* print any unnamed bits */
+			snprintf(hexstr, 16, "0x%X", flags);
+			name = hexstr;
+			flags = 0;	/* exit loop */
+		} else if ((flags & bit) == 0)
+			continue;
+		flags &= ~bit;
+		nlen = strlen(name);
+		slen += nlen;
+		/* count btwn flag space */
+		if (flags != 0)
+			slen += 1;
+		/* need NULL char as well */
+		if (len <= slen)
+			break;
+		/* copy NULL char but don't count it */
+		strncpy(p, name, nlen + 1);
+		p += nlen;
+		/* copy btwn flag space and NULL char */
+		if (flags != 0)
+			p += snprintf(p, 2, " ");
+	}
+
+	/* indicate the str was too short */
+	if (flags != 0) {
+		p += snprintf(p, 2, ">");
+	}
+
+	return (int)(p - buf);
+}
+#endif /* BCMDBG || WLMSG_PRHDRS || WLMSG_PRPKT || WLMSG_ASSOC || BCMDBG_DUMP || DHD_DEBUG */
+
+/* print bytes formatted as hex to a string. return the resulting string length */
+int
+bcm_format_hex(char *str, const void *bytes, int len)
+{
+	int i;
+	char *p = str;
+	const uint8 *src = (const uint8*)bytes;
+
+	for (i = 0; i < len; i++) {
+		p += snprintf(p, 3, "%02X", *src);
+		src++;
+	}
+	return (int)(p - str);
+}
+
+/* pretty hex print a contiguous buffer */
+void
+prhex(const char *msg, const uchar *buf, uint nbytes)
+{
+	char line[128], *p;
+	int len = sizeof(line);
+	int nchar;
+	uint i;
+
+	if (msg && (msg[0] != '\0'))
+		printf("%s:\n", msg);
+
+	p = line;
+	for (i = 0; i < nbytes; i++) {
+		if (i % 16 == 0) {
+			nchar = snprintf(p, len, "  %04x: ", i);	/* line prefix */
+			p += nchar;
+			len -= nchar;
+		}
+		if (len > 0) {
+			nchar = snprintf(p, len, "%02x ", buf[i]);
+			p += nchar;
+			len -= nchar;
+		}
+
+		if (i % 16 == 15) {
+			printf("%s\n", line);		/* flush line */
+			p = line;
+			len = sizeof(line);
+		}
+	}
+
+	/* flush last partial line */
+	if (p != line)
+		printf("%s\n", line);
+}
+
+static const char *crypto_algo_names[] = {
+	"NONE",
+	"WEP1",
+	"TKIP",
+	"WEP128",
+	"AES_CCM",
+	"AES_OCB_MSDU",
+	"AES_OCB_MPDU",
+	"NALG",
+	"UNDEF",
+	"UNDEF",
+	"UNDEF",
+#ifdef BCMWAPI_WAI
+	"WAPI",
+#else
+	"UNDEF"
+#endif
+	"PMK",
+	"BIP",
+	"AES_GCM",
+	"AES_CCM256",
+	"AES_GCM256",
+	"BIP_CMAC256",
+	"BIP_GMAC",
+	"BIP_GMAC256",
+	"UNDEF"
+};
+
+const char *
+bcm_crypto_algo_name(uint algo)
+{
+	return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR";
+}
+
+#ifdef BCMDBG
+void
+deadbeef(void *p, uint len)
+{
+	static uint8 meat[] = { 0xde, 0xad, 0xbe, 0xef };
+
+	while (len-- > 0) {
+		*(uint8*)p = meat[((uintptr)p) & 3];
+		p = (uint8*)p + 1;
+	}
+}
+#endif /* BCMDBG */
+
+char *
+bcm_chipname(uint chipid, char *buf, uint len)
+{
+	const char *fmt;
+
+	fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
+	snprintf(buf, len, fmt, chipid);
+	return buf;
+}
+
+/* Produce a human-readable string for boardrev */
+char *
+bcm_brev_str(uint32 brev, char *buf)
+{
+	if (brev < 0x100)
+		snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf);
+	else
+		snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff);
+
+	return (buf);
+}
+
+#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */
+
+/* dump large strings to console */
+void
+printbig(char *buf)
+{
+	uint len, max_len;
+	char c;
+
+	len = (uint)strlen(buf);
+
+	max_len = BUFSIZE_TODUMP_ATONCE;
+
+	while (len > max_len) {
+		c = buf[max_len];
+		buf[max_len] = '\0';
+		printf("%s", buf);
+		buf[max_len] = c;
+
+		buf += max_len;
+		len -= max_len;
+	}
+	/* print the remaining string */
+	printf("%s\n", buf);
+	return;
+}
+
+/* routine to dump fields in a fileddesc structure */
+uint
+bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array,
+	char *buf, uint32 bufsize)
+{
+	uint  filled_len;
+	int len;
+	struct fielddesc *cur_ptr;
+
+	filled_len = 0;
+	cur_ptr = fielddesc_array;
+
+	while (bufsize > 1) {
+		if (cur_ptr->nameandfmt == NULL)
+			break;
+		len = snprintf(buf, bufsize, cur_ptr->nameandfmt,
+		               read_rtn(arg0, arg1, cur_ptr->offset));
+		/* check for snprintf overflow or error */
+		if (len < 0 || (uint32)len >= bufsize)
+			len = bufsize - 1;
+		buf += len;
+		bufsize -= len;
+		filled_len += len;
+		cur_ptr++;
+	}
+	return filled_len;
+}
+
+uint
+bcm_mkiovar(const char *name, const char *data, uint datalen, char *buf, uint buflen)
+{
+	uint len;
+
+	len = (uint)strlen(name) + 1;
+
+	if ((len + datalen) > buflen)
+		return 0;
+
+	strncpy(buf, name, buflen);
+
+	/* append data onto the end of the name string */
+	if (data) {
+		memcpy(&buf[len], data, datalen);
+		len += datalen;
+	}
+
+	return len;
+}
+
+/* Quarter dBm units to mW
+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
+ * Table is offset so the last entry is largest mW value that fits in
+ * a uint16.
+ */
+
+#define QDBM_OFFSET 153		/* Offset for first entry */
+#define QDBM_TABLE_LEN 40	/* Table size */
+
+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
+ */
+#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
+
+/* Largest mW value that will round down to the last table entry,
+ * QDBM_OFFSET + QDBM_TABLE_LEN-1.
+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
+ */
+#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
+
+static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
+/* qdBm: 	+0 	+1 	+2 	+3 	+4 	+5 	+6 	+7 */
+/* 153: */      6683,	7079,	7499,	7943,	8414,	8913,	9441,	10000,
+/* 161: */      10593,	11220,	11885,	12589,	13335,	14125,	14962,	15849,
+/* 169: */      16788,	17783,	18836,	19953,	21135,	22387,	23714,	25119,
+/* 177: */      26607,	28184,	29854,	31623,	33497,	35481,	37584,	39811,
+/* 185: */      42170,	44668,	47315,	50119,	53088,	56234,	59566,	63096
+};
+
+uint16
+bcm_qdbm_to_mw(uint8 qdbm)
+{
+	uint factor = 1;
+	int idx = qdbm - QDBM_OFFSET;
+
+	if (idx >= QDBM_TABLE_LEN) {
+		/* clamp to max uint16 mW value */
+		return 0xFFFF;
+	}
+
+	/* scale the qdBm index up to the range of the table 0-40
+	 * where an offset of 40 qdBm equals a factor of 10 mW.
+	 */
+	while (idx < 0) {
+		idx += 40;
+		factor *= 10;
+	}
+
+	/* return the mW value scaled down to the correct factor of 10,
+	 * adding in factor/2 to get proper rounding.
+	 */
+	return ((nqdBm_to_mW_map[idx] + factor/2) / factor);
+}
+
+uint8
+bcm_mw_to_qdbm(uint16 mw)
+{
+	uint8 qdbm;
+	int offset;
+	uint mw_uint = mw;
+	uint boundary;
+
+	/* handle boundary case */
+	if (mw_uint <= 1)
+		return 0;
+
+	offset = QDBM_OFFSET;
+
+	/* move mw into the range of the table */
+	while (mw_uint < QDBM_TABLE_LOW_BOUND) {
+		mw_uint *= 10;
+		offset -= 40;
+	}
+
+	for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) {
+		boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] -
+		                                    nqdBm_to_mW_map[qdbm])/2;
+		if (mw_uint < boundary) break;
+	}
+
+	qdbm += (uint8)offset;
+
+	return (qdbm);
+}
+
+
+uint
+bcm_bitcount(uint8 *bitmap, uint length)
+{
+	uint bitcount = 0, i;
+	uint8 tmp;
+	for (i = 0; i < length; i++) {
+		tmp = bitmap[i];
+		while (tmp) {
+			bitcount++;
+			tmp &= (tmp - 1);
+		}
+	}
+	return bitcount;
+}
+
+/*
+ * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL.
+ * also accepts nvram files which are already in the format of <var1>=<value>\0\<var2>=<value2>\0
+ * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs.
+ * Shortens buffer as needed and pads with NULs.  End of buffer is marked by two NULs.
+*/
+
+unsigned int
+process_nvram_vars(char *varbuf, unsigned int len)
+{
+	char *dp;
+	bool findNewline;
+	int column;
+	unsigned int buf_len, n;
+	unsigned int pad = 0;
+
+	dp = varbuf;
+
+	findNewline = FALSE;
+	column = 0;
+
+	for (n = 0; n < len; n++) {
+		if (varbuf[n] == '\r')
+			continue;
+		if (findNewline && varbuf[n] != '\n')
+			continue;
+		findNewline = FALSE;
+		if (varbuf[n] == '#') {
+			findNewline = TRUE;
+			continue;
+		}
+		if (varbuf[n] == '\n') {
+			if (column == 0)
+				continue;
+			*dp++ = 0;
+			column = 0;
+			continue;
+		}
+		*dp++ = varbuf[n];
+		column++;
+	}
+	buf_len = (unsigned int)(dp - varbuf);
+	if (buf_len % 4) {
+		pad = 4 - buf_len % 4;
+		if (pad && (buf_len + pad <= len)) {
+			buf_len += pad;
+		}
+	}
+
+	while (dp < varbuf + n)
+		*dp++ = 0;
+
+	return buf_len;
+}
+
+/* calculate a * b + c */
+void
+bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c)
+{
+#define FORMALIZE(var) {cc += (var & 0x80000000) ? 1 : 0; var &= 0x7fffffff;}
+	uint32 r1, r0;
+	uint32 a1, a0, b1, b0, t, cc = 0;
+
+	a1 = a >> 16;
+	a0 = a & 0xffff;
+	b1 = b >> 16;
+	b0 = b & 0xffff;
+
+	r0 = a0 * b0;
+	FORMALIZE(r0);
+
+	t = (a1 * b0) << 16;
+	FORMALIZE(t);
+
+	r0 += t;
+	FORMALIZE(r0);
+
+	t = (a0 * b1) << 16;
+	FORMALIZE(t);
+
+	r0 += t;
+	FORMALIZE(r0);
+
+	FORMALIZE(c);
+
+	r0 += c;
+	FORMALIZE(r0);
+
+	r0 |= (cc % 2) ? 0x80000000 : 0;
+	r1 = a1 * b1 + ((a1 * b0) >> 16) + ((b1 * a0) >> 16) + (cc / 2);
+
+	*r_high = r1;
+	*r_low = r0;
+}
+
+/* calculate a / b */
+void
+bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
+{
+	uint32 a1 = a_high, a0 = a_low, r0 = 0;
+
+	if (b < 2)
+		return;
+
+	while (a1 != 0) {
+		r0 += (0xffffffff / b) * a1;
+		bcm_uint64_multiple_add(&a1, &a0, ((0xffffffff % b) + 1) % b, a1, a0);
+	}
+
+	r0 += a0 / b;
+	*r = r0;
+}
+
+/* calculate uint64 a / b
+ * keeping bcm_uint64_divide (returns uint32 value) since many module
+ * uses it. Added new func bcm_unit64_div to take care of uint64 quotient
+ */
+uint64
+bcm_uint64_div(uint32 a_high, uint32 a_low, uint32 b)
+{
+	uint32 a1 = a_high, a0 = a_low;
+	uint64 r0 = 0;
+
+	if (!b) {
+		ASSERT(0);
+		return 0;
+	}
+
+	if (b == 1) {
+		return (((uint64)a1 << 32) | a0);
+	}
+	while (a1 != 0) {
+		r0 += (uint64)(0xffffffff / b) * a1;
+		bcm_uint64_multiple_add(&a1, &a0, ((0xffffffff % b) + 1) % b, a1, a0);
+	}
+
+	r0 += a0 / b;
+	return r0;
+}
+
+#ifndef setbit /* As in the header file */
+#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS
+/* Set bit in byte array. */
+void
+setbit(void *array, uint bit)
+{
+	((uint8 *)array)[bit / NBBY] |= 1 << (bit % NBBY);
+}
+
+/* Clear bit in byte array. */
+void
+clrbit(void *array, uint bit)
+{
+	((uint8 *)array)[bit / NBBY] &= ~(1 << (bit % NBBY));
+}
+
+/* Test if bit is set in byte array. */
+bool
+isset(const void *array, uint bit)
+{
+	return (((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY)));
+}
+
+/* Test if bit is clear in byte array. */
+bool
+isclr(const void *array, uint bit)
+{
+	return ((((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))) == 0);
+}
+#endif /* BCMUTILS_BIT_MACROS_USE_FUNCS */
+#endif /* setbit */
+
+void
+set_bitrange(void *array, uint start, uint end, uint maxbit)
+{
+	uint startbyte = start/NBBY;
+	uint endbyte = end/NBBY;
+	uint i, startbytelastbit, endbytestartbit;
+
+	if (end >= start) {
+		if (endbyte - startbyte > 1)
+		{
+			startbytelastbit = (startbyte+1)*NBBY - 1;
+			endbytestartbit = endbyte*NBBY;
+			for (i = startbyte+1; i < endbyte; i++)
+				((uint8 *)array)[i] = 0xFF;
+			for (i = start; i <= startbytelastbit; i++)
+				setbit(array, i);
+			for (i = endbytestartbit; i <= end; i++)
+				setbit(array, i);
+		} else {
+			for (i = start; i <= end; i++)
+				setbit(array, i);
+		}
+	}
+	else {
+		set_bitrange(array, start, maxbit, maxbit);
+		set_bitrange(array, 0, end, maxbit);
+	}
+}
+
+void
+bcm_bitprint32(const uint32 u32arg)
+{
+	int i;
+	for (i = NBITS(uint32) - 1; i >= 0; i--) {
+		if (isbitset(u32arg, i)) {
+			printf("1");
+		} else {
+			printf("0");
+		}
+
+		if ((i % NBBY) == 0) printf(" ");
+	}
+	printf("\n");
+}
+
+/* calculate checksum for ip header, tcp / udp header / data */
+uint16
+bcm_ip_cksum(uint8 *buf, uint32 len, uint32 sum)
+{
+	while (len > 1) {
+		sum += (buf[0] << 8) | buf[1];
+		buf += 2;
+		len -= 2;
+	}
+
+	if (len > 0) {
+		sum += (*buf) << 8;
+	}
+
+	while (sum >> 16) {
+		sum = (sum & 0xffff) + (sum >> 16);
+	}
+
+	return ((uint16)~sum);
+}
+
+/* calculate a >> b; and returns only lower 32 bits */
+void
+bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
+{
+	uint32 a1 = a_high, a0 = a_low, r0 = 0;
+
+	if (b == 0) {
+		r0 = a_low;
+		*r = r0;
+		return;
+	}
+
+	if (b < 32) {
+		a0 = a0 >> b;
+		a1 = a1 & ((1 << b) - 1);
+		a1 = a1 << (32 - b);
+		r0 = a0 | a1;
+		*r = r0;
+		return;
+	} else {
+		r0 = a1 >> (b - 32);
+		*r = r0;
+		return;
+	}
+
+}
+
+/* calculate a + b where a is a 64 bit number and b is a 32 bit number */
+void
+bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset)
+{
+	uint32 r1_lo = *r_lo;
+	(*r_lo) += offset;
+	if (*r_lo < r1_lo)
+		(*r_hi) ++;
+}
+
+/* calculate a - b where a is a 64 bit number and b is a 32 bit number */
+void
+bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset)
+{
+	uint32 r1_lo = *r_lo;
+	(*r_lo) -= offset;
+	if (*r_lo > r1_lo)
+		(*r_hi) --;
+}
+
+int
+BCMRAMFN(valid_bcmerror)(int e)
+{
+	return ((e <= 0) && (e >= BCME_LAST));
+}
+
+/* Does unsigned 64 bit fixed point multiplication */
+uint64
+fp_mult_64(uint64 val1, uint64 val2, uint8 nf1, uint8 nf2, uint8 nf_res)
+{
+	uint64 mult_out_tmp, mult_out, rnd_val;
+	uint8 shift_amt;
+
+	shift_amt = nf1 + nf2 - nf_res;
+	/* 0.5 in 1.0.shift_amt */
+	rnd_val = bcm_shl_64(1, (shift_amt - 1));
+	rnd_val = (shift_amt == 0) ? 0 : rnd_val;
+	mult_out_tmp = (uint64)((uint64)val1 * (uint64)val2) + (uint64)rnd_val;
+	mult_out = bcm_shr_64(mult_out_tmp, shift_amt);
+
+	return mult_out;
+}
+
+
+/* Does unsigned 64 bit by 32 bit fixed point division */
+uint8
+fp_div_64(uint64 num, uint32 den, uint8 nf_num, uint8 nf_den, uint32 *div_out)
+{
+	uint8 shift_amt1, shift_amt2, shift_amt, nf_res, hd_rm_nr, hd_rm_dr;
+	uint32 num_hi, num_lo;
+	uint64 num_scale;
+
+	/* Worst case shift possible */
+	hd_rm_nr = fp_calc_head_room_64(num);
+	hd_rm_dr = fp_calc_head_room_32(den);
+
+	/* (Nr / Dr) <= 2^32 */
+	shift_amt1 = hd_rm_nr - hd_rm_dr - 1;
+	/* Shift <= 32 + N2 - N1 */
+	shift_amt2 = 31 + nf_den - nf_num;
+	shift_amt = MINIMUM(shift_amt1, shift_amt2);
+
+	/* Scale numerator */
+	num_scale = bcm_shl_64(num, shift_amt);
+
+	/* Do division */
+	num_hi = (uint32)((uint64)num_scale >> 32) & MASK_32_BITS;
+	num_lo = (uint32)(num_scale & MASK_32_BITS);
+	bcm_uint64_divide(div_out, num_hi, num_lo, den);
+
+	/* Result format */
+	nf_res = nf_num - nf_den + shift_amt;
+	return nf_res;
+}
+
+/* Look-up table to calculate head room present in a number */
+static const uint8 msb_table[] = {
+	0, 1, 2, 2, 3, 3, 3, 3,
+	4, 4, 4, 4, 4, 4, 4, 4,
+	5, 5, 5, 5, 5, 5, 5, 5,
+	5, 5, 5, 5, 5, 5, 5, 5,
+	6, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 6, 6, 6, 6,
+	7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8,
+};
+
+/* Finds the number of bits available for shifting in unsigned 64 bit number */
+uint8
+fp_calc_head_room_64(uint64 num)
+{
+	uint8 n_room_bits = 0, msb_pos;
+	uint32 num_hi, num_lo, x;
+
+	num_hi = (uint32)((uint64)num >> 32) & MASK_32_BITS;
+	num_lo = (uint32)(num & MASK_32_BITS);
+
+	if (num_hi > 0) {
+		x = num_hi;
+		n_room_bits = 0;
+	} else {
+		x = num_lo;
+		n_room_bits = 32;
+	}
+
+	msb_pos = (x >> 16) ? ((x >> 24) ? (24 + msb_table[(x >> 24) & MASK_8_BITS])
+			: (16 + msb_table[(x >> 16) & MASK_8_BITS]))
+			: ((x >> 8) ? (8 + msb_table[(x >> 8) & MASK_8_BITS])
+			: msb_table[x & MASK_8_BITS]);
+
+	return (n_room_bits + 32 - msb_pos);
+}
+
+/* Finds the number of bits available for shifting in unsigned 32 bit number */
+uint8
+fp_calc_head_room_32(uint32 x)
+{
+	uint8 msb_pos;
+
+	msb_pos = (x >> 16) ? ((x >> 24) ? (24 + msb_table[(x >> 24) & MASK_8_BITS])
+			: (16 + msb_table[(x >> 16) & MASK_8_BITS]))
+			: ((x >> 8) ? (8 + msb_table[(x >> 8) & MASK_8_BITS])
+			: msb_table[x & MASK_8_BITS]);
+
+	return (32 - msb_pos);
+}
+
+/* Does unsigned 64 bit fixed point floor */
+uint32
+fp_floor_64(uint64 num, uint8 floor_pos)
+{
+	uint32 floor_out;
+
+	floor_out = (uint32)bcm_shr_64(num, floor_pos);
+
+	return floor_out;
+}
+
+/* Does unsigned 32 bit fixed point floor */
+uint32
+fp_floor_32(uint32 num, uint8 floor_pos)
+{
+	return num >> floor_pos;
+}
+
+/* Does unsigned 64 bit fixed point rounding */
+uint32
+fp_round_64(uint64 num, uint8 rnd_pos)
+{
+	uint64 rnd_val, rnd_out_tmp;
+	uint32 rnd_out;
+
+	/* 0.5 in 1.0.rnd_pos */
+	rnd_val = bcm_shl_64(1, (rnd_pos - 1));
+	rnd_val = (rnd_pos == 0) ? 0 : rnd_val;
+	rnd_out_tmp = num + rnd_val;
+	rnd_out = (uint32)bcm_shr_64(rnd_out_tmp, rnd_pos);
+
+	return rnd_out;
+}
+
+/* Does unsigned 32 bit fixed point rounding */
+uint32
+fp_round_32(uint32 num, uint8 rnd_pos)
+{
+	uint32 rnd_val, rnd_out_tmp;
+
+	/* 0.5 in 1.0.rnd_pos */
+	rnd_val = 1 << (rnd_pos - 1);
+	rnd_val = (rnd_pos == 0) ? 0 : rnd_val;
+	rnd_out_tmp = num + rnd_val;
+	return (rnd_out_tmp >> rnd_pos);
+}
+
+/* Does unsigned fixed point ceiling */
+uint32
+fp_ceil_64(uint64 num, uint8 ceil_pos)
+{
+	uint64 ceil_val, ceil_out_tmp;
+	uint32 ceil_out;
+
+	/* 0.999 in 1.0.rnd_pos */
+	ceil_val = bcm_shl_64(1, ceil_pos) - 1;
+	ceil_out_tmp = num + ceil_val;
+	ceil_out = (uint32)bcm_shr_64(ceil_out_tmp, ceil_pos);
+
+	return ceil_out;
+}
+
+/* Does left shift of unsigned 64 bit number */
+uint64
+bcm_shl_64(uint64 input, uint8 shift_amt)
+{
+	uint32 in_hi, in_lo;
+	uint32 masked_lo = 0;
+	uint32 mask;
+	uint64 shl_out;
+
+	if (shift_amt == 0) {
+		return input;
+	}
+
+	/* Get hi and lo part */
+	in_hi = (uint32)((uint64)input >> 32) & MASK_32_BITS;
+	in_lo = (uint32)(input & MASK_32_BITS);
+
+	if (shift_amt < 32) {
+		/* Extract bit which belongs to hi part after shifting */
+		mask = ((uint32)~0) << (32 - shift_amt);
+		masked_lo = (in_lo & mask) >> (32 - shift_amt);
+
+		/* Shift hi and lo and prepare output */
+		in_hi = (in_hi << shift_amt) | masked_lo;
+		in_lo = in_lo << shift_amt;
+	} else {
+		/* Extract bit which belongs to hi part after shifting */
+		shift_amt = shift_amt - 32;
+
+		/* Shift hi and lo and prepare output */
+		in_hi = in_lo << shift_amt;
+		in_lo = 0;
+	}
+
+	shl_out = (((uint64)in_hi << 32) | in_lo);
+	return shl_out;
+}
+
+/* Does right shift of unsigned 64 bit number */
+uint64
+bcm_shr_64(uint64 input, uint8 shift_amt)
+{
+	uint32 in_hi, in_lo;
+	uint32 masked_hi = 0;
+	uint32 mask;
+	uint64 shr_out;
+
+	if (shift_amt == 0) {
+		return input;
+	}
+
+	/* Get hi and lo part */
+	in_hi = (uint32)((uint64)input >> 32) & MASK_32_BITS;
+	in_lo = (uint32)(input & MASK_32_BITS);
+
+	if (shift_amt < 32) {
+		/* Extract bit which belongs to lo part after shifting */
+		mask = (1 << shift_amt) - 1;
+		masked_hi = in_hi & mask;
+
+		/* Shift hi and lo and prepare output */
+		in_hi = (uint32)in_hi >> shift_amt;
+		in_lo = ((uint32)in_lo >> shift_amt) | (masked_hi << (32 - shift_amt));
+	} else {
+		shift_amt = shift_amt - 32;
+		in_lo = in_hi >> shift_amt;
+		in_hi = 0;
+	}
+
+	shr_out = (((uint64)in_hi << 32) | in_lo);
+	return shr_out;
+}
+
+#ifdef DEBUG_COUNTER
+#if (OSL_SYSUPTIME_SUPPORT == TRUE)
+void counter_printlog(counter_tbl_t *ctr_tbl)
+{
+	uint32 now;
+
+	if (!ctr_tbl->enabled)
+		return;
+
+	now = OSL_SYSUPTIME();
+
+	if (now - ctr_tbl->prev_log_print > ctr_tbl->log_print_interval) {
+		uint8 i = 0;
+		printf("counter_print(%s %d):", ctr_tbl->name, now - ctr_tbl->prev_log_print);
+
+		for (i = 0; i < ctr_tbl->needed_cnt; i++) {
+			printf(" %u", ctr_tbl->cnt[i]);
+		}
+		printf("\n");
+
+		ctr_tbl->prev_log_print = now;
+		bzero(ctr_tbl->cnt, CNTR_TBL_MAX * sizeof(uint));
+	}
+}
+#else
+/* OSL_SYSUPTIME is not supported so no way to get time */
+#define counter_printlog(a) do {} while (0)
+#endif /* OSL_SYSUPTIME_SUPPORT == TRUE */
+#endif /* DEBUG_COUNTER */
+
+/* calculate partial checksum */
+static uint32
+ip_cksum_partial(uint32 sum, uint8 *val8, uint32 count)
+{
+	uint32 i;
+	uint16 *val16 = (uint16 *)val8;
+
+	ASSERT(val8 != NULL);
+	/* partial chksum calculated on 16-bit values */
+	ASSERT((count % 2) == 0);
+
+	count /= 2;
+
+	for (i = 0; i < count; i++) {
+		sum += *val16++;
+	}
+	return sum;
+}
+
+/* calculate IP checksum */
+static uint16
+ip_cksum(uint32 sum, uint8 *val8, uint32 count)
+{
+	uint16 *val16 = (uint16 *)val8;
+
+	ASSERT(val8 != NULL);
+
+	while (count > 1) {
+		sum += *val16++;
+		count -= 2;
+	}
+	/*  add left-over byte, if any */
+	if (count > 0) {
+		sum += (*(uint8 *)val16);
+	}
+
+	/*  fold 32-bit sum to 16 bits */
+	sum = (sum >> 16) + (sum & 0xffff);
+	sum += (sum >> 16);
+	return ((uint16)~sum);
+}
+
+/* calculate IPv4 header checksum
+ * - input ip points to IP header in network order
+ * - output cksum is in network order
+ */
+uint16
+ipv4_hdr_cksum(uint8 *ip, int ip_len)
+{
+	uint32 sum = 0;
+	uint8 *ptr = ip;
+
+	ASSERT(ip != NULL);
+	ASSERT(ip_len >= IPV4_MIN_HEADER_LEN);
+
+	/* partial cksum skipping the hdr_chksum field */
+	sum = ip_cksum_partial(sum, ptr, OFFSETOF(struct ipv4_hdr, hdr_chksum));
+	ptr += OFFSETOF(struct ipv4_hdr, hdr_chksum) + 2;
+
+	/* return calculated chksum */
+	return ip_cksum(sum, ptr, ip_len - OFFSETOF(struct ipv4_hdr, src_ip));
+}
+
+/* calculate TCP header checksum using partial sum */
+static uint16
+tcp_hdr_chksum(uint32 sum, uint8 *tcp_hdr, uint16 tcp_len)
+{
+	uint8 *ptr = tcp_hdr;
+
+	ASSERT(tcp_hdr != NULL);
+	ASSERT(tcp_len >= TCP_MIN_HEADER_LEN);
+
+	/* partial TCP cksum skipping the chksum field */
+	sum = ip_cksum_partial(sum, ptr, OFFSETOF(struct bcmtcp_hdr, chksum));
+	ptr += OFFSETOF(struct bcmtcp_hdr, chksum) + 2;
+
+	/* return calculated chksum */
+	return ip_cksum(sum, ptr, tcp_len - OFFSETOF(struct bcmtcp_hdr, urg_ptr));
+}
+
+struct tcp_pseudo_hdr {
+	uint8   src_ip[IPV4_ADDR_LEN];  /* Source IP Address */
+	uint8   dst_ip[IPV4_ADDR_LEN];  /* Destination IP Address */
+	uint8	zero;
+	uint8	prot;
+	uint16	tcp_size;
+};
+
+/* calculate IPv4 TCP header checksum
+ * - input ip and tcp points to IP and TCP header in network order
+ * - output cksum is in network order
+ */
+uint16
+ipv4_tcp_hdr_cksum(uint8 *ip, uint8 *tcp, uint16 tcp_len)
+{
+	struct ipv4_hdr *ip_hdr = (struct ipv4_hdr *)ip;
+	struct tcp_pseudo_hdr tcp_ps;
+	uint32 sum = 0;
+
+	ASSERT(ip != NULL);
+	ASSERT(tcp != NULL);
+	ASSERT(tcp_len >= TCP_MIN_HEADER_LEN);
+
+	/* pseudo header cksum */
+	memset(&tcp_ps, 0, sizeof(tcp_ps));
+	memcpy(&tcp_ps.dst_ip, ip_hdr->dst_ip, IPV4_ADDR_LEN);
+	memcpy(&tcp_ps.src_ip, ip_hdr->src_ip, IPV4_ADDR_LEN);
+	tcp_ps.zero = 0;
+	tcp_ps.prot = ip_hdr->prot;
+	tcp_ps.tcp_size = hton16(tcp_len);
+	sum = ip_cksum_partial(sum, (uint8 *)&tcp_ps, sizeof(tcp_ps));
+
+	/* return calculated TCP header chksum */
+	return tcp_hdr_chksum(sum, tcp, tcp_len);
+}
+
+struct ipv6_pseudo_hdr {
+	uint8  saddr[IPV6_ADDR_LEN];
+	uint8  daddr[IPV6_ADDR_LEN];
+	uint16 payload_len;
+	uint8  zero;
+	uint8  next_hdr;
+};
+
+/* calculate IPv6 TCP header checksum
+ * - input ipv6 and tcp points to IPv6 and TCP header in network order
+ * - output cksum is in network order
+ */
+uint16
+ipv6_tcp_hdr_cksum(uint8 *ipv6, uint8 *tcp, uint16 tcp_len)
+{
+	struct ipv6_hdr *ipv6_hdr = (struct ipv6_hdr *)ipv6;
+	struct ipv6_pseudo_hdr ipv6_pseudo;
+	uint32 sum = 0;
+
+	ASSERT(ipv6 != NULL);
+	ASSERT(tcp != NULL);
+	ASSERT(tcp_len >= TCP_MIN_HEADER_LEN);
+
+	/* pseudo header cksum */
+	memset((char *)&ipv6_pseudo, 0, sizeof(ipv6_pseudo));
+	memcpy((char *)ipv6_pseudo.saddr, (char *)ipv6_hdr->saddr.addr,
+		sizeof(ipv6_pseudo.saddr));
+	memcpy((char *)ipv6_pseudo.daddr, (char *)ipv6_hdr->daddr.addr,
+		sizeof(ipv6_pseudo.daddr));
+	ipv6_pseudo.payload_len = ipv6_hdr->payload_len;
+	ipv6_pseudo.next_hdr = ipv6_hdr->nexthdr;
+	sum = ip_cksum_partial(sum, (uint8 *)&ipv6_pseudo, sizeof(ipv6_pseudo));
+
+	/* return calculated TCP header chksum */
+	return tcp_hdr_chksum(sum, tcp, tcp_len);
+}
+
+void *_bcmutils_dummy_fn = NULL;
+
+/* GROUP 1 --- start
+ * These function under GROUP 1 are general purpose functions to do complex number
+ * calculations and square root calculation.
+ */
+void mult_cint32_cfixed(const cint32* in1, const cint32* in2, const uint8 prec,
+	cint32* out, bool conj) {
+	int32 i1 = in1->i, q1 = in1->q;
+	int32 i2 = in2->i, q2 = in2->q * (conj ? -1 : 1);
+	out->i = (i1*i2 - q1*q2) / (1 << prec);
+	out->q = (i1*q2 + i2*q1) / (1 << prec);
+}
+
+void add_cint32(const cint32* in1, const cint32* in2, cint32* out)
+{
+	out->i = in1->i + in2->i;
+	out->q = in1->q + in2->q;
+}
+
+void power_cint32(const cint32* in1, uint32* pwr)
+{
+	int32 re = in1->i;
+	int32 im = in1->q;
+	*(pwr) = (re*re + im*im);
+}
+
+void power_cint32_arr(const cint32* in1, const uint16* idx_arr, uint16 len, uint32* pwr)
+{
+	uint32 tmp_pwr = 0;
+	uint16 i = 0, idx;
+	*pwr = 0;
+	for (i = 0; i < len; i++) {
+		idx = *(idx_arr + i);
+		power_cint32((in1 + idx), &tmp_pwr);
+		*(pwr) += tmp_pwr;
+	}
+}
+
+uint32 sqrt_int(uint32 value)
+{
+	uint32 root = 0, shift = 0;
+
+	/* Compute integer nearest to square root of input integer value */
+	for (shift = 0; shift < 32; shift += 2) {
+		if (((0x40000000 >> shift) + root) <= value) {
+			value -= ((0x40000000 >> shift) + root);
+			root = (root >> 1) | (0x40000000 >> shift);
+		}
+		else {
+			root = root >> 1;
+		}
+	}
+
+	/* round to the nearest integer */
+	if (root < value) ++root;
+
+	return root;
+}
+/* GROUP 1 --- end */
diff --git a/wl/src/shared/bcmwifi/include/bcmwifi_channels.h b/wl/src/shared/bcmwifi/include/bcmwifi_channels.h
new file mode 100644
index 0000000..17ff789
--- /dev/null
+++ b/wl/src/shared/bcmwifi/include/bcmwifi_channels.h
@@ -0,0 +1,836 @@
+/*
+ * 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) 2017, Broadcom. 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 655845 2016-08-24 01:05:41Z $
+ */
+
+#ifndef	_bcmwifi_channels_h_
+#define	_bcmwifi_channels_h_
+
+#if defined(__FreeBSD__)
+#include <stdbool.h>
+#endif
+
+/* A chanspec holds the channel number, band, bandwidth and control sideband */
+typedef uint16 chanspec_t;
+
+/* channel defines */
+#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	/* 2G band channels are 5 Mhz apart */
+#define CH_MAX_2G_CHANNEL		14	/* Max channel in 2G band */
+
+/* maximum # channels the s/w supports */
+#define MAXCHANNEL		224	/* max # supported channels. The max channel no is above,
+					 * this is that + 1 rounded up to a multiple of NBBY (8).
+					 * DO NOT MAKE it > 255: channels are uint8's all over
+					 */
+#define MAXCHANNEL_NUM	(MAXCHANNEL - 1)	/* max channel number */
+
+/* channel bitvec */
+typedef struct {
+	uint8   vec[MAXCHANNEL/8];   /* bitvec of channels */
+} chanvec_t;
+
+/* make sure channel num is within valid range */
+#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))
+
+/* All builds use the new 11ac ratespec/chanspec */
+#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 WL_CHANNEL_BAND(ch) (((ch) <= CH_MAX_2G_CHANNEL) ? \
+	WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)
+
+/* channel defines */
+#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)
+
+/* pass a 80MHz channel number (uint8) to get respective LL, UU, LU, UL */
+#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))
+
+/* simple MACROs to get different fields of chanspec */
+#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)
+
+#ifdef WL11N_20MHZONLY
+#ifdef WL11ULB
+#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)
+#else
+#define CHSPEC_IS2P5(chspec)	0
+#define CHSPEC_IS5(chspec)	0
+#define CHSPEC_IS10(chspec)	0
+#endif
+#define CHSPEC_IS20(chspec)	1
+#define CHSPEC_IS20_2G(chspec)	((((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) && \
+								CHSPEC_IS2G(chspec))
+#ifndef CHSPEC_IS40
+#define CHSPEC_IS40(chspec)	0
+#endif
+#ifndef CHSPEC_IS80
+#define CHSPEC_IS80(chspec)	0
+#endif
+#ifndef CHSPEC_IS160
+#define CHSPEC_IS160(chspec)	0
+#endif
+#ifndef CHSPEC_IS8080
+#define CHSPEC_IS8080(chspec)	0
+#endif
+#define BW_LE20(bw)		TRUE
+#define CHSPEC_ISLE20(chspec)	TRUE
+
+/* see FOREACH_20_SB in !WL11N_20MHZONLY section */
+#define FOREACH_20_SB(chspec, channel) \
+		for (channel = CHSPEC_CHANNEL(chspec); channel; channel = 0)
+
+/* see GET_ALL_SB in !WL11N_20MHZONLY section */
+#define GET_ALL_SB(chspec, psb) do { \
+	psb[0] = CHSPEC_CHANNEL(chspec); \
+} while (0)
+
+#else /* !WL11N_20MHZONLY */
+
+#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)
+#define CHSPEC_IS20_5G(chspec)	((((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) && \
+								CHSPEC_IS5G(chspec))
+#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
+
+/* pass a center channel and get channel offset from it by 10MHz */
+#define CH_OFF_10MHZ_MULTIPLES(channel, offset)  ((uint8) (((offset) < 0) ? \
+		(((channel) > (WL_CHANSPEC_CHAN_MASK & ((uint16)((-(offset)) * CH_10MHZ_APART)))) ?\
+			((channel) + (offset) * CH_10MHZ_APART) : 0) : \
+			(((channel) < (uint16)(MAXCHANNEL - (offset) * CH_10MHZ_APART)) ? \
+				((channel) + (offset) * CH_10MHZ_APART) : 0)))
+
+#if defined(WL11AC_80P80) || defined(WL11AC_160)
+/* pass a 160MHz center channel to get 20MHz subband channel numbers */
+#define LLL_20_SB_160(channel)  CH_OFF_10MHZ_MULTIPLES(channel, -7)
+#define LLU_20_SB_160(channel)  CH_OFF_10MHZ_MULTIPLES(channel, -5)
+#define LUL_20_SB_160(channel)  CH_OFF_10MHZ_MULTIPLES(channel, -3)
+#define LUU_20_SB_160(channel)  CH_OFF_10MHZ_MULTIPLES(channel, -1)
+#define ULL_20_SB_160(channel)  CH_OFF_10MHZ_MULTIPLES(channel,  1)
+#define ULU_20_SB_160(channel)  CH_OFF_10MHZ_MULTIPLES(channel,  3)
+#define UUL_20_SB_160(channel)  CH_OFF_10MHZ_MULTIPLES(channel,  5)
+#define UUU_20_SB_160(channel)  CH_OFF_10MHZ_MULTIPLES(channel,  7)
+
+/* given an 80p80 channel, return the lower 80MHz sideband */
+#define LOWER_80_SB(chspec)  (wf_chspec_primary80_channel(chspec) < \
+		wf_chspec_secondary80_channel(chspec) ? \
+		wf_chspec_primary80_channel(chspec) : wf_chspec_secondary80_channel(chspec))
+
+/* given an 80p80 channel, return the upper 80MHz sideband */
+#define UPPER_80_SB(chspec)  (wf_chspec_primary80_channel(chspec) > \
+		wf_chspec_secondary80_channel(chspec) ? \
+		wf_chspec_primary80_channel(chspec) : wf_chspec_secondary80_channel(chspec))
+
+/* pass an 80P80 chanspec (not channel) to get 20MHz subnand channel numbers */
+#define LLL_20_SB_8080(chspec)  CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec), -3)
+#define LLU_20_SB_8080(chspec)  CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec), -1)
+#define LUL_20_SB_8080(chspec)  CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec),  1)
+#define LUU_20_SB_8080(chspec)  CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec),  3)
+#define ULL_20_SB_8080(chspec)  CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec), -3)
+#define ULU_20_SB_8080(chspec)  CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec), -1)
+#define UUL_20_SB_8080(chspec)  CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec),  1)
+#define UUU_20_SB_8080(chspec)  CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec),  3)
+
+/* get lowest 20MHz sideband of a given chspec
+ * (works with 20, 40, 80, 160, 80p80)
+ */
+#define CH_FIRST_20_SB(chspec)  ((uint8) (\
+		CHSPEC_IS160(chspec) ? LLL_20_SB_160(CHSPEC_CHANNEL(chspec)) : (\
+		CHSPEC_IS8080(chspec) ? LLL_20_SB_8080(chspec) : (\
+			CHSPEC_IS80(chspec) ? LL_20_SB(CHSPEC_CHANNEL(chspec)) : (\
+				CHSPEC_IS40(chspec) ? LOWER_20_SB(CHSPEC_CHANNEL(chspec)) : \
+					CHSPEC_CHANNEL(chspec))))))
+
+/* get upper most 20MHz sideband of a given chspec
+ * (works with 20, 40, 80, 160, 80p80)
+ */
+#define CH_LAST_20_SB(chspec)  ((uint8) (\
+		CHSPEC_IS160(chspec) ? UUU_20_SB_160(CHSPEC_CHANNEL(chspec)) : (\
+		CHSPEC_IS8080(chspec) ? UUU_20_SB_8080(chspec) : (\
+			CHSPEC_IS80(chspec) ? UU_20_SB(CHSPEC_CHANNEL(chspec)) : (\
+				CHSPEC_IS40(chspec) ? UPPER_20_SB(CHSPEC_CHANNEL(chspec)) : \
+					CHSPEC_CHANNEL(chspec))))))
+
+/* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband
+ * (works with 80p80 only)
+ * resolves to 0 if called with upper most channel
+ */
+#define CH_NEXT_20_SB_IN_8080(chspec, channel)  ((uint8) (\
+		((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \
+			((channel) == LUU_20_SB_8080(chspec) ? ULL_20_SB_8080(chspec) : \
+				(channel) + CH_20MHZ_APART))))
+
+/* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband
+ * (works with 20, 40, 80, 160, 80p80)
+ * resolves to 0 if called with upper most channel
+ */
+#define CH_NEXT_20_SB(chspec, channel)  ((uint8) (\
+		(CHSPEC_IS8080(chspec) ? CH_NEXT_20_SB_IN_8080((chspec), (channel)) : \
+			((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \
+				((channel) + CH_20MHZ_APART)))))
+
+#else /* WL11AC_80P80, WL11AC_160 */
+
+#define LLL_20_SB_160(channel)  0
+#define LLU_20_SB_160(channel)  0
+#define LUL_20_SB_160(channel)  0
+#define LUU_20_SB_160(channel)  0
+#define ULL_20_SB_160(channel)  0
+#define ULU_20_SB_160(channel)  0
+#define UUL_20_SB_160(channel)  0
+#define UUU_20_SB_160(channel)  0
+
+#define LOWER_80_SB(chspec)	0
+
+#define UPPER_80_SB(chspec)	0
+
+#define LLL_20_SB_8080(chspec)	0
+#define LLU_20_SB_8080(chspec)	0
+#define LUL_20_SB_8080(chspec)	0
+#define LUU_20_SB_8080(chspec)	0
+#define ULL_20_SB_8080(chspec)	0
+#define ULU_20_SB_8080(chspec)	0
+#define UUL_20_SB_8080(chspec)	0
+#define UUU_20_SB_8080(chspec)	0
+
+/* get lowest 20MHz sideband of a given chspec
+ * (works with 20, 40, 80)
+ */
+#define CH_FIRST_20_SB(chspec)  ((uint8) (\
+			CHSPEC_IS80(chspec) ? LL_20_SB(CHSPEC_CHANNEL(chspec)) : (\
+				CHSPEC_IS40(chspec) ? LOWER_20_SB(CHSPEC_CHANNEL(chspec)) : \
+					CHSPEC_CHANNEL(chspec))))
+/* get upper most 20MHz sideband of a given chspec
+ * (works with 20, 40, 80, 160, 80p80)
+ */
+#define CH_LAST_20_SB(chspec)  ((uint8) (\
+			CHSPEC_IS80(chspec) ? UU_20_SB(CHSPEC_CHANNEL(chspec)) : (\
+				CHSPEC_IS40(chspec) ? UPPER_20_SB(CHSPEC_CHANNEL(chspec)) : \
+					CHSPEC_CHANNEL(chspec))))
+
+/* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband
+ * (works with 20, 40, 80, 160, 80p80)
+ * resolves to 0 if called with upper most channel
+ */
+#define CH_NEXT_20_SB(chspec, channel)  ((uint8) (\
+			((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \
+				((channel) + CH_20MHZ_APART))))
+
+#endif /* WL11AC_80P80, WL11AC_160 */
+
+/* Iterator for 20MHz side bands of a chanspec: (chanspec_t chspec, uint8 channel)
+ * 'chspec' chanspec_t of interest (used in loop, better to pass a resolved value than a macro)
+ * 'channel' must be a variable (not an expression).
+ */
+#define FOREACH_20_SB(chspec, channel) \
+		for (channel = CH_FIRST_20_SB(chspec); channel; \
+			channel = CH_NEXT_20_SB((chspec), channel))
+
+/* Uses iterator to populate array with all side bands involved (sorted lower to upper).
+ *     'chspec' chanspec_t of interest
+ *     'psb' pointer to uint8 array of enough size to hold all side bands for the given chspec
+ */
+#define GET_ALL_SB(chspec, psb) do { \
+		uint8 channel, idx = 0; \
+		chanspec_t chspec_local = chspec; \
+		FOREACH_20_SB(chspec_local, channel) \
+			(psb)[idx++] = channel; \
+} while (0)
+
+/* given a chanspec_t of any bw, returns if control SB is in lower 20, 40, 80 or not respectively */
+#define IS_CTL_IN_L20(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_U) /* CTL SB is in low 20 of any 40 */
+#define IS_CTL_IN_L40(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_UL)	/* in low 40 of any 80 */
+#define IS_CTL_IN_L80(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_ULL)	/* in low 80 of 80p80/160 */
+
+
+#ifdef WL11ULB
+#define BW_LT20(bw)		(((bw) == WL_CHANSPEC_BW_2P5) || \
+				((bw) == WL_CHANSPEC_BW_5) || \
+				((bw) == WL_CHANSPEC_BW_10))
+#define CHSPEC_BW_LT20(chspec)	(BW_LT20(CHSPEC_BW(chspec)))
+/* This MACRO is strictly to avoid abandons in existing code with ULB feature and is in no way
+ * optimial to use. Should be replaced with CHSPEC_BW_LE() instead
+ */
+#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)	(BW_LE20(CHSPEC_BW(chspec)))
+
+#else /* WL11ULB */
+#define BW_LE20(bw)		((bw) == WL_CHANSPEC_BW_20)
+#define CHSPEC_ISLE20(chspec)	(CHSPEC_IS20(chspec))
+#endif /* WL11ULB */
+#endif /* !WL11N_20MHZONLY */
+
+#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)
+
+/**
+ * Number of chars needed for wf_chspec_ntoa() destination character buffer.
+ */
+#define CHANSPEC_STR_LEN    20
+
+/*
+ * This function returns TRUE if both the chanspec can co-exist in PHY.
+ * Addition to control channel, the function checks for side band for 2g 40 channels
+ */
+extern bool wf_chspec_coexist(chanspec_t chspec1, chanspec_t chspec2);
+
+#define CHSPEC_IS_BW_160_WIDE(chspec) (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_160 ||\
+	CHSPEC_BW(chspec) == WL_CHANSPEC_BW_8080)
+
+/* BW inequality comparisons, LE (<=), GE (>=), LT (<), GT (>), comparisons can be made
+* as simple numeric comparisons, with the exception that 160 is the same BW as 80+80,
+* but have different numeric values; (WL_CHANSPEC_BW_160 < WL_CHANSPEC_BW_8080).
+*
+* The LT/LE/GT/GE macros check first checks whether both chspec bandwidth and bw are 160 wide.
+* If both chspec bandwidth and bw is not 160 wide, then the comparison is made.
+*/
+#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 /* 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)))
+#endif /* WL11ULB */
+
+#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 /* 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)))
+#endif /* WL11ULB */
+
+#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 /* 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)))
+#endif /* WL11ULB */
+
+#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 /* 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)))
+#endif /* WL11ULB */
+
+/* Legacy Chanspec defines
+ * These are the defines for the previous format of the chanspec_t
+ */
+#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 GET_ALL_EXT wf_get_all_ext
+
+/*
+ * WF_CHAN_FACTOR_* constants are used to calculate channel frequency
+ * given a channel number.
+ * chan_freq = chan_factor * 500Mhz + chan_number * 5
+ */
+
+/**
+ * Channel Factor for the starting frequence of 2.4 GHz channels.
+ * The value corresponds to 2407 MHz.
+ */
+#define WF_CHAN_FACTOR_2_4_G		4814	/* 2.4 GHz band, 2407 MHz */
+
+/**
+ * Channel Factor for the starting frequence of 5 GHz channels.
+ * The value corresponds to 5000 MHz.
+ */
+#define WF_CHAN_FACTOR_5_G		10000	/* 5   GHz band, 5000 MHz */
+
+/**
+ * Channel Factor for the starting frequence of 4.9 GHz channels.
+ * The value corresponds to 4000 MHz.
+ */
+#define WF_CHAN_FACTOR_4_G		8000	/* 4.9 GHz band for Japan */
+
+#define WLC_2G_25MHZ_OFFSET		5	/* 2.4GHz band channel offset */
+
+/**
+ *  No of sub-band vlaue of the specified Mhz chanspec
+ */
+#define WF_NUM_SIDEBANDS_40MHZ   2
+#define WF_NUM_SIDEBANDS_80MHZ   4
+#define WF_NUM_SIDEBANDS_8080MHZ 4
+#define WF_NUM_SIDEBANDS_160MHZ  8
+
+/* Get bandwidth of chanspec in half MHz;
+ * works with 2.5MHz to 160MHz (including 80p80) chanspecs
+ *
+ * @param	chspec		chanspec_t format
+ *
+ * @return	bandwidth of a chanspec in half MHz units
+ */
+extern uint16 wf_bw_chspec_to_half_mhz(chanspec_t chspec);
+
+/**
+ * Convert chanspec to ascii string
+ *
+ * @param	chspec		chanspec format
+ * @param	buf		ascii string of chanspec
+ *
+ * @return	pointer to buf with room for at least CHANSPEC_STR_LEN bytes
+ *		Original chanspec in case of error
+ *
+ * @see		CHANSPEC_STR_LEN
+ */
+extern char * wf_chspec_ntoa_ex(chanspec_t chspec, char *buf);
+
+/**
+ * Convert chanspec to ascii string
+ *
+ * @param	chspec		chanspec format
+ * @param	buf		ascii string of chanspec
+ *
+ * @return	pointer to buf with room for at least CHANSPEC_STR_LEN bytes
+ *		NULL in case of error
+ *
+ * @see		CHANSPEC_STR_LEN
+ */
+extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf);
+
+/**
+ * Convert ascii string to chanspec
+ *
+ * @param	a     pointer to input string
+ *
+ * @return	>= 0 if successful or 0 otherwise
+ */
+extern chanspec_t wf_chspec_aton(const char *a);
+
+/**
+ * Verify the chanspec fields are valid.
+ *
+ * Verify the chanspec is using a legal set field values, i.e. that the chanspec
+ * specified a band, bw, ctl_sb and channel and that the combination could be
+ * legal given some set of circumstances.
+ *
+ * @param	chanspec   input chanspec to verify
+ *
+ * @return TRUE if the chanspec is malformed, FALSE if it looks good.
+ */
+extern bool wf_chspec_malformed(chanspec_t chanspec);
+
+/**
+ * Verify the chanspec specifies a valid channel according to 802.11.
+ *
+ * @param	chanspec   input chanspec to verify
+ *
+ * @return TRUE if the chanspec is a valid 802.11 channel
+ */
+extern bool wf_chspec_valid(chanspec_t chanspec);
+
+/**
+ * Return the primary (control) channel.
+ *
+ * This function returns the channel number of the primary 20MHz channel. For
+ * 20MHz channels this is just the channel number. For 40MHz or wider channels
+ * it is the primary 20MHz channel specified by the chanspec.
+ *
+ * @param	chspec    input chanspec
+ *
+ * @return Returns the channel number of the primary 20MHz channel
+ */
+extern uint8 wf_chspec_ctlchan(chanspec_t chspec);
+
+/*
+ * Return the bandwidth string.
+ *
+ * This function returns the bandwidth string for the passed chanspec.
+ *
+ * @param	chspec    input chanspec
+ *
+ * @return Returns the bandwidth string
+ */
+extern const char *wf_chspec_to_bw_str(chanspec_t chspec);
+
+/**
+ * Return the primary (control) chanspec.
+ *
+ * This function returns the chanspec of the primary 20MHz channel. For 20MHz
+ * channels this is just the chanspec. For 40MHz or wider channels it is the
+ * chanspec of the primary 20MHZ channel specified by the chanspec.
+ *
+ * @param	chspec    input chanspec
+ *
+ * @return Returns the chanspec of the primary 20MHz channel
+ */
+extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec);
+
+/**
+ * Return a channel number corresponding to a frequency.
+ *
+ * This function returns the chanspec for the primary 40MHz of an 80MHz channel.
+ * The control sideband specifies the same 20MHz channel that the 80MHz channel is using
+ * as the primary 20MHz channel.
+ */
+extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec);
+
+/*
+ * Return the channel number for a given frequency and base frequency.
+ * The returned channel number is relative to the given base frequency.
+ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
+ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
+ *
+ * Frequency is specified in MHz.
+ * The base frequency is specified as (start_factor * 500 kHz).
+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
+ * 2.4 GHz and 5 GHz bands.
+ *
+ * The returned channel will be in the range [1, 14] in the 2.4 GHz band
+ * and [0, 200] otherwise.
+ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
+ * frequency is not a 2.4 GHz channel, or if the frequency is not and even
+ * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
+ *
+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ *
+ * @param	freq          frequency in MHz
+ * @param	start_factor  base frequency in 500 kHz units, e.g. 10000 for 5 GHz
+ *
+ * @return Returns a channel number
+ *
+ * @see  WF_CHAN_FACTOR_2_4_G
+ * @see  WF_CHAN_FACTOR_5_G
+ */
+extern int wf_mhz2channel(uint freq, uint start_factor);
+
+/**
+ * Return the center frequency in MHz of the given channel and base frequency.
+ *
+ * Return the center frequency in MHz of the given channel and base frequency.
+ * The channel number is interpreted relative to the given base frequency.
+ *
+ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise.
+ * The base frequency is specified as (start_factor * 500 kHz).
+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
+ * 2.4 GHz and 5 GHz bands.
+ * The channel range of [1, 14] is only checked for a start_factor of
+ * WF_CHAN_FACTOR_2_4_G (4814).
+ * Odd start_factors produce channels on .5 MHz boundaries, in which case
+ * the answer is rounded down to an integral MHz.
+ * -1 is returned for an out of range channel.
+ *
+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ *
+ * @param	channel       input channel number
+ * @param	start_factor  base frequency in 500 kHz units, e.g. 10000 for 5 GHz
+ *
+ * @return Returns a frequency in MHz
+ *
+ * @see  WF_CHAN_FACTOR_2_4_G
+ * @see  WF_CHAN_FACTOR_5_G
+ */
+extern int wf_channel2mhz(uint channel, uint start_factor);
+
+/**
+ * Returns the chanspec 80Mhz channel corresponding to the following input
+ * parameters
+ *
+ *	primary_channel - primary 20Mhz channel
+ *	center_channel   - center frequecny of the 80Mhz channel
+ *
+ * The center_channel can be one of {42, 58, 106, 122, 138, 155}
+ *
+ * returns INVCHANSPEC in case of error
+ */
+extern chanspec_t wf_chspec_80(uint8 center_channel, uint8 primary_channel);
+
+/**
+ * Convert ctl chan and bw to chanspec
+ *
+ * @param	ctl_ch		channel
+ * @param	bw	        bandwidth
+ *
+ * @return	> 0 if successful or 0 otherwise
+ *
+ */
+extern uint16 wf_channel2chspec(uint ctl_ch, uint bw);
+
+extern uint wf_channel2freq(uint channel);
+extern uint wf_freq2channel(uint freq);
+
+/*
+ * Returns the 80+80 MHz chanspec corresponding to the following input parameters
+ *
+ *    primary_20mhz - Primary 20 MHz channel
+ *    chan0_80MHz - center channel number of one frequency segment
+ *    chan1_80MHz - center channel number of the other frequency segment
+ *
+ * Parameters chan0_80MHz and chan1_80MHz are channel numbers in {42, 58, 106, 122, 138, 155}.
+ * The primary channel must be contained in one of the 80MHz channels. This routine
+ * will determine which frequency segment is the primary 80 MHz segment.
+ *
+ * Returns INVCHANSPEC in case of error.
+ *
+ * Refer to IEEE802.11ac section 22.3.14 "Channelization".
+ */
+extern chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz,
+	uint8 chan0_80Mhz, uint8 chan1_80Mhz);
+
+/*
+ * Returns the primary 80 Mhz channel for the provided chanspec
+ *
+ *    chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved
+ *
+ *  returns -1 in case the provided channel is 20/40 Mhz chanspec
+ */
+extern uint8 wf_chspec_primary80_channel(chanspec_t chanspec);
+
+/*
+ * Returns the secondary 80 Mhz channel for the provided chanspec
+ *
+ *    chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved
+ *
+ *  returns -1 in case the provided channel is 20/40 Mhz chanspec
+ */
+extern uint8 wf_chspec_secondary80_channel(chanspec_t chanspec);
+
+/*
+ * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel.
+ */
+extern chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec);
+
+/*
+ * For 160MHz or 80P80 chanspec, set ch[0]/ch[1] to be the low/high 80 Mhz channels
+ *
+ * For 20/40/80MHz chanspec, set ch[0] to be the center freq, and chan[1]=-1
+ */
+extern void wf_chspec_get_80p80_channels(chanspec_t chspec, uint8 *ch);
+
+#ifdef WL11AC_80P80
+/*
+ * This function returns the centre chanel for the given chanspec.
+ * In case of 80+80 chanspec it returns the primary 80 Mhz centre channel
+ */
+extern uint8 wf_chspec_channel(chanspec_t chspec);
+#endif
+extern chanspec_t wf_channel_create_chspec_frm_opclass(uint8 opclass, uint8 channel);
+extern int wf_channel_create_opclass_frm_chspec(chanspec_t chspec);
+
+/* Populates array with all 20MHz side bands of a given chanspec_t in the following order:
+ *		control, ext20, two ext40s, four ext80s.
+ *     'chspec' is the chanspec of interest
+ *     'pext' must point to an uint8 array of long enough to hold all side bands of the given chspec
+ *
+ * Works with 20, 40, 80, 80p80 and 160MHz chspec
+ */
+
+extern void wf_get_all_ext(chanspec_t chspec, uint8 *chan_ptr);
+#endif	/* _bcmwifi_channels_h_ */
diff --git a/wl/src/shared/bcmwifi/include/bcmwifi_rates.h b/wl/src/shared/bcmwifi/include/bcmwifi_rates.h
new file mode 100644
index 0000000..70ed384
--- /dev/null
+++ b/wl/src/shared/bcmwifi/include/bcmwifi_rates.h
@@ -0,0 +1,787 @@
+/*
+ * Indices for 802.11 a/b/g/n/ac 1-3 chain symmetric transmit rates
+ *
+ * Copyright (C) 2017, Broadcom. 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 612483 2016-01-14 03:44:27Z $
+ */
+
+#ifndef _bcmwifi_rates_h_
+#define _bcmwifi_rates_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#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	/* MAC histogram, compatibility with wl utility */
+
+#define WL_TX_CHAINS_MAX		4
+
+#define WL_RATE_DISABLED		(-128) /* Power value corresponding to unsupported rate */
+
+/* Transmit channel bandwidths */
+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;
+
+
+/*
+ * Transmit modes.
+ * Not all modes are listed here, only those required for disambiguation. e.g. SPEXP is not listed
+ */
+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;
+
+
+/* Number of transmit chains */
+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;
+
+
+/* Number of transmit streams */
+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;
+
+
+/* This enum maps each rate to a CLM index */
+
+typedef enum clm_rates {
+	/************
+	* 1 chain  *
+	************
+	*/
+
+	/* 1 Stream */
+	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,
+
+
+	/************
+	* 2 chains *
+	************
+	*/
+
+	/* 1 Stream expanded + 1 */
+	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,
+
+	/* 2 Streams */
+	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,
+
+	/****************************
+	 * TX Beamforming, 2 chains *
+	 ****************************
+	 */
+
+	/* 1 Stream expanded + 1 */
+	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,
+
+	/* 2 Streams */
+	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,
+
+
+	/************
+	* 3 chains *
+	************
+	*/
+
+	/* 1 Stream expanded + 2 */
+	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,
+
+	/* 2 Streams expanded + 1 */
+	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,
+
+	/* 3 Streams */
+	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,
+
+
+	/****************************
+	 * TX Beamforming, 3 chains *
+	 ****************************
+	 */
+
+	/* 1 Stream expanded + 2 */
+	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,
+
+	/* 2 Streams expanded + 1 */
+	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,
+
+	/* 3 Streams */
+	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,
+
+
+	/************
+	* 4 chains *
+	************
+	*/
+
+	/* 1 Stream expanded + 3 */
+	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,
+
+	/* 2 Streams expanded + 2 */
+	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,
+
+	/* 3 Streams expanded + 1 */
+	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,
+
+
+	/* 4 Streams */
+	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,
+
+
+	/****************************
+	 * TX Beamforming, 4 chains *
+	 ****************************
+	 */
+
+	/* 1 Stream expanded + 3 */
+	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,
+
+	/* 2 Streams expanded + 2 */
+	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,
+
+	/* 3 Streams expanded + 1 */
+	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,
+
+	/* 4 Streams */
+	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;
+
+/* Number of rate codes */
+#define WL_NUMRATES 336
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _bcmwifi_rates_h_ */
diff --git a/wl/src/shared/bcmwifi/src/bcmwifi_channels.c b/wl/src/shared/bcmwifi/src/bcmwifi_channels.c
new file mode 100644
index 0000000..c3738ed
--- /dev/null
+++ b/wl/src/shared/bcmwifi/src/bcmwifi_channels.c
@@ -0,0 +1,1452 @@
+/*
+ * Misc utility routines used by kernel or app-level.
+ * Contents are wifi-specific, used by any kernel or app-level
+ * software that might want wifi things as it grows.
+ *
+ * Copyright (C) 2017, Broadcom. 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.c 655845 2016-08-24 01:05:41Z $
+ */
+
+#include <bcm_cfg.h>
+#include <typedefs.h>
+#include <bcmutils.h>
+
+#ifdef BCMDRIVER
+#include <osl.h>
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifndef ASSERT
+#define ASSERT(exp)
+#endif
+#endif /* BCMDRIVER */
+
+#include <bcmwifi_channels.h>
+
+#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
+#include <bcmstdlib.h> 	/* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
+#endif
+
+/* Definitions for D11AC capable Chanspec type */
+
+/* Chanspec ASCII representation with 802.11ac capability:
+ * [<band> 'g'] <channel> ['/'<bandwidth> [<ctl-sideband>]['/'<1st80channel>'-'<2nd80channel>]]
+ *
+ * <band>:
+ *      (optional) 2, 3, 4, 5 for 2.4GHz, 3GHz, 4GHz, and 5GHz respectively.
+ *      Default value is 2g if channel <= 14, otherwise 5g.
+ * <channel>:
+ *      channel number of the 5MHz, 10MHz, 20MHz channel,
+ *      or primary channel of 40MHz, 80MHz, 160MHz, or 80+80MHz channel.
+ * <bandwidth>:
+ *      (optional) 5, 10, 20, 40, 80, 160, or 80+80. Default value is 20.
+ * <primary-sideband>:
+ *      (only for 2.4GHz band 40MHz) U for upper sideband primary, L for lower.
+ *
+ *      For 2.4GHz band 40MHz channels, the same primary channel may be the
+ *      upper sideband for one 40MHz channel, and the lower sideband for an
+ *      overlapping 40MHz channel.  The U/L disambiguates which 40MHz channel
+ *      is being specified.
+ *
+ *      For 40MHz in the 5GHz band and all channel bandwidths greater than
+ *      40MHz, the U/L specificaion is not allowed since the channels are
+ *      non-overlapping and the primary sub-band is derived from its
+ *      position in the wide bandwidth channel.
+ *
+ * <1st80Channel>:
+ * <2nd80Channel>:
+ *      Required for 80+80, otherwise not allowed.
+ *      Specifies the center channel of the first and second 80MHz band.
+ *
+ * In its simplest form, it is a 20MHz channel number, with the implied band
+ * of 2.4GHz if channel number <= 14, and 5GHz otherwise.
+ *
+ * To allow for backward compatibility with scripts, the old form for
+ * 40MHz channels is also allowed: <channel><ctl-sideband>
+ *
+ * <channel>:
+ *	primary channel of 40MHz, channel <= 14 is 2GHz, otherwise 5GHz
+ * <ctl-sideband>:
+ * 	"U" for upper, "L" for lower (or lower case "u" "l")
+ *
+ * 5 GHz Examples:
+ *      Chanspec        BW        Center Ch  Channel Range  Primary Ch
+ *      5g8             20MHz     8          -              -
+ *      52              20MHz     52         -              -
+ *      52/40           40MHz     54         52-56          52
+ *      56/40           40MHz     54         52-56          56
+ *      52/80           80MHz     58         52-64          52
+ *      56/80           80MHz     58         52-64          56
+ *      60/80           80MHz     58         52-64          60
+ *      64/80           80MHz     58         52-64          64
+ *      52/160          160MHz    50         36-64          52
+ *      36/160          160MGz    50         36-64          36
+ *      36/80+80/42-106 80+80MHz  42,106     36-48,100-112  36
+ *
+ * 2 GHz Examples:
+ *      Chanspec        BW        Center Ch  Channel Range  Primary Ch
+ *      2g8             20MHz     8          -              -
+ *      8               20MHz     8          -              -
+ *      6               20MHz     6          -              -
+ *      6/40l           40MHz     8          6-10           6
+ *      6l              40MHz     8          6-10           6
+ *      6/40u           40MHz     4          2-6            6
+ *      6u              40MHz     4          2-6            6
+ */
+
+/* bandwidth ASCII string */
+static const char *wf_chspec_bw_str[] =
+{
+	"5",
+	"10",
+	"20",
+	"40",
+	"80",
+	"160",
+	"80+80",
+#ifdef WL11ULB
+	"2.5"
+#else /* WL11ULB */
+	"na"
+#endif /* WL11ULB */
+};
+
+static const uint16 wf_chspec_bw_half_mhz[] = {
+	10,	/*   5MHz (WL_CHANSPEC_BW_5) */
+	20,	/*  10MHz (WL_CHANSPEC_BW_10) */
+	40,	/*  20MHz (WL_CHANSPEC_BW_20) */
+	80,	/*  40MHz (WL_CHANSPEC_BW_40) */
+	160,	/*  80MHz (WL_CHANSPEC_BW_80) */
+	320,	/* 160MHz (WL_CHANSPEC_BW_160) */
+	320,	/* 160MHz (WL_CHANSPEC_BW_8080) */
+	5	/* 2.5MHz (WL_CHANSPEC_BW_2P5) */
+};
+
+#define WF_NUM_BW_HALF_MHZ	ARRAYSIZE(wf_chspec_bw_half_mhz)
+
+static const uint8 wf_chspec_bw_mhz[] =
+{5, 10, 20, 40, 80, 160, 160};
+
+#define WF_NUM_BW \
+	(sizeof(wf_chspec_bw_mhz)/sizeof(uint8))
+
+/* 40MHz channels in 5GHz band */
+static const uint8 wf_5g_40m_chans[] =
+{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159};
+#define WF_NUM_5G_40M_CHANS \
+	(sizeof(wf_5g_40m_chans)/sizeof(uint8))
+
+/* 80MHz channels in 5GHz band */
+static const uint8 wf_5g_80m_chans[] =
+{42, 58, 106, 122, 138, 155};
+#define WF_NUM_5G_80M_CHANS \
+	(sizeof(wf_5g_80m_chans)/sizeof(uint8))
+
+/* 160MHz channels in 5GHz band */
+static const uint8 wf_5g_160m_chans[] =
+{50, 114};
+#define WF_NUM_5G_160M_CHANS \
+	(sizeof(wf_5g_160m_chans)/sizeof(uint8))
+
+/* opclass and channel information for US. Table E-1 */
+static const uint16 opclass_data[] = {
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_2G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_3G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_3G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_3G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_5)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_10)&WL_CHANSPEC_BW_MASK)),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_20)&WL_CHANSPEC_BW_MASK)),
+	0,
+	0,
+	0,
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+	(WL_CHANSPEC_BAND_5G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+	(WL_CHANSPEC_BAND_2G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_LOWER),
+	(WL_CHANSPEC_BAND_2G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER),
+};
+
+/* Get bandwidth of chanspec in half MHz;
+ * works with 2.5MHz to 160MHz (including 80p80) chanspecs
+ *
+ * @param	chspec		chanspec_t format
+ *
+ * @return	bandwidth of a chanspec in half MHz units
+ */
+uint16
+wf_bw_chspec_to_half_mhz(chanspec_t chspec)
+{
+	uint16 bw;
+
+	bw = (chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT;
+	return (bw >= WF_NUM_BW_HALF_MHZ ? 0 : wf_chspec_bw_half_mhz[bw]);
+}
+
+/* convert bandwidth from chanspec to MHz; works with 5MHz to 160MHz (including 80p80) */
+static uint
+bw_chspec_to_mhz(chanspec_t chspec)
+{
+	uint bw;
+
+	bw = (chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT;
+	return (bw >= WF_NUM_BW ? 0 : wf_chspec_bw_mhz[bw]);
+}
+
+/* bw in MHz, return the channel count from the center channel to the
+ * the channel at the edge of the band
+ */
+static uint8
+center_chan_to_edge(uint bw)
+{
+	/* edge channels separated by BW - 10MHz on each side
+	 * delta from cf to edge is half of that,
+	 * MHz to channel num conversion is 5MHz/channel
+	 */
+	return (uint8)(((bw - 20) / 2) / 5);
+}
+
+/* return channel number of the low edge of the band
+ * given the center channel and BW
+ */
+static uint8
+channel_low_edge(uint center_ch, uint bw)
+{
+	return (uint8)(center_ch - center_chan_to_edge(bw));
+}
+
+/* return side band number given center channel and control channel
+ * return -1 on error
+ */
+static int
+channel_to_sb(uint center_ch, uint ctl_ch, uint bw)
+{
+	uint lowest = channel_low_edge(center_ch, bw);
+	uint sb;
+
+	if ((ctl_ch - lowest) % 4) {
+		/* bad ctl channel, not mult 4 */
+		return -1;
+	}
+
+	sb = ((ctl_ch - lowest) / 4);
+
+	/* sb must be a index to a 20MHz channel in range */
+	if (sb >= (bw / 20)) {
+		/* ctl_ch must have been too high for the center_ch */
+		return -1;
+	}
+
+	return sb;
+}
+
+/* return control channel given center channel and side band */
+static uint8
+channel_to_ctl_chan(uint center_ch, uint bw, uint sb)
+{
+	return (uint8)(channel_low_edge(center_ch, bw) + sb * 4);
+}
+
+/* return index of 80MHz channel from channel number
+ * return -1 on error
+ */
+static int
+channel_80mhz_to_id(uint ch)
+{
+	uint i;
+	for (i = 0; i < WF_NUM_5G_80M_CHANS; i ++) {
+		if (ch == wf_5g_80m_chans[i])
+			return i;
+	}
+
+	return -1;
+}
+
+/* wrapper function for wf_chspec_ntoa. In case of an error it puts
+ * the original chanspec in the output buffer, prepended with "invalid".
+ * Can be directly used in print routines as it takes care of null
+ */
+char *
+wf_chspec_ntoa_ex(chanspec_t chspec, char *buf)
+{
+	if (wf_chspec_ntoa(chspec, buf) == NULL)
+		snprintf(buf, CHANSPEC_STR_LEN, "invalid 0x%04x", chspec);
+	return buf;
+}
+
+/* given a chanspec and a string buffer, format the chanspec as a
+ * string, and return the original pointer a.
+ * Min buffer length must be CHANSPEC_STR_LEN.
+ * On error return NULL
+ */
+char *
+wf_chspec_ntoa(chanspec_t chspec, char *buf)
+{
+	const char *band;
+	uint ctl_chan;
+
+	if (wf_chspec_malformed(chspec))
+		return NULL;
+
+	band = "";
+
+	/* check for non-default band spec */
+	if ((CHSPEC_IS2G(chspec) && CHSPEC_CHANNEL(chspec) > CH_MAX_2G_CHANNEL) ||
+	    (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL))
+		band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g";
+
+	/* ctl channel */
+	ctl_chan = wf_chspec_ctlchan(chspec);
+
+	/* bandwidth and ctl sideband */
+	if (CHSPEC_IS20(chspec)) {
+		snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan);
+	} else if (!CHSPEC_IS8080(chspec)) {
+		const char *bw;
+		const char *sb = "";
+
+		bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT];
+
+#ifdef CHANSPEC_NEW_40MHZ_FORMAT
+		/* ctl sideband string if needed for 2g 40MHz */
+		if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) {
+			sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
+		}
+
+		snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb);
+#else
+		/* ctl sideband string instead of BW for 40MHz */
+		if (CHSPEC_IS40(chspec)) {
+			sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l";
+			snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb);
+		} else {
+			snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw);
+		}
+#endif /* CHANSPEC_NEW_40MHZ_FORMAT */
+
+	} else {
+		/* 80+80 */
+		uint chan1 = (chspec & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT;
+		uint chan2 = (chspec & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT;
+
+		/* convert to channel number */
+		chan1 = (chan1 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan1] : 0;
+		chan2 = (chan2 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan2] : 0;
+
+		/* Outputs a max of CHANSPEC_STR_LEN chars including '\0'  */
+		snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", ctl_chan, chan1, chan2);
+	}
+
+	return (buf);
+}
+
+static int
+read_uint(const char **p, unsigned int *num)
+{
+	unsigned long val;
+	char *endp = NULL;
+
+	val = strtoul(*p, &endp, 10);
+	/* if endp is the initial pointer value, then a number was not read */
+	if (endp == *p)
+		return 0;
+
+	/* advance the buffer pointer to the end of the integer string */
+	*p = endp;
+	/* return the parsed integer */
+	*num = (unsigned int)val;
+
+	return 1;
+}
+
+/* given a chanspec string, convert to a chanspec.
+ * On error return 0
+ */
+chanspec_t
+wf_chspec_aton(const char *a)
+{
+	chanspec_t chspec;
+	uint chspec_ch, chspec_band, bw, chspec_bw, chspec_sb;
+	uint num, ctl_ch;
+	uint ch1, ch2;
+	char c, sb_ul = '\0';
+	int i;
+
+	bw = 20;
+	chspec_sb = 0;
+	chspec_ch = ch1 = ch2 = 0;
+
+	/* parse channel num or band */
+	if (!read_uint(&a, &num))
+		return 0;
+	/* if we are looking at a 'g', then the first number was a band */
+	c = tolower((int)a[0]);
+	if (c == 'g') {
+		a++; /* consume the char */
+
+		/* band must be "2" or "5" */
+		if (num == 2)
+			chspec_band = WL_CHANSPEC_BAND_2G;
+		else if (num == 5)
+			chspec_band = WL_CHANSPEC_BAND_5G;
+		else
+			return 0;
+
+		/* read the channel number */
+		if (!read_uint(&a, &ctl_ch))
+			return 0;
+
+		c = tolower((int)a[0]);
+	}
+	else {
+		/* first number is channel, use default for band */
+		ctl_ch = num;
+		chspec_band = ((ctl_ch <= CH_MAX_2G_CHANNEL) ?
+		               WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
+	}
+
+	if (c == '\0') {
+		/* default BW of 20MHz */
+		chspec_bw = WL_CHANSPEC_BW_20;
+		goto done_read;
+	}
+
+	a ++; /* consume the 'u','l', or '/' */
+
+	/* check 'u'/'l' */
+	if (c == 'u' || c == 'l') {
+		sb_ul = c;
+		chspec_bw = WL_CHANSPEC_BW_40;
+		goto done_read;
+	}
+
+	/* next letter must be '/' */
+	if (c != '/')
+		return 0;
+
+	/* read bandwidth */
+	if (!read_uint(&a, &bw))
+		return 0;
+
+	/* convert to chspec value */
+	if (bw == 2) {
+		chspec_bw = WL_CHANSPEC_BW_2P5;
+	} else if (bw == 5) {
+		chspec_bw = WL_CHANSPEC_BW_5;
+	} else if (bw == 10) {
+		chspec_bw = WL_CHANSPEC_BW_10;
+	} else if (bw == 20) {
+		chspec_bw = WL_CHANSPEC_BW_20;
+	} else if (bw == 40) {
+		chspec_bw = WL_CHANSPEC_BW_40;
+	} else if (bw == 80) {
+		chspec_bw = WL_CHANSPEC_BW_80;
+	} else if (bw == 160) {
+		chspec_bw = WL_CHANSPEC_BW_160;
+	} else {
+		return 0;
+	}
+
+	/* So far we have <band>g<chan>/<bw>
+	 * Can now be followed by u/l if bw = 40,
+	 * or '+80' if bw = 80, to make '80+80' bw,
+	 * or '.5' if bw = 2.5 to make '2.5' bw .
+	 */
+
+	c = tolower((int)a[0]);
+
+	/* if we have a 2g/40 channel, we should have a l/u spec now */
+	if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) {
+		if (c == 'u' || c == 'l') {
+			a ++; /* consume the u/l char */
+			sb_ul = c;
+			goto done_read;
+		}
+	}
+
+	/* check for 80+80 */
+	if (c == '+') {
+		/* 80+80 */
+		const char plus80[] = "80/";
+
+		/* must be looking at '+80/'
+		 * check and consume this string.
+		 */
+		chspec_bw = WL_CHANSPEC_BW_8080;
+
+		a ++; /* consume the char '+' */
+
+		/* consume the '80/' string */
+		for (i = 0; i < 3; i++) {
+			if (*a++ != plus80[i]) {
+				return 0;
+			}
+		}
+
+		/* read primary 80MHz channel */
+		if (!read_uint(&a, &ch1))
+			return 0;
+
+		/* must followed by '-' */
+		if (a[0] != '-')
+			return 0;
+		a ++; /* consume the char */
+
+		/* read secondary 80MHz channel */
+		if (!read_uint(&a, &ch2))
+			return 0;
+	} else if (c == '.') {
+		/* 2.5 */
+		/* must be looking at '.5'
+		 * check and consume this string.
+		 */
+		chspec_bw = WL_CHANSPEC_BW_2P5;
+
+		a ++; /* consume the char '.' */
+
+		/* consume the '5' string */
+		if (*a++ != '5') {
+			return 0;
+		}
+	}
+
+done_read:
+	/* skip trailing white space */
+	while (a[0] == ' ') {
+		a ++;
+	}
+
+	/* must be end of string */
+	if (a[0] != '\0')
+		return 0;
+
+	/* Now have all the chanspec string parts read;
+	 * chspec_band, ctl_ch, chspec_bw, sb_ul, ch1, ch2.
+	 * chspec_band and chspec_bw are chanspec values.
+	 * Need to convert ctl_ch, sb_ul, and ch1,ch2 into
+	 * a center channel (or two) and sideband.
+	 */
+
+	/* if a sb u/l string was given, just use that,
+	 * guaranteed to be bw = 40 by sting parse.
+	 */
+	if (sb_ul != '\0') {
+		if (sb_ul == 'l') {
+			chspec_ch = UPPER_20_SB(ctl_ch);
+			chspec_sb = WL_CHANSPEC_CTL_SB_LLL;
+		} else if (sb_ul == 'u') {
+			chspec_ch = LOWER_20_SB(ctl_ch);
+			chspec_sb = WL_CHANSPEC_CTL_SB_LLU;
+		}
+	}
+	/* if the bw is 20, center and sideband are trivial */
+	else if (BW_LE20(chspec_bw)) {
+		chspec_ch = ctl_ch;
+		chspec_sb = WL_CHANSPEC_CTL_SB_NONE;
+	}
+	/* if the bw is 40/80/160, not 80+80, a single method
+	 * can be used to to find the center and sideband
+	 */
+	else if (chspec_bw != WL_CHANSPEC_BW_8080) {
+		/* figure out ctl sideband based on ctl channel and bandwidth */
+		const uint8 *center_ch = NULL;
+		int num_ch = 0;
+		int sb = -1;
+
+		if (chspec_bw == WL_CHANSPEC_BW_40) {
+			center_ch = wf_5g_40m_chans;
+			num_ch = WF_NUM_5G_40M_CHANS;
+		} else if (chspec_bw == WL_CHANSPEC_BW_80) {
+			center_ch = wf_5g_80m_chans;
+			num_ch = WF_NUM_5G_80M_CHANS;
+		} else if (chspec_bw == WL_CHANSPEC_BW_160) {
+			center_ch = wf_5g_160m_chans;
+			num_ch = WF_NUM_5G_160M_CHANS;
+		} else {
+			return 0;
+		}
+
+		for (i = 0; i < num_ch; i ++) {
+			sb = channel_to_sb(center_ch[i], ctl_ch, bw);
+			if (sb >= 0) {
+				chspec_ch = center_ch[i];
+				chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
+				break;
+			}
+		}
+
+		/* check for no matching sb/center */
+		if (sb < 0) {
+			return 0;
+		}
+	}
+	/* Otherwise, bw is 80+80. Figure out channel pair and sb */
+	else {
+		int ch1_id = 0, ch2_id = 0;
+		int sb;
+
+		/* look up the channel ID for the specified channel numbers */
+		ch1_id = channel_80mhz_to_id(ch1);
+		ch2_id = channel_80mhz_to_id(ch2);
+
+		/* validate channels */
+		if (ch1_id < 0 || ch2_id < 0)
+			return 0;
+
+		/* combine 2 channel IDs in channel field of chspec */
+		chspec_ch = (((uint)ch1_id << WL_CHANSPEC_CHAN1_SHIFT) |
+		             ((uint)ch2_id << WL_CHANSPEC_CHAN2_SHIFT));
+
+		/* figure out primary 20 MHz sideband */
+
+		/* is the primary channel contained in the 1st 80MHz channel? */
+		sb = channel_to_sb(ch1, ctl_ch, bw);
+		if (sb < 0) {
+			/* no match for primary channel 'ctl_ch' in segment0 80MHz channel */
+			return 0;
+		}
+
+		chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT;
+	}
+
+	chspec = (chspec_ch | chspec_band | chspec_bw | chspec_sb);
+
+	if (wf_chspec_malformed(chspec))
+		return 0;
+
+	return chspec;
+}
+
+/*
+ * Verify the chanspec is using a legal set of parameters, i.e. that the
+ * chanspec specified a band, bw, ctl_sb and channel and that the
+ * combination could be legal given any set of circumstances.
+ * RETURNS: TRUE is the chanspec is malformed, false if it looks good.
+ */
+bool
+wf_chspec_malformed(chanspec_t chanspec)
+{
+	uint chspec_bw = CHSPEC_BW(chanspec);
+	uint chspec_ch = CHSPEC_CHANNEL(chanspec);
+
+	/* must be 2G or 5G band */
+	if (CHSPEC_IS2G(chanspec)) {
+		/* must be valid bandwidth */
+		if (!BW_LE40(chspec_bw)) {
+			return TRUE;
+		}
+	} else if (CHSPEC_IS5G(chanspec)) {
+		if (chspec_bw == WL_CHANSPEC_BW_8080) {
+			uint ch1_id, ch2_id;
+
+			/* channel IDs in 80+80 must be in range */
+			ch1_id = CHSPEC_CHAN1(chanspec);
+			ch2_id = CHSPEC_CHAN2(chanspec);
+			if (ch1_id >= WF_NUM_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS)
+				return TRUE;
+
+		} else if (BW_LE20(chspec_bw) || chspec_bw == WL_CHANSPEC_BW_40 ||
+				chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) {
+
+			if (chspec_ch > MAXCHANNEL) {
+				return TRUE;
+			}
+		} else {
+			/* invalid bandwidth */
+			return TRUE;
+		}
+	} else {
+		/* must be 2G or 5G band */
+		return TRUE;
+	}
+
+	/* side band needs to be consistent with bandwidth */
+	if (BW_LE20(chspec_bw)) {
+		if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL)
+			return TRUE;
+	} else if (chspec_bw == WL_CHANSPEC_BW_40) {
+		if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LLU)
+			return TRUE;
+	} else if (chspec_bw == WL_CHANSPEC_BW_80) {
+		if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU)
+			return TRUE;
+	}
+	else if (chspec_bw == WL_CHANSPEC_BW_160 ||
+		chspec_bw == WL_CHANSPEC_BW_8080) {
+		ASSERT(CHSPEC_CTL_SB(chanspec) <= WL_CHANSPEC_CTL_SB_UUU);
+	}
+	return FALSE;
+}
+
+/*
+ * Verify the chanspec specifies a valid channel according to 802.11.
+ * RETURNS: TRUE if the chanspec is a valid 802.11 channel
+ */
+bool
+wf_chspec_valid(chanspec_t chanspec)
+{
+	uint chspec_bw = CHSPEC_BW(chanspec);
+	uint chspec_ch = CHSPEC_CHANNEL(chanspec);
+
+	if (wf_chspec_malformed(chanspec))
+		return FALSE;
+
+	if (CHSPEC_IS2G(chanspec)) {
+		/* must be valid bandwidth and channel range */
+		if (BW_LE20(chspec_bw)) {
+			if (chspec_ch >= 1 && chspec_ch <= 14)
+				return TRUE;
+		} else if (chspec_bw == WL_CHANSPEC_BW_40) {
+			if (chspec_ch >= 3 && chspec_ch <= 11)
+				return TRUE;
+		}
+	} else if (CHSPEC_IS5G(chanspec)) {
+		if (chspec_bw == WL_CHANSPEC_BW_8080) {
+			uint16 ch1, ch2;
+
+			ch1 = wf_5g_80m_chans[CHSPEC_CHAN1(chanspec)];
+			ch2 = wf_5g_80m_chans[CHSPEC_CHAN2(chanspec)];
+
+			/* the two channels must be separated by more than 80MHz by VHT req */
+			if ((ch2 > ch1 + CH_80MHZ_APART) ||
+			    (ch1 > ch2 + CH_80MHZ_APART))
+				return TRUE;
+		} else {
+			const uint8 *center_ch;
+			uint num_ch, i;
+
+			if (BW_LE40(chspec_bw)) {
+				center_ch = wf_5g_40m_chans;
+				num_ch = WF_NUM_5G_40M_CHANS;
+			} else if (chspec_bw == WL_CHANSPEC_BW_80) {
+				center_ch = wf_5g_80m_chans;
+				num_ch = WF_NUM_5G_80M_CHANS;
+			} else if (chspec_bw == WL_CHANSPEC_BW_160) {
+				center_ch = wf_5g_160m_chans;
+				num_ch = WF_NUM_5G_160M_CHANS;
+			} else {
+				/* invalid bandwidth */
+				return FALSE;
+			}
+
+			/* check for a valid center channel */
+			if (BW_LE20(chspec_bw)) {
+				/* We don't have an array of legal 20MHz 5G channels, but they are
+				 * each side of the legal 40MHz channels.  Check the chanspec
+				 * channel against either side of the 40MHz channels.
+				 */
+				for (i = 0; i < num_ch; i ++) {
+					if (chspec_ch == (uint)LOWER_20_SB(center_ch[i]) ||
+					    chspec_ch == (uint)UPPER_20_SB(center_ch[i]))
+						break; /* match found */
+				}
+
+				if (i == num_ch) {
+					/* check for channel 165 which is not the side band
+					 * of 40MHz 5G channel
+					 */
+					if (chspec_ch == 165)
+						i = 0;
+
+					/* check for legacy JP channels on failure */
+					if (chspec_ch == 34 || chspec_ch == 38 ||
+					    chspec_ch == 42 || chspec_ch == 46)
+						i = 0;
+				}
+			} else {
+				/* check the chanspec channel to each legal channel */
+				for (i = 0; i < num_ch; i ++) {
+					if (chspec_ch == center_ch[i])
+						break; /* match found */
+				}
+			}
+
+			if (i < num_ch) {
+				/* match found */
+				return TRUE;
+			}
+		}
+	}
+
+	return FALSE;
+}
+
+/*
+ * This function returns TRUE if both the chanspec can co-exist in PHY.
+ * Addition to control channel, the function checks for side band for 2g 40 channels
+ */
+bool
+wf_chspec_coexist(chanspec_t chspec1, chanspec_t chspec2)
+{
+	bool same_ctl = (wf_chspec_ctlchan(chspec1) == wf_chspec_ctlchan(chspec2));
+
+	if (same_ctl && CHSPEC_IS2G(chspec1)) {
+	    if (CHSPEC_IS40(chspec1) && CHSPEC_IS40(chspec2)) {
+	        return (CHSPEC_CTL_SB(chspec1) == CHSPEC_CTL_SB(chspec2));
+	    }
+	}
+	return same_ctl;
+}
+
+/*
+ * This function returns the channel number that control traffic is being sent on, for 20MHz
+ * channels this is just the channel number, for 40MHZ, 80MHz, 160MHz channels it is the 20MHZ
+ * sideband depending on the chanspec selected
+ */
+uint8
+wf_chspec_ctlchan(chanspec_t chspec)
+{
+	uint center_chan;
+	uint bw_mhz;
+	uint sb;
+
+	ASSERT(!wf_chspec_malformed(chspec));
+
+	/* Is there a sideband ? */
+	if (CHSPEC_BW_LE20(chspec)) {
+		return CHSPEC_CHANNEL(chspec);
+	} else {
+		sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
+
+		if (CHSPEC_IS8080(chspec)) {
+			/* For an 80+80 MHz channel, the sideband 'sb' field is an 80 MHz sideband
+			 * (LL, LU, UL, LU) for the 80 MHz frequency segment 0.
+			 */
+			uint chan_id = CHSPEC_CHAN1(chspec);
+
+			bw_mhz = 80;
+
+			/* convert from channel index to channel number */
+			center_chan = wf_5g_80m_chans[chan_id];
+		}
+		else {
+			bw_mhz = bw_chspec_to_mhz(chspec);
+			center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT;
+		}
+
+		return (channel_to_ctl_chan(center_chan, bw_mhz, sb));
+	}
+}
+
+/* given a chanspec, return the bandwidth string */
+const char *
+wf_chspec_to_bw_str(chanspec_t chspec)
+{
+	return wf_chspec_bw_str[(CHSPEC_BW(chspec) >> WL_CHANSPEC_BW_SHIFT)];
+}
+
+/*
+ * This function returns the chanspec of the control channel of a given chanspec
+ */
+chanspec_t
+wf_chspec_ctlchspec(chanspec_t chspec)
+{
+	chanspec_t ctl_chspec = chspec;
+	uint8 ctl_chan;
+
+	ASSERT(!wf_chspec_malformed(chspec));
+
+	/* Is there a sideband ? */
+	if (!CHSPEC_BW_LE20(chspec)) {
+		ctl_chan = wf_chspec_ctlchan(chspec);
+		ctl_chspec = ctl_chan | WL_CHANSPEC_BW_20;
+		ctl_chspec |= CHSPEC_BAND(chspec);
+	}
+	return ctl_chspec;
+}
+
+/* return chanspec given control channel and bandwidth
+ * return 0 on error
+ */
+uint16
+wf_channel2chspec(uint ctl_ch, uint bw)
+{
+	uint16 chspec;
+	const uint8 *center_ch = NULL;
+	int num_ch = 0;
+	int sb = -1;
+	int i = 0;
+
+	chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G);
+
+	chspec |= bw;
+
+	if (bw == WL_CHANSPEC_BW_40) {
+		center_ch = wf_5g_40m_chans;
+		num_ch = WF_NUM_5G_40M_CHANS;
+		bw = 40;
+	} else if (bw == WL_CHANSPEC_BW_80) {
+		center_ch = wf_5g_80m_chans;
+		num_ch = WF_NUM_5G_80M_CHANS;
+		bw = 80;
+	} else if (bw == WL_CHANSPEC_BW_160) {
+		center_ch = wf_5g_160m_chans;
+		num_ch = WF_NUM_5G_160M_CHANS;
+		bw = 160;
+	} else if (BW_LE20(bw)) {
+		chspec |= ctl_ch;
+		return chspec;
+	} else {
+		return 0;
+	}
+
+	for (i = 0; i < num_ch; i ++) {
+		sb = channel_to_sb(center_ch[i], ctl_ch, bw);
+		if (sb >= 0) {
+			chspec |= center_ch[i];
+			chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT);
+			break;
+		}
+	}
+
+	/* check for no matching sb/center */
+	if (sb < 0) {
+		return 0;
+	}
+
+	return chspec;
+}
+
+/*
+ * This function returns the chanspec for the primary 40MHz of an 80MHz channel.
+ * The control sideband specifies the same 20MHz channel that the 80MHz channel is using
+ * as the primary 20MHz channel.
+ */
+extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec)
+{
+	chanspec_t chspec40 = chspec;
+	uint center_chan;
+	uint sb;
+
+	ASSERT(!wf_chspec_malformed(chspec));
+
+	/* if the chanspec is > 80MHz, use the helper routine to find the primary 80 MHz channel */
+	if (CHSPEC_IS8080(chspec) || CHSPEC_IS160(chspec)) {
+		chspec = wf_chspec_primary80_chspec(chspec);
+	}
+
+	/* determine primary 40 MHz sub-channel of an 80 MHz chanspec */
+	if (CHSPEC_IS80(chspec)) {
+		center_chan = CHSPEC_CHANNEL(chspec);
+		sb = CHSPEC_CTL_SB(chspec);
+
+		if (sb < WL_CHANSPEC_CTL_SB_UL) {
+			/* Primary 40MHz is on lower side */
+			center_chan -= CH_20MHZ_APART;
+			/* sideband bits are the same for LL/LU and L/U */
+		} else {
+			/* Primary 40MHz is on upper side */
+			center_chan += CH_20MHZ_APART;
+			/* sideband bits need to be adjusted by UL offset */
+			sb -= WL_CHANSPEC_CTL_SB_UL;
+		}
+
+		/* Create primary 40MHz chanspec */
+		chspec40 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_40 |
+		            sb | center_chan);
+	}
+
+	return chspec40;
+}
+
+/*
+ * Return the channel number for a given frequency and base frequency.
+ * The returned channel number is relative to the given base frequency.
+ * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
+ * frequencies from 5 - 6 GHz, and 2.407 GHz is assumed for 2.4 - 2.5 GHz.
+ *
+ * Frequency is specified in MHz.
+ * The base frequency is specified as (start_factor * 500 kHz).
+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
+ * 2.4 GHz and 5 GHz bands.
+ *
+ * The returned channel will be in the range [1, 14] in the 2.4 GHz band
+ * and [0, 200] otherwise.
+ * -1 is returned if the start_factor is WF_CHAN_FACTOR_2_4_G and the
+ * frequency is not a 2.4 GHz channel, or if the frequency is not and even
+ * multiple of 5 MHz from the base frequency to the base plus 1 GHz.
+ *
+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ */
+int
+wf_mhz2channel(uint freq, uint start_factor)
+{
+	int ch = -1;
+	uint base;
+	int offset;
+
+	/* take the default channel start frequency */
+	if (start_factor == 0) {
+		if (freq >= 2400 && freq <= 2500)
+			start_factor = WF_CHAN_FACTOR_2_4_G;
+		else if (freq >= 5000 && freq <= 6000)
+			start_factor = WF_CHAN_FACTOR_5_G;
+	}
+
+	if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G)
+		return 14;
+
+	base = start_factor / 2;
+
+	/* check that the frequency is in 1GHz range of the base */
+	if ((freq < base) || (freq > base + 1000))
+		return -1;
+
+	offset = freq - base;
+	ch = offset / 5;
+
+	/* check that frequency is a 5MHz multiple from the base */
+	if (offset != (ch * 5))
+		return -1;
+
+	/* restricted channel range check for 2.4G */
+	if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13))
+		return -1;
+
+	return ch;
+}
+
+/*
+ * Return the center frequency in MHz of the given channel and base frequency.
+ * The channel number is interpreted relative to the given base frequency.
+ *
+ * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise.
+ * The base frequency is specified as (start_factor * 500 kHz).
+ * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_4_G, and WF_CHAN_FACTOR_5_G
+ * are defined for 2.4 GHz, 4 GHz, and 5 GHz bands.
+ * The channel range of [1, 14] is only checked for a start_factor of
+ * WF_CHAN_FACTOR_2_4_G (4814 = 2407 * 2).
+ * Odd start_factors produce channels on .5 MHz boundaries, in which case
+ * the answer is rounded down to an integral MHz.
+ * -1 is returned for an out of range channel.
+ *
+ * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
+ */
+int
+wf_channel2mhz(uint ch, uint start_factor)
+{
+	int freq;
+
+	if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) ||
+	    (ch > 200))
+		freq = -1;
+	else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14))
+		freq = 2484;
+	else
+		freq = ch * 5 + start_factor / 2;
+
+	return freq;
+}
+
+static const uint16 sidebands[] = {
+	WL_CHANSPEC_CTL_SB_LLL, WL_CHANSPEC_CTL_SB_LLU,
+	WL_CHANSPEC_CTL_SB_LUL, WL_CHANSPEC_CTL_SB_LUU,
+	WL_CHANSPEC_CTL_SB_ULL, WL_CHANSPEC_CTL_SB_ULU,
+	WL_CHANSPEC_CTL_SB_UUL, WL_CHANSPEC_CTL_SB_UUU
+};
+
+/*
+ * Returns the chanspec 80Mhz channel corresponding to the following input
+ * parameters
+ *
+ *	primary_channel - primary 20Mhz channel
+ *	center_channel   - center frequecny of the 80Mhz channel
+ *
+ * The center_channel can be one of {42, 58, 106, 122, 138, 155}
+ *
+ * returns INVCHANSPEC in case of error
+ */
+chanspec_t
+wf_chspec_80(uint8 center_channel, uint8 primary_channel)
+{
+
+	chanspec_t chanspec = INVCHANSPEC;
+	chanspec_t chanspec_cur;
+	uint i;
+
+	for (i = 0; i < WF_NUM_SIDEBANDS_80MHZ; i++) {
+		chanspec_cur = CH80MHZ_CHSPEC(center_channel, sidebands[i]);
+		if (primary_channel == wf_chspec_ctlchan(chanspec_cur)) {
+			chanspec = chanspec_cur;
+			break;
+		}
+	}
+	/* If the loop ended early, we are good, otherwise we did not
+	* find a 80MHz chanspec with the given center_channel that had a primary channel
+	*matching the given primary_channel.
+	*/
+	return chanspec;
+}
+
+/*
+ * Returns the 80+80 chanspec corresponding to the following input parameters
+ *
+ *    primary_20mhz - Primary 20 MHz channel
+ *    chan0 - center channel number of one frequency segment
+ *    chan1 - center channel number of the other frequency segment
+ *
+ * Parameters chan0 and chan1 are channel numbers in {42, 58, 106, 122, 138, 155}.
+ * The primary channel must be contained in one of the 80MHz channels. This routine
+ * will determine which frequency segment is the primary 80 MHz segment.
+ *
+ * Returns INVCHANSPEC in case of error.
+ *
+ * Refer to IEEE802.11ac section 22.3.14 "Channelization".
+ */
+chanspec_t
+wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan0, uint8 chan1)
+{
+	int sb = 0;
+	uint16 chanspec = 0;
+	int chan0_id = 0, chan1_id = 0;
+	int seg0, seg1;
+
+	chan0_id = channel_80mhz_to_id(chan0);
+	chan1_id = channel_80mhz_to_id(chan1);
+
+	/* make sure the channel numbers were valid */
+	if (chan0_id == -1 || chan1_id == -1)
+		return INVCHANSPEC;
+
+	/* does the primary channel fit with the 1st 80MHz channel ? */
+	sb = channel_to_sb(chan0, primary_20mhz, 80);
+	if (sb >= 0) {
+		/* yes, so chan0 is frequency segment 0, and chan1 is seg 1 */
+		seg0 = chan0_id;
+		seg1 = chan1_id;
+	} else {
+		/* no, so does the primary channel fit with the 2nd 80MHz channel ? */
+		sb = channel_to_sb(chan1, primary_20mhz, 80);
+		if (sb < 0) {
+			/* no match for ctl_ch to either 80MHz center channel */
+			return INVCHANSPEC;
+		}
+		/* swapped, so chan1 is frequency segment 0, and chan0 is seg 1 */
+		seg0 = chan1_id;
+		seg1 = chan0_id;
+	}
+
+	chanspec = ((seg0 << WL_CHANSPEC_CHAN1_SHIFT) |
+	            (seg1 << WL_CHANSPEC_CHAN2_SHIFT) |
+	            (sb << WL_CHANSPEC_CTL_SB_SHIFT) |
+	            WL_CHANSPEC_BW_8080 |
+	            WL_CHANSPEC_BAND_5G);
+
+	return chanspec;
+}
+
+/*
+ * This function returns the 80Mhz channel for the given id.
+ */
+static uint8
+wf_chspec_get80Mhz_ch(uint8 chan_80Mhz_id)
+{
+	if (chan_80Mhz_id < WF_NUM_5G_80M_CHANS)
+		return wf_5g_80m_chans[chan_80Mhz_id];
+
+	return 0;
+}
+
+/*
+ * Returns the primary 80 Mhz channel for the provided chanspec
+ *
+ *    chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved
+ *
+ *  returns -1 in case the provided channel is 20/40 Mhz chanspec
+ */
+
+uint8
+wf_chspec_primary80_channel(chanspec_t chanspec)
+{
+	uint8 primary80_chan;
+
+	if (CHSPEC_IS80(chanspec))	{
+		primary80_chan = CHSPEC_CHANNEL(chanspec);
+	}
+	else if (CHSPEC_IS8080(chanspec)) {
+		/* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */
+		primary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec));
+	}
+	else if (CHSPEC_IS160(chanspec)) {
+		uint8 center_chan = CHSPEC_CHANNEL(chanspec);
+		uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
+
+		/* based on the sb value primary 80 channel can be retrieved
+		 * if sb is in range 0 to 3 the lower band is the 80Mhz primary band
+		 */
+		if (sb < 4) {
+			primary80_chan = center_chan - CH_40MHZ_APART;
+		}
+		/* if sb is in range 4 to 7 the upper band is the 80Mhz primary band */
+		else
+		{
+			primary80_chan = center_chan + CH_40MHZ_APART;
+		}
+	}
+	else {
+		/* for 20 and 40 Mhz */
+		primary80_chan = -1;
+	}
+	return primary80_chan;
+}
+
+/*
+ * Returns the secondary 80 Mhz channel for the provided chanspec
+ *
+ *    chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved
+ *
+ *  returns -1 in case the provided channel is 20/40/80 Mhz chanspec
+ */
+uint8
+wf_chspec_secondary80_channel(chanspec_t chanspec)
+{
+	uint8 secondary80_chan;
+
+	if (CHSPEC_IS8080(chanspec)) {
+		secondary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec));
+	}
+	else if (CHSPEC_IS160(chanspec)) {
+		uint8 center_chan = CHSPEC_CHANNEL(chanspec);
+		uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT;
+
+		/* based on the sb value  secondary 80 channel can be retrieved
+		 * if sb is in range 0 to 3 upper band is the secondary 80Mhz band
+		 */
+		if (sb < 4) {
+			secondary80_chan = center_chan + CH_40MHZ_APART;
+		}
+		/* if sb is in range 4 to 7 the lower band is the secondary 80Mhz band */
+		else
+		{
+			secondary80_chan = center_chan - CH_40MHZ_APART;
+		}
+	}
+	else {
+		/* for 20, 40, and 80 Mhz */
+		secondary80_chan = -1;
+	}
+	return secondary80_chan;
+}
+
+/*
+ * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel.
+ *
+ *    chanspec - Input chanspec for which the primary 80Mhz chanspec has to be retreived
+ *
+ *  returns the input chanspec in case the provided chanspec is an 80 MHz chanspec
+ *  returns INVCHANSPEC in case the provided channel is 20/40 MHz chanspec
+ */
+chanspec_t
+wf_chspec_primary80_chspec(chanspec_t chspec)
+{
+	chanspec_t chspec80;
+	uint center_chan;
+	uint sb;
+
+	ASSERT(!wf_chspec_malformed(chspec));
+	if (CHSPEC_IS80(chspec)) {
+		chspec80 = chspec;
+	}
+	else if (CHSPEC_IS8080(chspec)) {
+		sb = CHSPEC_CTL_SB(chspec);
+		if (sb < WL_CHANSPEC_CTL_SB_ULL) {
+			center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
+		} else {
+			center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chspec));
+			sb &= WL_CHANSPEC_CTL_SB_LUU; /* reduce to 80MHz side band */
+		}
+
+		/* Create primary 80MHz chanspec */
+		chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
+	}
+	else if (CHSPEC_IS160(chspec)) {
+		center_chan = CHSPEC_CHANNEL(chspec);
+		sb = CHSPEC_CTL_SB(chspec);
+
+		if (sb < WL_CHANSPEC_CTL_SB_ULL) {
+			/* Primary 80MHz is on lower side */
+			center_chan -= CH_40MHZ_APART;
+		}
+		else {
+			/* Primary 80MHz is on upper side */
+			center_chan += CH_40MHZ_APART;
+			sb -= WL_CHANSPEC_CTL_SB_ULL;
+		}
+		/* Create primary 80MHz chanspec */
+		chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan);
+	}
+	else {
+		chspec80 = INVCHANSPEC;
+	}
+
+	return chspec80;
+}
+
+/*
+ * For 160MHz or 80P80 chanspec, set ch[0]/ch[1] to be the low/high 80 Mhz channels
+ *
+ * For 20/40/80MHz chanspec, set ch[0] to be the center freq, and chan[1]=-1
+ */
+void
+wf_chspec_get_80p80_channels(chanspec_t chspec, uint8 *ch)
+{
+
+	if (CHSPEC_IS8080(chspec)) {
+		ch[0] = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec));
+		ch[1] = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chspec));
+	}
+	else if (CHSPEC_IS160(chspec)) {
+		uint8 center_chan = CHSPEC_CHANNEL(chspec);
+		ch[0] = center_chan - CH_40MHZ_APART;
+		ch[1] = center_chan + CH_40MHZ_APART;
+	}
+	else {
+		/* for 20, 40, and 80 Mhz */
+		ch[0] = CHSPEC_CHANNEL(chspec);
+		ch[1] = -1;
+	}
+	return;
+
+}
+
+#ifdef WL11AC_80P80
+uint8
+wf_chspec_channel(chanspec_t chspec)
+{
+	if (CHSPEC_IS8080(chspec)) {
+		return wf_chspec_primary80_channel(chspec);
+	}
+	else {
+		return ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK));
+	}
+}
+#endif /* WL11AC_80P80 */
+
+/* This routine returns the chanspec for a given operating class and
+ * channel number
+ */
+chanspec_t
+wf_channel_create_chspec_frm_opclass(uint8 opclass, uint8 channel)
+{
+	chanspec_t chanspec = 0;
+	uint16 opclass_info = 0;
+	uint16 lookupindex = 0;
+	switch (opclass) {
+		case 115:
+			lookupindex = 1;
+			break;
+		case 124:
+			lookupindex = 3;
+			break;
+		case 125:
+			lookupindex = 5;
+			break;
+		case 81:
+			lookupindex = 12;
+			break;
+		case 116:
+			lookupindex = 22;
+			break;
+		case 119:
+			lookupindex = 23;
+			break;
+		case 126:
+			lookupindex = 25;
+			break;
+		case 83:
+			lookupindex = 32;
+			break;
+		case 84:
+			lookupindex = 33;
+			break;
+		default:
+			lookupindex = 12;
+	}
+
+	if (lookupindex < 33) {
+		opclass_info = opclass_data[lookupindex-1];
+	}
+	else {
+		opclass_info = opclass_data[11];
+	}
+	chanspec = opclass_info | (uint16)channel;
+	return chanspec;
+}
+
+/* This routine returns the opclass for a given chanspec */
+int
+wf_channel_create_opclass_frm_chspec(chanspec_t chspec)
+{
+	BCM_REFERENCE(chspec);
+	/* TODO: Implement this function ! */
+	return 12; /* opclass 12 for basic 2G channels */
+}
+
+/* Populates array with all 20MHz side bands of a given chanspec_t in the following order:
+ *		control, ext20, two ext40s, four ext80s.
+ *    'chspec' is the chanspec of interest
+ *    'pext' must point to an uint8 array of long enough to hold all side bands of the given chspec
+ *
+ * Works with 20, 40, 80, 80p80 and 160MHz chspec
+ */
+void
+wf_get_all_ext(chanspec_t chspec, uint8 *pext)
+{
+#ifdef WL11N_20MHZONLY
+	GET_ALL_SB(chspec, pext);
+#else /* !WL11N_20MHZONLY */
+	chanspec_t t = (CHSPEC_IS160(chspec) || CHSPEC_IS8080(chspec)) ? /* if bw > 80MHz */
+	wf_chspec_primary80_chspec(chspec) : (chspec); /* extract primary 80 */
+	/* control channel as first element */
+	uint8 ctl_ch = (pext)[0] = wf_chspec_ctlchan(t);
+	if (CHSPEC_ISLE20(chspec)) return; /* nothing more to do since 20MHz chspec */
+	/* 20MHz EXT */
+	(pext)[1] = ctl_ch + (IS_CTL_IN_L20(t) ? CH_20MHZ_APART : -CH_20MHZ_APART);
+	if (CHSPEC_IS40(chspec)) return; /* nothing more to do since 40MHz chspec */
+	/* center 40MHz EXT */
+	t = wf_channel2chspec(ctl_ch + (IS_CTL_IN_L40(chspec) ?
+		CH_40MHZ_APART : -CH_40MHZ_APART), WL_CHANSPEC_BW_40);
+	GET_ALL_SB(t, &((pext)[2])); /* get the 20MHz side bands in 40MHz EXT */
+	if (CHSPEC_IS80(chspec)) return; /* nothing more to do since 80MHz chspec */
+	t = CH80MHZ_CHSPEC(wf_chspec_secondary80_channel(chspec), WL_CHANSPEC_CTL_SB_LLL);
+	/* get the 20MHz side bands in 80MHz EXT (secondary) */
+	GET_ALL_SB(t, &((pext)[4]));
+#endif /* !WL11N_20MHZONLY */
+}
diff --git a/wl/src/shared/bcmxtlv.c b/wl/src/shared/bcmxtlv.c
new file mode 100644
index 0000000..9f6e91a
--- /dev/null
+++ b/wl/src/shared/bcmxtlv.c
@@ -0,0 +1,610 @@
+/*
+ * Driver O/S-independent utility routines
+ *
+ * Copyright (C) 2017, Broadcom. 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: bcmxtlv.c 635987 2016-05-06 01:49:37Z $
+ */
+
+#ifndef __FreeBSD__
+#include <bcm_cfg.h>
+#endif
+
+#include <typedefs.h>
+#include <bcmdefs.h>
+
+#if defined(__FreeBSD__)
+#include <machine/stdarg.h>
+#else
+#include <stdarg.h>
+#endif /* __FreeBSD__ */
+
+#ifdef BCMDRIVER
+#include <osl.h>
+#else /* !BCMDRIVER */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifndef ASSERT
+#define ASSERT(exp)
+#endif
+#endif /* !BCMDRIVER */
+
+#include <bcmtlv.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+
+int
+bcm_xtlv_hdr_size(bcm_xtlv_opts_t opts)
+{
+	int len = (int)OFFSETOF(bcm_xtlv_t, data); /* nominal */
+	if (opts & BCM_XTLV_OPTION_LENU8) --len;
+	if (opts & BCM_XTLV_OPTION_IDU8) --len;
+
+	return len;
+}
+
+bool
+bcm_valid_xtlv(const bcm_xtlv_t *elt, int buf_len, bcm_xtlv_opts_t opts)
+{
+	return elt != NULL &&
+		buf_len >= bcm_xtlv_hdr_size(opts) &&
+		buf_len  >= bcm_xtlv_size(elt, opts);
+}
+
+int
+bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts)
+{
+	int hsz;
+
+	hsz = bcm_xtlv_hdr_size(opts);
+	return ((opts & BCM_XTLV_OPTION_ALIGN32) ? ALIGN_SIZE(dlen + hsz, 4)
+		: (dlen + hsz));
+}
+
+int
+bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
+{
+	int size;	/* size including header, data, and any pad */
+	int len;	/* length wthout padding */
+
+	len = BCM_XTLV_LEN_EX(elt, opts);
+	size = bcm_xtlv_size_for_data(len, opts);
+	return size;
+}
+
+int
+bcm_xtlv_len(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
+{
+	const uint8 *lenp;
+	int len;
+
+	lenp = (const uint8 *)&elt->len; /* nominal */
+	if (opts & BCM_XTLV_OPTION_IDU8) --lenp;
+
+	if (opts & BCM_XTLV_OPTION_LENU8)
+		len = *lenp;
+	else
+		len = ltoh16_ua(lenp);
+
+	return len;
+}
+
+int
+bcm_xtlv_id(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts)
+{
+	int id = 0;
+	if (opts & BCM_XTLV_OPTION_IDU8)
+		id =  *(const uint8 *)elt;
+	else
+		id = ltoh16_ua((const uint8 *)elt);
+
+	return id;
+}
+
+bcm_xtlv_t *
+bcm_next_xtlv(bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts)
+{
+	int sz;
+#ifdef BCMDBG
+	/* validate current elt */
+	if (!bcm_valid_xtlv(elt, *buflen, opts))
+		return NULL;
+#endif
+	/* advance to next elt */
+	sz = BCM_XTLV_SIZE_EX(elt, opts);
+	elt = (bcm_xtlv_t*)((uint8 *)elt + sz);
+	*buflen -= sz;
+
+	/* validate next elt */
+	if (!bcm_valid_xtlv(elt, *buflen, opts))
+		return NULL;
+
+	return elt;
+}
+
+int
+bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len, bcm_xtlv_opts_t opts)
+{
+	if (!tlv_buf || !buf || !len)
+		return BCME_BADARG;
+
+	tlv_buf->opts = opts;
+	tlv_buf->size = len;
+	tlv_buf->head = buf;
+	tlv_buf->buf  = buf;
+	return BCME_OK;
+}
+
+uint16
+bcm_xtlv_buf_len(bcm_xtlvbuf_t *tbuf)
+{
+	uint16 len;
+
+	if (tbuf)
+		len = (uint16)(tbuf->buf - tbuf->head);
+	else
+		len = 0;
+
+	return len;
+}
+
+uint16
+bcm_xtlv_buf_rlen(bcm_xtlvbuf_t *tbuf)
+{
+	uint16 rlen;
+	if (tbuf)
+		rlen = tbuf->size - bcm_xtlv_buf_len(tbuf);
+	else
+		rlen = 0;
+
+	return rlen;
+}
+
+uint8 *
+bcm_xtlv_buf(bcm_xtlvbuf_t *tbuf)
+{
+	return tbuf ? tbuf->buf : NULL;
+}
+
+uint8 *
+bcm_xtlv_head(bcm_xtlvbuf_t *tbuf)
+{
+	return tbuf ? tbuf->head : NULL;
+}
+
+void
+bcm_xtlv_pack_xtlv(bcm_xtlv_t *xtlv, uint16 type, uint16 len, const uint8 *data,
+	bcm_xtlv_opts_t opts)
+{
+	uint8 *data_buf;
+	bcm_xtlv_opts_t mask = BCM_XTLV_OPTION_IDU8 | BCM_XTLV_OPTION_LENU8;
+
+	if (!(opts & mask)) {		/* default */
+		uint8 *idp = (uint8 *)xtlv;
+		uint8 *lenp = idp + sizeof(xtlv->id);
+		htol16_ua_store(type, idp);
+		htol16_ua_store(len, lenp);
+		data_buf = lenp + sizeof(uint16);
+	} else if ((opts & mask) == mask) { /* u8 id and u8 len */
+		uint8 *idp = (uint8 *)xtlv;
+		uint8 *lenp = idp + 1;
+		*idp = (uint8)type;
+		*lenp = (uint8)len;
+		data_buf = lenp + sizeof(uint8);
+	} else if (opts & BCM_XTLV_OPTION_IDU8) { /* u8 id, u16 len */
+		uint8 *idp = (uint8 *)xtlv;
+		uint8 *lenp = idp + 1;
+		*idp = (uint8)type;
+		htol16_ua_store(len, lenp);
+		data_buf = lenp + sizeof(uint16);
+	} else if (opts & BCM_XTLV_OPTION_LENU8) { /* u16 id, u8 len */
+		uint8 *idp = (uint8 *)xtlv;
+		uint8 *lenp = idp + sizeof(uint16);
+		htol16_ua_store(type, idp);
+		*lenp = (uint8)len;
+		data_buf = lenp + sizeof(uint8);
+	} else {
+		ASSERT(!"Unexpected xtlv option");
+		return;
+	}
+
+	if (opts & BCM_XTLV_OPTION_LENU8) {
+		ASSERT(len <= 0x00ff);
+		len &= 0xff;
+	}
+
+	if (data != NULL)
+		memcpy(data_buf, data, len);
+}
+
+/* xtlv header is always packed in LE order */
+void
+bcm_xtlv_unpack_xtlv(const bcm_xtlv_t *xtlv, uint16 *type, uint16 *len,
+	const uint8 **data, bcm_xtlv_opts_t opts)
+{
+	if (type)
+		*type = (uint16)bcm_xtlv_id(xtlv, opts);
+	if (len)
+		*len = (uint16)bcm_xtlv_len(xtlv, opts);
+	if (data)
+		*data = (const uint8 *)xtlv + BCM_XTLV_HDR_SIZE_EX(opts);
+}
+
+int
+bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n)
+{
+	bcm_xtlv_t *xtlv;
+	int size;
+
+	if (tbuf == NULL)
+		return BCME_BADARG;
+
+	size = bcm_xtlv_size_for_data(n, tbuf->opts);
+	if (bcm_xtlv_buf_rlen(tbuf) < size)
+		return BCME_NOMEM;
+
+	xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
+	bcm_xtlv_pack_xtlv(xtlv, type, (uint16)n, data, tbuf->opts);
+	tbuf->buf += size; /* note: data may be NULL, reserves space */
+	return BCME_OK;
+}
+
+static int
+bcm_xtlv_put_int(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n, int int_sz)
+{
+	bcm_xtlv_t *xtlv;
+	int xtlv_len;
+	uint8 *xtlv_data;
+	int err = BCME_OK;
+
+	if (tbuf == NULL) {
+		err = BCME_BADARG;
+		goto done;
+	}
+
+	xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf);
+
+	/* put type and length in xtlv and reserve data space */
+	xtlv_len = n * int_sz;
+	err = bcm_xtlv_put_data(tbuf, type, NULL, xtlv_len);
+	if (err != BCME_OK)
+		goto done;
+
+	xtlv_data = (uint8 *)xtlv + bcm_xtlv_hdr_size(tbuf->opts);
+
+	/* write data w/ little-endianness into buffer - single loop, aligned access */
+	for (; n != 0; --n, xtlv_data += int_sz, data += int_sz) {
+		switch (int_sz) {
+		case sizeof(uint8):
+			break;
+		case sizeof(uint16):
+			{
+				uint16 v =  load16_ua(data);
+				htol16_ua_store(v, xtlv_data);
+				break;
+			}
+		case sizeof(uint32):
+			{
+				uint32 v = load32_ua(data);
+				htol32_ua_store(v, xtlv_data);
+				break;
+			}
+		case sizeof(uint64):
+			{
+				uint64 v = load64_ua(data);
+				htol64_ua_store(v, xtlv_data);
+				break;
+			}
+		default:
+			err = BCME_UNSUPPORTED;
+			goto done;
+		}
+	}
+
+done:
+	return err;
+}
+
+int
+bcm_xtlv_put16(bcm_xtlvbuf_t *tbuf, uint16 type, const uint16 *data, int n)
+{
+	return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint16));
+}
+
+int
+bcm_xtlv_put32(bcm_xtlvbuf_t *tbuf, uint16 type, const uint32 *data, int n)
+{
+	return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint32));
+}
+
+int
+bcm_xtlv_put64(bcm_xtlvbuf_t *tbuf, uint16 type, const uint64 *data, int n)
+{
+	return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint64));
+}
+
+/*
+ *  upacks xtlv record from buf checks the type
+ *  copies data to callers buffer
+ *  advances tlv pointer to next record
+ *  caller's resposible for dst space check
+ */
+int
+bcm_unpack_xtlv_entry(uint8 **tlv_buf, uint16 xpct_type, uint16 xpct_len,
+	uint8 *dst_data, bcm_xtlv_opts_t opts)
+{
+	bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf;
+	uint16 len;
+	uint16 type;
+	const uint8 *data;
+
+	ASSERT(ptlv);
+
+	bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts);
+	if (len) {
+		if ((type != xpct_type) || (len > xpct_len))
+			return BCME_BADARG;
+		if (dst_data && data)
+			memcpy(dst_data, data, len); /* copy data to dst */
+	}
+
+	*tlv_buf += BCM_XTLV_SIZE_EX(ptlv, opts);
+	return BCME_OK;
+}
+
+/*
+ *  packs user data into tlv record and advances tlv pointer to next xtlv slot
+ *  buflen is used for tlv_buf space check
+ */
+int
+bcm_pack_xtlv_entry(uint8 **tlv_buf, uint16 *buflen, uint16 type, uint16 len,
+	const uint8 *src_data, bcm_xtlv_opts_t opts)
+{
+	bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf;
+	int size;
+
+	ASSERT(ptlv);
+
+	size = bcm_xtlv_size_for_data(len, opts);
+
+	/* copy data from tlv buffer to dst provided by user */
+	if (size > *buflen)
+		return BCME_BADLEN;
+
+	bcm_xtlv_pack_xtlv(ptlv, type, len, src_data, opts);
+
+	/* advance callers pointer to tlv buff */
+	*tlv_buf = (uint8*)(*tlv_buf) + size;
+	/* decrement the len */
+	*buflen -= (uint16)size;
+	return BCME_OK;
+}
+
+/*
+ *  unpack all xtlv records from the issue a callback
+ *  to set function one call per found tlv record
+ */
+int
+bcm_unpack_xtlv_buf(void *ctx, const uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
+	bcm_xtlv_unpack_cbfn_t *cbfn)
+{
+	uint16 len;
+	uint16 type;
+	int res = BCME_OK;
+	int size;
+	const bcm_xtlv_t *ptlv;
+	int sbuflen = buflen;
+	const uint8 *data;
+	int hdr_size;
+
+	ASSERT(!buflen || tlv_buf);
+	ASSERT(!buflen || cbfn);
+
+	hdr_size = BCM_XTLV_HDR_SIZE_EX(opts);
+	while (sbuflen >= hdr_size) {
+		ptlv = (const bcm_xtlv_t *)tlv_buf;
+
+		bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts);
+		size = bcm_xtlv_size_for_data(len, opts);
+
+		sbuflen -= size;
+		if (sbuflen < 0) /* check for buffer overrun */
+			break;
+
+		if ((res = cbfn(ctx, data, type, len)) != BCME_OK)
+			break;
+		tlv_buf += size;
+	}
+	return res;
+}
+
+int
+bcm_pack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts,
+	bcm_pack_xtlv_next_info_cbfn_t get_next, bcm_pack_xtlv_pack_next_cbfn_t pack_next,
+	int *outlen)
+{
+	int res = BCME_OK;
+	uint16 tlv_id;
+	uint16 tlv_len;
+	uint8 *startp;
+	uint8 *endp;
+	uint8 *buf;
+	bool more;
+	int size;
+	int hdr_size;
+
+	ASSERT(get_next && pack_next);
+
+	buf = tlv_buf;
+	startp = buf;
+	endp = (uint8 *)buf + buflen;
+	more = TRUE;
+	hdr_size = BCM_XTLV_HDR_SIZE_EX(opts);
+
+	while (more && (buf < endp)) {
+		more = get_next(ctx, &tlv_id, &tlv_len);
+		size = bcm_xtlv_size_for_data(tlv_len, opts);
+		if ((buf + size) > endp) {
+			res = BCME_BUFTOOSHORT;
+			goto done;
+		}
+
+		bcm_xtlv_pack_xtlv((bcm_xtlv_t *)buf, tlv_id, tlv_len, NULL, opts);
+		pack_next(ctx, tlv_id, tlv_len, buf + hdr_size);
+		buf += size;
+	}
+
+	if (more)
+		res = BCME_BUFTOOSHORT;
+
+done:
+	if (outlen) {
+		*outlen = (int)(buf - startp);
+	}
+	return res;
+}
+
+/*
+ *  pack xtlv buffer from memory according to xtlv_desc_t
+ */
+int
+bcm_pack_xtlv_buf_from_mem(uint8 **tlv_buf, uint16 *buflen, const xtlv_desc_t *items,
+	bcm_xtlv_opts_t opts)
+{
+	int res = BCME_OK;
+	uint8 *ptlv = *tlv_buf;
+
+	while (items->type != 0) {
+		if (items->len && items->ptr) {
+			res = bcm_pack_xtlv_entry(&ptlv, buflen, items->type,
+				items->len, items->ptr, opts);
+			if (res != BCME_OK)
+				break;
+		}
+		items++;
+	}
+
+	*tlv_buf = ptlv; /* update the external pointer */
+	return res;
+}
+
+/*
+ *  unpack xtlv buffer to memory according to xtlv_desc_t
+ *
+ */
+int
+bcm_unpack_xtlv_buf_to_mem(uint8 *tlv_buf, int *buflen, xtlv_desc_t *items,
+	bcm_xtlv_opts_t opts)
+{
+	int res = BCME_OK;
+	bcm_xtlv_t *elt;
+
+	elt =  bcm_valid_xtlv((bcm_xtlv_t *)tlv_buf, *buflen, opts) ? (bcm_xtlv_t *)tlv_buf : NULL;
+	if (!elt || !items) {
+		res = BCME_BADARG;
+		return res;
+	}
+
+	for (; elt != NULL && res == BCME_OK; elt = bcm_next_xtlv(elt, buflen, opts)) {
+		/*  find matches in desc_t items  */
+		xtlv_desc_t *dst_desc = items;
+		uint16 len, type;
+		const uint8 *data;
+
+		bcm_xtlv_unpack_xtlv(elt, &type, &len, &data, opts);
+		while (dst_desc->type != 0) {
+			if (type == dst_desc->type) {
+				if (len != dst_desc->len) {
+					res = BCME_BADLEN;
+				} else {
+					memcpy(dst_desc->ptr, data, len);
+				}
+				break;
+			}
+			dst_desc++;
+		}
+	}
+
+	if (res == BCME_OK && *buflen != 0)
+		res =  BCME_BUFTOOSHORT;
+
+	return res;
+}
+
+/*
+ * return data pointer of a given ID from xtlv buffer.
+ * If the specified xTLV ID is found, on return *datalen will contain
+ * the the data length of the xTLV ID.
+ */
+const uint8*
+bcm_get_data_from_xtlv_buf(const uint8 *tlv_buf, uint16 buflen, uint16 id,
+	uint16 *datalen, bcm_xtlv_opts_t opts)
+{
+	const uint8 *retptr = NULL;
+	uint16 type, len;
+	int size;
+	const bcm_xtlv_t *ptlv;
+	int sbuflen = buflen;
+	const uint8 *data;
+	int hdr_size;
+
+	hdr_size = BCM_XTLV_HDR_SIZE_EX(opts);
+	while (sbuflen >= hdr_size) {
+		ptlv = (const bcm_xtlv_t *)tlv_buf;
+		bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts);
+
+		size = bcm_xtlv_size_for_data(len, opts);
+		sbuflen -= size;
+		if (sbuflen < 0) /* buffer overrun? */
+			break;
+
+		if (id == type) {
+			retptr = data;
+			if (datalen)
+				*datalen = len;
+			break;
+		}
+
+		tlv_buf += size;
+	}
+
+	return retptr;
+}
+
+bcm_xtlv_t*
+bcm_xtlv_bcopy(const bcm_xtlv_t *src, bcm_xtlv_t *dst,
+	int src_buf_len, int dst_buf_len, bcm_xtlv_opts_t opts)
+{
+	bcm_xtlv_t *dst_next = NULL;
+	src =  (src && bcm_valid_xtlv(src, src_buf_len, opts)) ? src : NULL;
+	if (src && dst) {
+		uint16 type;
+		uint16 len;
+		const uint8 *data;
+		int size;
+		bcm_xtlv_unpack_xtlv(src, &type, &len, &data, opts);
+		size = bcm_xtlv_size_for_data(len, opts);
+		if (size <= dst_buf_len) {
+			bcm_xtlv_pack_xtlv(dst, type, len, data, opts);
+			dst_next = (bcm_xtlv_t *)((uint8 *)dst + size);
+		}
+	}
+
+	return dst_next;
+}
diff --git a/wl/src/shared/miniopt.c b/wl/src/shared/miniopt.c
new file mode 100644
index 0000000..9a81751
--- /dev/null
+++ b/wl/src/shared/miniopt.c
@@ -0,0 +1,161 @@
+/*
+ * Description.
+ *
+ * Copyright (C) 2017, Broadcom. 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: miniopt.c 514727 2014-11-12 03:02:48Z $
+ */
+
+/* ---- Include Files ---------------------------------------------------- */
+
+#include <typedefs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <miniopt.h>
+
+
+/* ---- Public Variables ------------------------------------------------- */
+/* ---- Private Constants and Types -------------------------------------- */
+
+
+
+/* ---- Private Variables ------------------------------------------------ */
+/* ---- Private Function Prototypes -------------------------------------- */
+/* ---- Functions -------------------------------------------------------- */
+
+/* ----------------------------------------------------------------------- */
+void
+miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags)
+{
+	static const char *null_flags = "";
+
+	memset(t, 0, sizeof(miniopt_t));
+	t->name = name;
+	if (flags == NULL)
+		t->flags = null_flags;
+	else
+		t->flags = flags;
+	t->longflags = longflags;
+}
+
+
+/* ----------------------------------------------------------------------- */
+int
+miniopt(miniopt_t *t, char **argv)
+{
+	int keylen;
+	char *p, *eq, *valstr, *endptr = NULL;
+	int err = 0;
+
+	t->consumed = 0;
+	t->positional = FALSE;
+	memset(t->key, 0, MINIOPT_MAXKEY);
+	t->opt = '\0';
+	t->valstr = NULL;
+	t->good_int = FALSE;
+	valstr = NULL;
+
+	if (*argv == NULL) {
+		err = -1;
+		goto exit;
+	}
+
+	p = *argv++;
+	t->consumed++;
+
+	if (!t->opt_end && !strcmp(p, "--")) {
+		t->opt_end = TRUE;
+		if (*argv == NULL) {
+			err = -1;
+			goto exit;
+		}
+		p = *argv++;
+		t->consumed++;
+	}
+
+	if (t->opt_end) {
+		t->positional = TRUE;
+		valstr = p;
+	}
+	else if (!strncmp(p, "--", 2)) {
+		eq = strchr(p, '=');
+		if (eq == NULL && !t->longflags) {
+			fprintf(stderr,
+				"%s: missing \" = \" in long param \"%s\"\n", t->name, p);
+			err = 1;
+			goto exit;
+		}
+		keylen = eq ? (int)(eq - (p + 2)) : (int)strlen(p) - 2;
+		if (keylen > 63) keylen = 63;
+		memcpy(t->key, p + 2, keylen);
+
+		if (eq) {
+			valstr = eq + 1;
+			if (*valstr == '\0') {
+				fprintf(stderr,
+				        "%s: missing value after \" = \" in long param \"%s\"\n",
+				        t->name, p);
+				err = 1;
+				goto exit;
+			}
+		}
+	}
+	else if (!strncmp(p, "-", 1)) {
+		t->opt = p[1];
+		if (strlen(p) > 2) {
+			fprintf(stderr,
+				"%s: only single char options, error on param \"%s\"\n",
+				t->name, p);
+			err = 1;
+			goto exit;
+		}
+		if (strchr(t->flags, t->opt)) {
+			/* this is a flag option, no value expected */
+			valstr = NULL;
+		} else {
+			if (*argv == NULL) {
+				fprintf(stderr,
+				"%s: missing value parameter after \"%s\"\n", t->name, p);
+				err = 1;
+				goto exit;
+			}
+			valstr = *argv;
+			argv++;
+			t->consumed++;
+		}
+	} else {
+		t->positional = TRUE;
+		valstr = p;
+	}
+
+	/* parse valstr as int just in case */
+	if (valstr) {
+		t->uval = (uint)strtoul(valstr, &endptr, 0);
+		t->val = (int)t->uval;
+		t->good_int = (*endptr == '\0');
+	}
+
+	t->valstr = valstr;
+
+exit:
+	if (err == 1)
+		t->opt = '?';
+
+	return err;
+}
diff --git a/wl/src/tools/release/WLAN.usf b/wl/src/tools/release/WLAN.usf
new file mode 100644
index 0000000..681d66a
--- /dev/null
+++ b/wl/src/tools/release/WLAN.usf
@@ -0,0 +1,57 @@
+#
+# This is a common config file that is used mainly by modules
+# or brand makefiles. The ".usf" suffix stands for "universal
+# settings file". The important feature is that this file is
+# both legal makefile and shell syntax, and could be parsed as
+# a properties file by any language (Perl, Python, Java, ...)
+# which understands properties.
+#
+# Rules: Each line is either an assignment, a comment, or blank.
+# Assignments MUST be of the form "foo=bar" (no spaces) and
+# comments have a leading "#" character.
+#
+# It can be included by common templates like WLAN_Common.mk,
+# or by brand makefiles, or sourced by build scripts.
+#
+# Copyright (C) 2017, Broadcom. 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: WLAN.usf 658442 2016-09-08 01:17:56Z $
+#
+
+# Current list of components
+# This list is used in module makefiles to set vpath search
+# paths and include paths
+
+WLAN_COMPONENT_PATHS=src/shared/bcmwifi components/clm-api src/wl/lwip src/wl/ppr \
+                     src/wl/rel_mcast src/wl/gas src/wl/encode src/wl/olpc \
+		     src/wl/keymgmt src/wl/iocv src/wl/dump \
+		     components/ndis src/wl/proxd src/dongle src/rte \
+		     components/nan src/wl/ate src/wl/mesh src/wl/randmac \
+		     components/phy src/wl/natoe components/accel components/avs \
+		     components/msch components/apf components/hml src/wl/chctx
+
+# This is a staging area for generated content that need to be shared
+# between build step and packaging step. E.g when CLM data files
+# need to be packaged, they are first staged to $(WLAN_GEN_BASEDIR)
+# and packaged from there.
+
+WLAN_GEN_BASEDIR=generated
+
+# This is the conventional Windows mount point for network files.
+
+WLAN_WINPFX=Z:
diff --git a/wl/src/wl/exe/GNUmakefile b/wl/src/wl/exe/GNUmakefile
new file mode 100644
index 0000000..4f04ce9
--- /dev/null
+++ b/wl/src/wl/exe/GNUmakefile
@@ -0,0 +1,814 @@
+#
+# GNUmakefile for wl/exe
+#
+#  Broadcom Proprietary and Confidential. Copyright (C) 2017,
+#  All Rights Reserved.
+#  
+#  This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+#  the contents of this file may not be disclosed to third parties, copied
+#  or duplicated in any form, in whole or in part, without the prior
+#  written permission of Broadcom.
+#
+#
+#  <<Broadcom-WL-IPTag/Proprietary:>>
+#
+# $Id: GNUmakefile 663904 2017-02-16 07:26:50Z $
+
+WLAN_ComponentsInUse := bcmwifi ppr
+ifeq ($(CONFIG_WLEXE),y)
+    SRCBASE := $(WLAN_SrcBaseR)
+    export WLAN_TreeBaseA=$(abspath ../../..)
+endif
+include ../../makefiles/WLAN_Common.mk
+
+ifndef	SRCBASE
+    SRCBASE := $(WLAN_SrcBaseR)
+endif
+
+UNAME = $(shell uname)
+
+ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
+
+#-----------------------------------------------------------------
+# Windows build, don't include Makerules due to all: conflict
+
+include ../../GNUmakefile.inc
+
+# MfgTest XP and WIN7 WLU DLL builds are built from other standalone Makefiles
+# from App and MfgTest teams
+# To build XP WLU DLL (output is in windows/winxp/obj/*/mfg_dll/{free,checked}/...)
+#    $(MAKE) -C src/wl/exe -f GNUmakefile.wlu_dll
+# To build Win7/Vista WLU DLL (output is in windows/win7/obj/*/mfg_dll/{Release,Debug}/...)
+#    $(MAKE) -C src/wl/exe/win7
+
+else # UNAME
+
+#-----------------------------------------------------------------
+# Linux build
+#
+
+# This should be one of values recognized in src/Makerules
+# 2) not windows, need to include first to pick up TARGETENV dependent vars
+include $(SRCBASE)/Makerules
+
+# GNU make function to do compilation and dependency generation
+# in one step.
+define CompileAndMakedep
+$(strip $1 -c -MMD -MF $(@D)/.$(@F).depend -MP $2)
+endef
+
+ifeq ($(CONFIG_WLEXE),y)
+  CFLAGS += -fno-strict-aliasing -O2 -s
+endif
+
+
+# Use newer 11ac ratespec for wl command line
+CFLAGS += -DD11AC_IOTYPES
+
+# Use opaque PPR structures
+CFLAGS += -DPPR_API
+
+#ifdef SR_DEBUG
+CFLAGS += -DSR_DEBUG
+#endif
+
+#ifdef WLCNT
+  CFLAGS += -DWLCNT
+#endif
+
+#ifdef WIFI_ACT_FRAME
+  CFLAGS += -DWIFI_ACT_FRAME
+#endif
+
+#ifdef WLEXTLOG
+  CFLAGS += -DWLEXTLOG
+#endif
+
+ifeq ($(WLTEST),1)
+    CFLAGS += -DSERDOWNLOAD
+    CFLAGS += -DWLTEST
+endif
+
+ifeq ($(PCIE_MFGTEST),1)
+    CFLAGS += -DPCIE_MFGTEST
+endif
+
+ifeq ($(OLYMPIC_RWL),1)
+    CFLAGS += -DOLYMPIC_RWL
+endif
+
+
+ifneq ($(findstring $(TARGETENV), "linux linuxmips linuxmips_be linuxarm linuxarm_le android android_ndk_r6b freebsd freebsd_be"),)
+
+#ifdef WLP2P
+  CFLAGS += -DWLP2P
+#endif
+
+#ifdef WLMCHAN
+  CFLAGS += -DWLMCHAN
+#endif
+
+#ifdef WLTDLS
+ CFLAGS += -DWLTDLS
+#endif
+
+#ifdef WLNDOE
+  CFLAGS += -DWLNDOE
+#endif
+
+#ifdef WLP2PO
+  CFLAGS += -DWLP2PO
+#endif
+
+#ifdef WLANQPO
+  CFLAGS += -DWLANQPO
+#endif
+
+#ifdef WLBDO
+  CFLAGS += -DWLBDO
+#endif
+
+#ifdef WLTKO
+  CFLAGS += -DWLTKO
+#endif
+
+#ifdef TRAFFIC_MGMT
+  CFLAGS += -DTRAFFIC_MGMT
+#endif
+
+#ifdef WL_PROXDETECT
+  CFLAGS += -DWL_PROXDETECT
+#endif
+
+#ifdef WL_RANDMAC
+  CFLAGS += -DWL_RANDMAC
+#endif
+
+#ifdef WL_MSCH
+  CFLAGS += -DWL_MSCH
+#endif
+
+#ifdef WL11ULB
+  CFLAGS += -DWL11ULB
+#endif
+
+# netlink driver interface
+ifeq ($(NL80211),1)
+  CFLAGS += -DNL80211
+endif
+
+#ifeq ($(tbow),1)
+  CFLAGS += -DBT_WIFI_HANDOVER
+#endif
+
+#ifdef WLWNM
+ CFLAGS += -DWLWNM
+#endif
+
+#if defined(WLBSSLOAD_REPORT)
+ CFLAGS += -DWLBSSLOAD_REPORT
+#endif
+
+#ifdef WL_NAN
+CFLAGS += -DWL_NAN
+#endif
+
+#ifdef WLRSDB
+CFLAGS += -DWLRSDB
+#endif
+
+#ifdef WL_NATOE
+CFLAGS += -DWL_NATOE
+#endif
+
+#ifdef WL_BTCDYN
+ CFLAGS += -DWL_BTCDYN
+#endif
+
+#ifdef WL_MPF
+CFLAGS += -DWL_MPF
+#endif
+
+#ifdef WLRCC
+CFLAGS += -DWLRCC
+#endif
+#ifdef WL_MBO
+CFLAGS += -DWL_MBO
+#endif
+#ifdef WL_MBO_WFA_CERT
+CFLAGS += -DWL_MBO_WFA_CERT
+#endif
+
+
+#ifdef ECOUNTERS
+  CFLAGS += -DECOUNTERS
+#endif
+
+CFLAGS += -DTBTT_OFFSET_STAT
+
+# extra warnings
+ifneq ($(filter mips_be arm_le arm_android arm_android_ndk_r6b arm64_android,$(TARGETARCH)),)
+CFLAGS += -Wextra -Wall
+else
+CFLAGS += -Wextra -Wall -Werror
+endif
+CFLAGS += -DWLPFN -DWLPFN_AUTO_CONNECT
+
+# Avoid compilation error of unused value warning in open source sha256
+ifneq ($(findstring WL_NAN, $(CFLAGS)),)
+CFLAGS += -Wno-error="unused-value"
+endif
+
+ifneq (,$(findstring freebsd, $(TARGETENV)))
+        # To do cross compilation on linux,
+        #     - Define the env CROSS_COMPILE pointing to the cross compile tool dir
+        #     - Define the env FREEBSD_DIR pointing to the FreeBSD source directory
+        # To do local compilation on a FreeBSD machine, do not set CROSS_COMPILE or FREEBSD_DIR
+	CC := $(CROSS_COMPILE)gcc
+	LD := $(CROSS_COMPILE)ld
+	NM := $(CROSS_COMPILE)nm
+	OBJCOPY := $(CROSS_COMPILE)objcopy
+	ifneq (,$(findstring freebsd_be, $(TARGETENV)))
+		CFLAGS += -DIL_BIGENDIAN
+	endif
+else
+	CFLAGS += -DLINUX
+endif
+CFLAGS += -I$(SRCBASE)/wl/sys
+CFLAGS += $(WLAN_ComponentIncPathR)
+
+# Discard any "MMX" or other qualifications on x86 so that
+# any TARGETARCH containing x86 is just "x86"
+ifeq ($(findstring x86_mmx,$(TARGETARCH)),x86_mmx)
+	TARGETARCH = x86
+endif
+
+ASD        ?= 0
+ifneq ($(ASD),1)
+  override ASD:=
+endif
+ifneq ($(ASD),1)
+  NOASDDIR    = _noasd
+endif
+
+RWL        ?= 1
+ifeq ($(RWL),0)
+  override RWL:=
+endif
+
+ifeq (,$(findstring freebsd, $(TARGETENV)))
+RWL_DONGLE        ?= 1
+RWL_SOCKET        ?= 1
+RWL_WIFI          ?= 1
+RWL_SERIAL        ?= 1
+
+ifneq ($(RWL_DONGLE),0)
+RWL_SERVERS += $(SERVER_DONGLE)
+endif
+ifneq ($(RWL_SOCKET),0)
+RWL_SERVERS += $(SERVER_SOCKET)
+endif
+ifneq ($(RWL_WIFI),0)
+RWL_SERVERS += $(SERVER_WIFI)
+endif
+ifneq ($(RWL_SERIAL),0)
+RWL_SERVERS += $(SERVER_SERIAL)
+endif
+endif
+# $(TARGETARCH) is set based on TARGETENV in src/Makerules.* files
+ifneq (,$(findstring freebsd, $(TARGETENV)))
+WL_OBJS      := wlu.o wlu_common.o wlu_bsd.o wlu_cmd.o wlu_iov.o wlu_rates_matrix.o miniopt.o bcmutils.o bcmwifi_channels.o bcm_app_utils.o wlc_ppr.o bcmxtlv.o bcmbloom.o wlu_subcounters.o
+else
+WL_OBJS      := wlu.o wlu_common.o wlu_linux.o bcmutils.o bcmwifi_channels.o wlu_cmd.o wlu_iov.o wlu_client_shared.o wlu_pipe_linux.o wlu_pipe.o miniopt.o bcm_app_utils.o wlu_rates_matrix.o wlc_ppr.o bcmxtlv.o bcmbloom.o wlu_subcounters.o
+endif
+
+ifneq ($(findstring WL_NAN, $(CFLAGS)),)
+WL_OBJS += sha256.o
+endif
+
+SERVER_OBJS  := wlu_server_linux.o wlu_pipe_linux.o wlu_pipe.o wlu_server_shared.o shellproc_linux.o
+WLM_OBJS     := $(WL_OBJS) wlm.o
+WLHIGHSTUB_OBJS := wlhighstub.o bcm_rpc_char.o bcm_rpc.o linux_rpc_osl.o
+WLHIGHSTUB_OBJS += wlc_low_stubs.o bcm_xdr.o
+
+WL_OBJS += wluc_phy.o
+WL_OBJS += wluc_wnm.o
+WL_OBJS += wluc_cac.o
+WL_OBJS += wluc_relmcast.o
+WL_OBJS += wluc_rrm.o
+WL_OBJS += wluc_wowl.o
+WL_OBJS += wluc_pkt_filter.o
+WL_OBJS += wluc_mfp.o
+WL_OBJS += wluc_ota_test.o
+WL_OBJS += wluc_bssload.o
+WL_OBJS += wluc_stf.o
+WL_OBJS += wluc_offloads.o
+WL_OBJS += wluc_tpc.o
+WL_OBJS += wluc_toe.o
+WL_OBJS += wluc_arpoe.o
+WL_OBJS += wluc_keep_alive.o
+WL_OBJS += wluc_ap.o
+WL_OBJS += wluc_ampdu.o
+WL_OBJS += wluc_ampdu_cmn.o
+WL_OBJS += wluc_bmac.o
+WL_OBJS += wluc_ht.o
+WL_OBJS += wluc_wds.o
+WL_OBJS += wluc_keymgmt.o
+WL_OBJS += wluc_scan.o
+WL_OBJS += wluc_obss.o
+WL_OBJS += wluc_prot_obss.o
+WL_OBJS += wluc_lq.o
+WL_OBJS += wluc_seq_cmds.o
+WL_OBJS += wluc_btcx.o
+WL_OBJS += wluc_led.o
+WL_OBJS += wluc_interfere.o
+WL_OBJS += wluc_ltecx.o
+WL_OBJS += wlu_avail_utils.o
+
+ifneq ($(findstring WL_BTCDYN, $(CFLAGS)),)
+WL_OBJS += wluc_btcdyn.o
+endif
+
+ifneq ($(findstring WL_NAN, $(CFLAGS)),)
+WL_OBJS += wluc_nan.o
+endif
+
+ifneq ($(findstring WLRSDB, $(CFLAGS)),)
+WL_OBJS += wluc_rsdb.o
+endif
+
+ifneq ($(findstring WLEXTLOG, $(CFLAGS)),)
+WL_OBJS += wluc_extlog.o
+endif
+
+ifneq ($(findstring BCMSDIO, $(CFLAGS)),)
+WL_OBJS += wluc_sdio.o
+endif
+
+ifneq ($(findstring WLNDOE, $(CFLAGS)),)
+WL_OBJS += wluc_ndoe.o
+endif
+
+ifneq ($(filter -DWLP2PO, $(CFLAGS)),)
+WL_OBJS += wluc_p2po.o
+endif
+
+ifneq ($(findstring WLANQPO, $(CFLAGS)),)
+WL_OBJS += wluc_anqpo.o
+endif
+
+ifneq ($(findstring WLBDO, $(CFLAGS)),)
+WL_OBJS += wluc_bdo.o
+endif
+
+ifneq ($(findstring WLTKO, $(CFLAGS)),)
+WL_OBJS += wluc_tko.o
+endif
+
+ifneq ($(findstring WLPFN, $(CFLAGS)),)
+WL_OBJS += wluc_pfn.o
+endif
+
+ifneq ($(findstring BT_WIFI_HANDOVER, $(CFLAGS)),)
+WL_OBJS += wluc_tbow.o
+endif
+
+ifneq ($(filter -DWLP2P, $(CFLAGS)),)
+WL_OBJS += wluc_p2p.o
+endif
+
+ifneq ($(findstring WLTDLS, $(CFLAGS)),)
+WL_OBJS += wluc_tdls.o
+endif
+
+ifneq ($(findstring TRAFFIC_MGMT, $(CFLAGS)),)
+WL_OBJS += wluc_traffic_mgmt.o
+endif
+
+ifneq ($(findstring WL_PROXDETECT, $(CFLAGS)),)
+WL_OBJS += wluc_proxd.o
+endif
+
+ifneq ($(findstring WL_RANDMAC, $(CFLAGS)),)
+WL_OBJS += wluc_randmac.o
+endif
+
+ifneq ($(findstring WLMESH, $(CFLAGS)),)
+WL_OBJS += wluc_mesh.o
+endif
+
+ifneq ($(findstring WL_NATOE, $(CFLAGS)),)
+WL_OBJS += wluc_natoe.o
+endif
+
+ifneq ($(findstring WL_MSCH, $(CFLAGS)),)
+WL_OBJS += wluc_msch.o
+endif
+
+WL_OBJS += wluc_he.o
+
+
+ifneq ($(findstring WL_MBO, $(CFLAGS)),)
+WL_OBJS += wluc_mbo.o
+endif
+
+ifneq ($(findstring ECOUNTERS, $(CFLAGS)),)
+WL_OBJS += wluc_ecounters.o
+endif
+
+ifneq ($(wildcard ../../../components/hml),)
+CFLAGS += -DHOFFLOAD_MODULES
+CFLAGS += -I ../../../components/hml/include -I ../../pciedev
+WL_OBJS += wluc_hoffload.o
+endif
+
+# include build settings for nl80211 support
+ifeq ($(NL80211),1)
+include netlink.inc
+endif
+
+# Prefix obj/<type>/TARGETARCH to produced .obj files
+WL_OBJS      := $(WL_OBJS:%.o=obj/wl$(NOASDDIR)/$(TARGETARCH)/%.o)
+DONGLE_OBJS  := $(SERVER_OBJS:%.o=obj/dongle$(NOASDDIR)/$(TARGETARCH)/%.o)
+SOCKET_OBJS  := $(SERVER_OBJS:%.o=obj/socket$(NOASDDIR)/$(TARGETARCH)/%.o)
+WIFI_OBJS    := $(SERVER_OBJS:%.o=obj/wifi$(NOASDDIR)/$(TARGETARCH)/%.o)
+SERIAL_OBJS  := $(SERVER_OBJS:%.o=obj/serial$(NOASDDIR)/$(TARGETARCH)/%.o)
+WLM_OBJS     := $(WLM_OBJS:%.o=obj/wlm/$(TARGETARCH)/%.o)
+WLHIGHSTUB_OBJS  := $(WLHIGHSTUB_OBJS:%.o=obj/wlhighstub/$(TARGETARCH)/%.o)
+
+# Derive a final list of all known objects.
+OBJS         := $(WL_OBJS) $(DONGLE_OBJS) $(SOCKET_OBJS) $(WIFI_OBJS) $(SERIAL_OBJS) $(WLM_OBJS) $(WLHIGHSTUB_OBJS)
+
+# Make a list of dependency files, one per object file.
+DEPENDS      := $(join $(dir $(OBJS)),$(addprefix .,$(addsuffix .depend,$(notdir $(OBJS)))))
+
+# Include any dependency files which currently exist.
+-include $(DEPENDS)
+
+# TODO: Move final built objects to respective TARGETARCH dirs as well
+# Final exe names
+ifneq ($(TARGETARCH),x86)
+	ARCH_SFX   = $(TARGETARCH)
+endif
+WL_EXE       := wl$(ARCH_SFX)
+SERVER_SOCKET = socket$(NOASDDIR)/$(TARGETARCH)/wl_server_socket$(ARCH_SFX)
+SERVER_DONGLE = dongle$(NOASDDIR)/$(TARGETARCH)/wl_server_dongle$(ARCH_SFX)
+SERVER_WIFI   = wifi$(NOASDDIR)/$(TARGETARCH)/wl_server_wifi$(ARCH_SFX)
+SERVER_SERIAL = serial$(NOASDDIR)/$(TARGETARCH)/wl_server_serial$(ARCH_SFX)
+WLM_SO       := wlm/$(TARGETARCH)/wlm$(ARCH_SFX).so
+WLHIGHSTUB   := obj/wlhighstub/$(TARGETARCH)/wlhighstub$(ARCH_SFX)
+
+# excluding lbrt  inclusion for android build 
+ifeq (,$(findstring android,$(TARGETARCH)))
+LDFLAGS      += -lrt
+endif
+
+# ASD specific flags
+ifeq ($(ASD),1)
+  ASD_CFLAGS := -DRWLASD
+  ASD_CFLAGS += -I../../tools/Wifi_ASD_test/inc
+ifneq ($(filter mips_be arm_android arm_android_ndk_r6b x86_android_ndk_r6b arm64_android,$(TARGETARCH)),)
+  ASD_LDFLAGS:= -L../../tools/Wifi_ASD_test/lib/$(TARGETARCH) -lwfa
+else
+  ASD_LDFLAGS:= -L../../tools/Wifi_ASD_test/lib/$(TARGETARCH) -lwfa -lpthread
+endif
+endif # ASD
+INSTALL_DIR ?= apps
+
+vpath %.c $(SRCBASE)/shared $(SRCBASE)/wl/sys $(WLAN_StdSrcDirsR) $(WLAN_ComponentSrcDirsR)
+
+all:  build_deps
+
+# Build servers for all but mips_be
+ifeq ($(filter mips_be,$(TARGETARCH)),)
+all:  $(WL_EXE) servers
+else
+all: $(WL_EXE)
+endif
+
+build_deps:
+ifeq ($(ASD),1)
+	$(MAKE) -C ../../tools/Wifi_ASD_test
+endif # ASD
+
+wlm: $(WLM_SO)
+
+servers: $(RWL_SERVERS)
+
+# Handle creation of directories for objects mentioned below.
+$(addprefix obj/,$(addsuffix $(NOASDDIR)/$(TARGETARCH),wl dongle socket wifi serial) $(addsuffix /$(TARGETARCH),wlm wlhighstub)):
+	@mkdir -pv $@
+
+# Compilation targets
+obj/wl$(NOASDDIR)/$(TARGETARCH)/%.o: %.c | obj/wl$(NOASDDIR)/$(TARGETARCH)
+ifneq ($(RWL),)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_SOCKET -DRWL_DONGLE -DRWL_WIFI -DRWL_SERIAL -o $@ $<)
+else
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -o $@ $<)
+endif
+
+obj/dongle$(NOASDDIR)/$(TARGETARCH)/%.o: %.c | obj/dongle$(NOASDDIR)/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_DONGLE -o $@ $<)
+
+obj/socket$(NOASDDIR)/$(TARGETARCH)/%.o: %.c | obj/socket$(NOASDDIR)/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_SOCKET -o $@ $<)
+
+obj/wifi$(NOASDDIR)/$(TARGETARCH)/%.o: %.c | obj/wifi$(NOASDDIR)/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_WIFI -o $@ $<)
+
+obj/serial$(NOASDDIR)/$(TARGETARCH)/%.o: %.c | obj/serial$(NOASDDIR)/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_SERIAL -o $@ $<)
+
+obj/wlm/$(TARGETARCH)/%.o: %.c | obj/wlm/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) $(ASD_CFLAGS) -DRWL_DONGLE -DRWL_SOCKET -DRWL_WIFI -DRWL_SERIAL -DWLMSO -fPIC -o $@ $<)
+
+obj/wlhighstub/$(TARGETARCH)/%.o: %.c | obj/wlhighstub/$(TARGETARCH)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) -o $@ $<)
+
+$(WLHIGHSTUB): $(WLHIGHSTUB_OBJS)
+	@mkdir -pv $(@D)
+
+# Final link targets
+$(WL_EXE): $(WL_OBJS)
+	$(strip $(CC) -o $@ $^ $(LDFLAGS) $(LIBS))
+ifneq ($(filter arm_android_ndk_r6b,$(TARGETARCH)),)
+ifneq ($(TARGET_PREFIX),)
+	$(TARGET_PREFIX)strip $(WL_EXE)
+endif
+endif
+
+# net_priv target is for building the dhd with NET_ADMIN privilege (i.e. to avoid running as root)
+# note: The 'setcap' command is availble from the libcap2-bin package
+# note: linux kernel < 2.6.33 doesn't support Security File Capabilities by default
+net_priv: $(WL_EXE)
+	sudo setcap CAP_NET_ADMIN=eip $^
+
+$(SERVER_DONGLE): $(DONGLE_OBJS)
+	@mkdir -pv $(@D)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^ $(ASD_LDFLAGS))
+
+$(SERVER_SOCKET): $(SOCKET_OBJS)
+	@mkdir -pv $(@D)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^ $(ASD_LDFLAGS))
+
+$(SERVER_WIFI): $(WIFI_OBJS)
+	@mkdir -pv $(@D)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^ $(ASD_LDFLAGS))
+
+$(SERVER_SERIAL): $(SERIAL_OBJS)
+	@mkdir -pv $(@D)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^ $(ASD_LDFLAGS))
+
+$(WLM_SO): $(WLM_OBJS)
+	@mkdir -pv $(@D)
+	$(strip $(CC) $(LDFLAGS) -shared -o $@ $^)
+
+wldefs: wlmain.o
+	$(CC) $(LDFLAGS) -o $@ $<
+
+.PHONY: all clean wlm release_bins net_priv
+
+release_bins:
+	@mkdir -p $(INSTALL_DIR)
+	install -pv $(WL_EXE) $(INSTALL_DIR)
+ifeq ($(filter mips_be,$(TARGETARCH)),)
+	install -pv $(SERVER_SOCKET) $(INSTALL_DIR)
+	install -pv $(SERVER_DONGLE) $(INSTALL_DIR)
+	install -pv $(SERVER_WIFI) $(INSTALL_DIR)
+	install -pv $(SERVER_SERIAL) $(INSTALL_DIR)
+endif
+ifeq ($(ASD),1)
+	$(MAKE) -C ../../tools/Wifi_ASD_test release_bins
+endif #ASD
+
+clean::
+	rm -fv $(WL_EXE) $(WL_OBJS) $(SERVER_SOCKET) $(SERVER_DONGLE) $(SERVER_WIFI) $(SERVER_SERIAL) $(SOCKET_OBJS) $(SERIAL_OBJS) $(WIFI_OBJS) $(DONGLE_OBJS) $(WLM_SO) $(WLM_OBJS) $(SERVER_SERIAL) $(DEPENDS)
+
+endif # TARGETENV linux
+
+#-----------------------------------------------------------------
+# MacOS build
+#
+
+ifeq ($(TARGETENV), macos)
+
+ifndef MACOS_VER
+  MACOS_VER := $(shell sw_vers -productVersion)
+endif
+
+include $(SRCBASE)/Makerules.env
+
+.PHONY: all everything clean wl wl_server_socket wl_server_wifi wl_dongle
+
+PROJTGT	:= wl
+BUILD	:= xcodebuild
+PROJECT	:= wl.xcodeproj
+OBJDIR	:= $(TARGETENV)/$(MACOS_VER)
+
+all: wl wl_server_socket
+
+everything: wl wl_server_socket wl_server_wifi wl_dongle
+
+clean::
+	rm -rf $(OBJDIR) build
+
+wl wl_server_socket wl_server_wifi: | $(OBJDIR)
+
+#
+# dongle wl is located at ./build/Debug/wl
+#
+wl_dongle:
+	$(BUILD) -project $(PROJECT) -target $(PROJTGT) -configuration Debug build
+
+WL_EXE		:= $(OBJDIR)/wl
+SERVER_SOCKET	:= $(OBJDIR)/socket/wl_server_socket
+SERVER_WIFI	:= $(OBJDIR)/wifi/wl_server_wifi
+
+WL_OBJS := $(addprefix $(OBJDIR)/,wlu.o wlu_common.o wlu_macos.o bcmutils.o bcmwifi_channels.o wlu_cmd.o wlu_iov.o miniopt.o bcm_app_utils.o wlu_rates_matrix.o wlc_ppr.o bcmxtlv.o wlu_subcounters.o)
+SERVER_OBJS := wlu_server_macos.o  wlu_pipe_linux.o wlu_pipe.o wlu_server_shared.o shellproc_linux.o
+SOCKET_OBJS := $(SERVER_OBJS:%.o=$(OBJDIR)/socket/%.o)
+WIFI_OBJS := $(SERVER_OBJS:%.o=$(OBJDIR)/wifi/%.o)
+
+# Derive a final list of all known objects.
+OBJS         := $(WL_OBJS) $(SOCKET_OBJS) $(WIFI_OBJS)
+
+# Create the sub-directories needed to hold object files.
+$(sort $(dir $(OBJS))):
+	@mkdir -pv $@
+
+# Make a list of dependency files, one per object file.
+DEPENDS      := $(join $(dir $(OBJS)),$(addprefix .,$(addsuffix .depend,$(notdir $(OBJS)))))
+
+# Include any dependency files which currently exist.
+-include $(DEPENDS)
+
+vpath %.c .. $(SRCBASE)/shared $(SRCBASE)/wl/sys $(WLAN_StdSrcDirsR) $(WLAN_ComponentSrcDirsR)
+
+ifneq (,$(findstring 10.11,$(MACOS_VER)))
+        GCDEFS  += -DWLP2P -DWLMCHAN -DPPR_API -DWLANQPO -DWLP2PO -DWL_DUMP_BUF_LEN=819200
+else
+ifneq (,$(findstring 10.10,$(MACOS_VER)))
+        GCDEFS  += -DWLP2P -DWLMCHAN -DPPR_API -DWLANQPO -DWLP2PO -DWL_DUMP_BUF_LEN=819200
+else
+ifneq (,$(findstring 10.9,$(MACOS_VER)))
+        GCDEFS  += -DWLP2P -DWLMCHAN -DPPR_API -DWLANQPO -DWLP2PO
+else
+        GCDEFS  += -DWLP2P -DWLMCHAN -DPPR_API -DWLANQPO -DWLP2PO -DWL_DUMP_BUF_LEN=819200
+endif
+endif
+endif
+
+
+WL_OBJS += $(OBJDIR)/wluc_phy.o
+WL_OBJS += $(OBJDIR)/wluc_wnm.o
+WL_OBJS += $(OBJDIR)/wluc_cac.o
+WL_OBJS += $(OBJDIR)/wluc_relmcast.o
+WL_OBJS += $(OBJDIR)/wluc_rrm.o
+WL_OBJS += $(OBJDIR)/wluc_wowl.o
+WL_OBJS += $(OBJDIR)/wluc_pkt_filter.o
+WL_OBJS += $(OBJDIR)/wluc_mfp.o
+WL_OBJS += $(OBJDIR)/wluc_ota_test.o
+WL_OBJS += $(OBJDIR)/wluc_bssload.o
+WL_OBJS += $(OBJDIR)/wluc_stf.o
+WL_OBJS += $(OBJDIR)/wluc_offloads.o
+WL_OBJS += $(OBJDIR)/wluc_tpc.o
+WL_OBJS += $(OBJDIR)/wluc_toe.o
+WL_OBJS += $(OBJDIR)/wluc_arpoe.o
+WL_OBJS += $(OBJDIR)/wluc_keep_alive.o
+WL_OBJS += $(OBJDIR)/wluc_ap.o
+WL_OBJS += $(OBJDIR)/wluc_ampdu.o
+WL_OBJS += $(OBJDIR)/wluc_ampdu_cmn.o
+WL_OBJS += $(OBJDIR)/wluc_bmac.o
+WL_OBJS += $(OBJDIR)/wluc_ht.o
+WL_OBJS += $(OBJDIR)/wluc_wds.o
+WL_OBJS += $(OBJDIR)/wluc_keymgmt.o
+WL_OBJS += $(OBJDIR)/wluc_scan.o
+WL_OBJS += $(OBJDIR)/wluc_obss.o
+WL_OBJS += $(OBJDIR)/wluc_prot_obss.o
+WL_OBJS += $(OBJDIR)/wluc_lq.o
+WL_OBJS += $(OBJDIR)/wluc_seq_cmds.o
+WL_OBJS += $(OBJDIR)/wluc_btcx.o
+WL_OBJS += $(OBJDIR)/wluc_led.o
+WL_OBJS += $(OBJDIR)/wluc_interfere.o
+WL_OBJS += $(OBJDIR)/wluc_ltecx.o
+
+ifneq ($(or $(findstring WL_BTCDYN, $(GCDEFS)),\
+	    $(findstring WL_BTCDYN, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_btcdyn.o
+endif
+
+ifneq ($(findstring WLMESH, $(CFLAGS)),)
+WL_OBJS += $(OBJDIR)/wluc_mesh.o
+endif
+
+ifneq ($(or $(findstring WL_NAN, $(GCDEFS)),\
+	    $(findstring WL_NAN, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_nan.o
+endif
+
+ifneq ($(or $(findstring WLRSDB, $(GCDEFS)),\
+	    $(findstring WLRSDB, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_rsdb.o
+endif
+
+ifneq ($(or $(findstring WL_NATOE, $(GCDEFS)),\
+	    $(findstring WL_NATOE, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_natoe.o
+endif
+
+ifneq ($(or $(findstring WLEXTLOG, $(GCDEFS)),\
+	    $(findstring WLEXTLOG, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_extlog.o
+endif
+
+ifneq ($(or $(findstring BCMSDIO, $(GCDEFS)),\
+	    $(findstring BCMSDIO, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_sdio.o
+endif
+
+ifneq ($(or $(findstring WLNDOE, $(GCDEFS)),\
+	    $(findstring WLNDOE, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_ndoe.o
+endif
+
+ifneq ($(or $(filter -DWLP2PO, $(GCDEFS)),\
+	    $(filter -DWLP2PO, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_p2po.o
+endif
+
+ifneq ($(or $(findstring WLANQPO, $(GCDEFS)),\
+	    $(findstring WLANQPO, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_anqpo.o
+endif
+
+ifneq ($(or $(findstring WLBDO, $(GCDEFS)),\
+	    $(findstring WLBDO, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_bdo.o
+endif
+
+ifneq ($(or $(findstring WLTKO, $(GCDEFS)),\
+	    $(findstring WLTKO, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_tko.o
+endif
+ifneq ($(or $(findstring WLPFN, $(GCDEFS)),\
+	    $(findstring WLPFN, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_pfn.o
+endif
+
+ifneq ($(or $(filter -DWLP2P, $(GCDEFS)),\
+	    $(filter -DWLP2P, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_p2p.o
+endif
+
+ifneq ($(or $(findstring WLTDLS, $(GCDEFS)),\
+	    $(findstring WLTDLS, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_tdls.o
+endif
+
+ifneq ($(or $(findstring TRAFFIC_MGMT, $(GCDEFS)),\
+	    $(findstring TRAFFIC_MGMT, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_traffic_mgmt.o
+endif
+
+ifneq ($(or $(findstring WL_PROXDETECT, $(GCDEFS)),\
+	    $(findstring WL_PROXDETECT, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_proxd.o
+endif
+
+ifneq ($(or $(findstring WL_MSCH, $(GCDEFS)),\
+	    $(findstring WL_MSCH, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_msch.o
+endif
+
+
+ifneq ($(or $(findstring ECOUNTERS, $(GCDEFS)),\
+	    $(findstring ECOUNTERS, $(CFLAGS))),)
+WL_OBJS += $(OBJDIR)/wluc_ecounters.o
+endif
+
+WL_OBJS += $(OBJDIR)/wluc_he.o
+
+$(OBJDIR)/%.o: %.c | $(OBJDIR)
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) -o $@ $<)
+
+wl: $(OBJDIR)/wl
+$(OBJDIR)/wl: $(WL_OBJS)
+	$(CC) -L/usr/lib $(LDFLAGS) -o $@ $^
+
+wl_server_socket: $(SERVER_SOCKET)
+$(SERVER_SOCKET): $(SOCKET_OBJS)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^)
+
+$(OBJDIR)/socket/%.o: %.c | $(OBJDIR)/socket
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) -DRWL_SOCKET -DREMOTE_WL -o $@ $<)
+
+wl_server_wifi: $(SERVER_WIFI)
+$(SERVER_WIFI): $(WIFI_OBJS)
+	$(strip $(CC) $(LDFLAGS) -o $@ $^)
+
+$(OBJDIR)/wifi/%.o: %.c | $(OBJDIR)/wifi
+	$(call CompileAndMakedep,$(CC),$(CFLAGS) -DRWL_WIFI -DREMOTE_WL -o $@ $<)
+
+endif # TARGETENV macos
+
+endif # UNAME
diff --git a/wl/src/wl/exe/netlink.inc b/wl/src/wl/exe/netlink.inc
new file mode 100644
index 0000000..d32b169
--- /dev/null
+++ b/wl/src/wl/exe/netlink.inc
@@ -0,0 +1,95 @@
+#
+# netlink.inc for wl/exe
+#
+# Broadcom Proprietary and Confidential. Copyright (C) 2017,
+# All Rights Reserved.
+# 
+# This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+# the contents of this file may not be disclosed to third parties, copied
+# or duplicated in any form, in whole or in part, without the prior
+# written permission of Broadcom.
+#
+#
+# <<Broadcom-WL-IPTag/Proprietary:>>
+#
+# $Id: netlink.inc 629114 2016-04-04 08:29:40Z $
+
+ifneq ($(findstring android,$(TARGETENV)),)
+
+include $(dir $(lastword $(MAKEFILE_LIST)))/../../makefiles/WLAN_Common.mk
+
+ifeq ($(NLHEADERS_PATH),)
+$(error libnl headers path must be specified)
+endif
+ifeq ($(NLSTATICLIB_PATH),)
+$(error libnl static library path must be specified)
+endif
+
+CFLAGS += -I$(NLHEADERS_PATH)
+LIBS += -Wl,--whole-archive -Wl,--no-whole-archive $(NLSTATICLIB_PATH)
+
+LIBNLVER = $(shell grep "LIBNL_VERSION" $(NLHEADERS_PATH)/netlink/version.h | cut -d " " -f 3 | sed "s/\"//g")
+
+ifeq ($(call wlan_version_ge,$(LIBNLVER),3.0),TRUE)
+CFLAGS += -DCONFIG_LIBNL30
+else ifeq ($(call wlan_version_ge,$(LIBNLVER),2.0),TRUE)
+CFLAGS += -DCONFIG_LIBNL20
+endif
+
+else #ifneq ($(findstring android,$(TARGETENV)),)
+
+PKG_CONFIG ?= pkg-config
+
+NL1FOUND := $(shell $(PKG_CONFIG) --atleast-version=1 libnl-1 && echo Y)
+NL2FOUND := $(shell $(PKG_CONFIG) --atleast-version=2 libnl-2.0 && echo Y)
+NL3FOUND := $(shell $(PKG_CONFIG) --atleast-version=3 libnl-3.0 && echo Y)
+NL31FOUND := $(shell $(PKG_CONFIG) --exact-version=3.1 libnl-3.1 && echo Y)
+NL3xFOUND := $(shell $(PKG_CONFIG) --atleast-version=3.2 libnl-3.0 && echo Y)
+
+ifeq ($(NL1FOUND),Y)
+NLLIBNAME = libnl-1
+endif
+
+ifeq ($(NL2FOUND),Y)
+CFLAGS += -DCONFIG_LIBNL20
+LIBS += -lnl-genl
+NLLIBNAME = libnl-2.0
+endif
+
+ifeq ($(NL3xFOUND),Y)
+# libnl 3.2 might be found as 3.2 and 3.0
+NL3FOUND = N
+CFLAGS += -DCONFIG_LIBNL30
+LIBS += -lnl-genl-3
+NLLIBNAME = libnl-3.0
+endif
+
+ifeq ($(NL3FOUND),Y)
+CFLAGS += -DCONFIG_LIBNL30
+LIBS += -lnl-genl
+NLLIBNAME = libnl-3.0
+endif
+
+# nl-3.1 has a broken libnl-gnl-3.1.pc file
+# as show by pkg-config --debug --libs --cflags --exact-version=3.1 libnl-genl-3.1;echo $?
+ifeq ($(NL31FOUND),Y)
+CFLAGS += -DCONFIG_LIBNL30
+LIBS += -lnl-genl
+NLLIBNAME = libnl-3.1
+endif
+
+ifeq ($(NLLIBNAME),)
+ifeq ($(and $(NLLIBS), $(NLCFLAGS)),)
+$(error Cannot find development files for any supported version of libnl)
+endif
+LIBS += $(NLLIBS)
+CFLAGS += $(NLCFLAGS)
+$(warning override $(LIBS))
+else
+LIBS += $(shell $(PKG_CONFIG) --libs $(NLLIBNAME))
+CFLAGS += $(shell $(PKG_CONFIG) --cflags $(NLLIBNAME))
+endif
+
+endif #ifneq ($(findstring android,$(TARGETENV)),)
+
+WL_OBJS += wlu_nl80211.o
diff --git a/wl/src/wl/exe/shellproc_linux.c b/wl/src/wl/exe/shellproc_linux.c
new file mode 100644
index 0000000..e2cc825
--- /dev/null
+++ b/wl/src/wl/exe/shellproc_linux.c
@@ -0,0 +1,700 @@
+/*
+ * Remote shell command execution (common for all transports) for linux
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: shellproc_linux.c 514727 2014-11-12 03:02:48Z $
+ */
+
+/* Linux remote shell command execution
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <bcmcdc.h>
+#include "wlu_remote.h"
+#include <sys/poll.h>
+#include <malloc.h>
+#include <miniopt.h>
+#include <sys/utsname.h>
+#define ASYNC_RESP     0
+#define MAX_SHELL_ASYNC_RESP  128  /* Support for maximum 5 async process */
+#define MAX_ASYNC_FILE_LENGTH 50
+#define MAX_PID_CMD_LENGTH    20
+#define MAX_PID_RESP_LENTH    50
+#define MAX_SHELL_CMD_LENTH   256
+#define PID_TOKEN_SIZE	      50
+#define PID_SEARCH_CMD_SIZE   100
+#define ASYNC_SHELL_CHAR "%"  /* Async process identifier from the client */
+#define FILE_PERMISSION	 777
+
+#define DEFAULT_SHELL_TIMEOUT	0 /* Default TimeOut Value for synchronous shell commands */
+#define SHELL_RETURNVALUE_SIZE	2 /* Size of Return Value of the shell command */
+#define SHELL_ASYNCCMD_ID	1 /* To identify if it is an async command */
+#define REBOOT_MSG      "Rebooting AP  ...\n"
+
+/* Function prototypes */
+
+static int rwl_get_file_size(char *file_name);
+static int remote_shell_async_exec(char *buf_ptr);
+static int remote_shell_sync_exec(char *cmd_buf_ptr, void *wl);
+
+
+/* Data structure to hold async shell information */
+typedef struct remote_shell_async {
+	pid_t PID;
+	char file_name[MAX_ASYNC_FILE_LENGTH];
+} remote_shell_async_t;
+
+remote_shell_async_t g_async_resp[MAX_SHELL_ASYNC_RESP];
+
+extern int g_shellsync_pid;
+
+extern unsigned char g_return_stat;
+extern void rwl_chld_handler(int num);
+extern int set_ctrlc;
+extern void handle_ctrlc(int unused);
+
+/* Global variable to store the timeout value for the shell commands */
+static int g_shellsync_timeout = DEFAULT_SHELL_TIMEOUT;
+char globalbuffer[MAX_SHELL_CMD_LENTH];
+
+/* Wait for process termination.
+ * This function returns immediately if the child has
+ * already exited (zombie process)
+ */
+static void
+sigchld_handler(int s)
+{
+	UNUSED_PARAMETER(s);
+
+	while (waitpid(-1, NULL, WNOHANG) > 0);
+}
+
+/* Create a main directory \tmp\RWL\ for the shell response files */
+int
+rwl_create_dir(void)
+{
+	if (mkdir(SHELL_RESP_PATH, FILE_PERMISSION) < 0) {
+		if (errno != EEXIST)
+			return BCME_ERROR;
+	}
+
+	return SUCCESS;
+}
+
+/* Main function for shell command execution */
+int
+remote_shell_execute(char* buf_ptr, void *wl)
+{
+	char *async_cmd_flag;
+	int msg_len;
+
+	/* Check for the "%" token in the buffer from client
+	 * If "%" token is present, execute asynchronous process
+	 * else, execute synchronous shell process
+	 */
+	async_cmd_flag = strstr((char*)buf_ptr, ASYNC_SHELL_CHAR);
+
+	if ((async_cmd_flag != NULL) && (!strcmp(async_cmd_flag, ASYNC_SHELL_CHAR))) {
+		g_shellsync_pid = SHELL_ASYNCCMD_ID;
+		msg_len = remote_shell_async_exec(buf_ptr);
+	}
+	else {
+		msg_len = remote_shell_sync_exec(buf_ptr, wl);
+		strcpy(buf_ptr, globalbuffer);
+	}
+	return msg_len;
+}
+
+/* Function to get the shell response from the file */
+int
+remote_shell_async_get_resp(char* shell_fname, char* buf_ptr, int msg_len)
+{
+	int sts = 0;
+	FILE *shell_fpt;
+
+	shell_fpt = fopen(shell_fname, "rb");
+
+	if (shell_fpt == NULL) {
+		DPRINT_ERR(ERR, "\nShell Cmd:File open error\n");
+		return sts;
+	}
+
+	/* If there is any response from the shell, Read the file and
+	 * update the buffer for the shell response
+	 * else Just send the return value of the command executed
+	 */
+	if (g_shellsync_pid != SHELL_ASYNCCMD_ID) {
+		if (msg_len)
+			sts  = fread(buf_ptr, sizeof(char), msg_len, shell_fpt);
+		fscanf(shell_fpt, "%2x", &sts);
+	}
+	else
+		sts  = fread(buf_ptr, sizeof(char), MAX_SHELL_CMD_LENTH, shell_fpt);
+
+	fclose(shell_fpt);
+
+	remove(shell_fname);
+
+	DPRINT_DBG(OUTPUT, "\n Resp buff from shell cmdis %s\n", buf_ptr);
+
+	return sts;
+}
+
+/*
+ * Function to get the shell response length
+ * by opening the file containing the shell response
+ * and get the total file size.
+ * For a given input file name it returns File size.
+ */
+static int
+rwl_get_file_size(char *file_name)
+{
+	FILE *shell_fpt;
+	int filesize = 0;
+
+	shell_fpt = fopen(file_name, "rb");
+
+	if (shell_fpt == NULL) {
+		DPRINT_DBG(OUTPUT, "\nShell Cmd:File open error\n");
+		return filesize;
+	}
+
+	/* obtain file size */
+	if (fseek(shell_fpt, 0, SEEK_END) < 0)
+		return filesize;
+
+	filesize = ftell(shell_fpt);
+	fclose(shell_fpt);
+
+	return filesize;
+}
+
+/*
+ * Function for executing asynchronous shell comamnd
+ * Stores the results in async temp file and returns the PID
+ */
+static int
+remote_shell_async_exec(char *buf_ptr)
+{
+	int PID_val = 0, val, msg_len, sts;
+	FILE *fpt;
+	int async_count = 0; /* counter needs to be initialized */
+	struct sigaction sa;
+	char pid_search_cmd[MAX_PID_CMD_LENGTH];
+	char pid_resp_buf[MAX_PID_RESP_LENTH];
+	char temp_async_file_name[MAX_ASYNC_FILE_LENGTH];
+	pid_t pid;
+	char *pid_token, next_pid[PID_TOKEN_SIZE][PID_TOKEN_SIZE];
+	struct utsname name;
+
+	/* Call the signal handler for reaping defunct or zombie process */
+	sa.sa_handler = sigchld_handler;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_RESTART;
+	if (sigaction(SIGCHLD, &sa, NULL) == -1) {
+		perror("sigaction:");
+	}
+
+	/* Store the async file name if that async process is not killed.
+	 * Async file name: async_temp_0...5
+	 */
+	for (val = 0; val < MAX_SHELL_ASYNC_RESP; val++) {
+		if (g_async_resp[val].PID > 0) {
+			async_count++;
+		} else {
+			sprintf(g_async_resp[val].file_name, "%s%d", "async_temp_", val);
+			break;
+		}
+	}
+	sprintf(temp_async_file_name, "%s%s", SHELL_RESP_PATH,
+		g_async_resp[val].file_name);
+
+	DPRINT_DBG(OUTPUT, "\nasync_count:%d\n", async_count);
+	if (async_count >= MAX_SHELL_ASYNC_RESP) {
+		sprintf(buf_ptr, "\n%s\n", "Exceeded max async process forking");
+		return BCME_ERROR;
+	}
+
+	/* Open a child process. The fork will return the PID of the child process
+	 * (i.e) defunct process PID in parent's thread of execution. Zero is returned
+	 * for child's thread of execution.
+	 */
+	if ((pid = fork()) == 0) {
+		/* Redirect the async process output to the async file
+		 * Then after the client executes the kill command for that
+		 * async process, the file will give the status of async process
+		 */
+		strtok(buf_ptr, ASYNC_SHELL_CHAR); /* Remove % character from the command buf */
+		uname(&name);
+		/*
+		* Checking for mips architecture
+		* different command for mips and x86
+		*/
+		if (strncmp(name.machine, "mips", sizeof(name.machine)) != 0) {
+			strcat(buf_ptr, "&> "); /* buf_ptr is now "ping 127.0.0.1&> " */
+			strcat(buf_ptr, temp_async_file_name); /* Add path \tmp\RWL\async_temp_* */
+		}
+		else {
+			strcat(buf_ptr, " > "); /* buf_ptr is now "ping 127.0.0.1> " */
+			strcat(buf_ptr, temp_async_file_name); /* Add path \tmp\RWL\async_temp_* */
+			strcat(buf_ptr, " 2>&1 &");
+		}
+		if ((sts = execl(SH_PATH, "sh", "-c", buf_ptr, NULL)) == -1) {
+			sprintf(buf_ptr, "%s\n", "Not able to execute shell cmd");
+			return BCME_ERROR;
+		}
+		exit(0);
+	} /* end of fork */
+
+	if (pid < 0) {
+		perror("\nFork error:");
+		sprintf(buf_ptr, "%s\n", "Forking async process failed");
+		return BCME_ERROR;
+	}
+
+	/* Find the PID of the running process (for ex: ping)
+	 * pidof -s options returns latest PID of the command.
+	 */
+	strtok(buf_ptr, " ");
+
+	uname(&name);
+	/* Checking for mips architecture */
+	if (strncmp(name.machine, "mips", sizeof(name.machine)) != 0)
+		sprintf(pid_search_cmd, "pidof -s %s", buf_ptr);
+	else
+		sprintf(pid_search_cmd, "pidof %s", buf_ptr);
+
+	sleep(1);
+
+	/* Execute the command e.g "pidof ping" */
+	if ((fpt = popen(pid_search_cmd, "r")) == NULL) {
+		sprintf(buf_ptr, "%s\n", "Can't return PID");
+		return BCME_ERROR;
+	}
+
+	/* Get the PID and copy the PID in buf_ptr to send to the client */
+	fgets(pid_resp_buf, sizeof(pid_resp_buf), fpt);
+
+	/* Checking for mips architecture */
+	if (strncmp(name.machine, "mips", sizeof(name.machine)) != 0) {
+		PID_val = atoi(pid_resp_buf);
+	}
+	else {
+		/* code to extract the correct PID */
+		pid_token = strtok_r(pid_resp_buf, " ", (char **)next_pid);
+		/* the pid buffer will terminate with a '\n' */
+		while (pid_token != NULL && *pid_token != '\n') {
+			PID_val = atoi(pid_token);
+			pid_token = strtok_r(NULL, " ", (char **)next_pid);
+		}
+	}
+	if (PID_val == 0) {
+		msg_len = rwl_get_file_size(temp_async_file_name);
+		remote_shell_async_get_resp(temp_async_file_name, buf_ptr, msg_len);
+
+	} else {
+		g_async_resp[val].PID = PID_val;
+		/* Update PID value in buffer to send it to client */
+		sprintf(buf_ptr, "%d", PID_val);
+		msg_len = strlen(buf_ptr);
+	}
+
+	pclose(fpt);
+	/* In async case, the PID value will be copied to the input buffer only
+	 * and there is no need of getting the response from the file. So return
+	 * value can be -1.
+	 */
+	return msg_len;
+}
+
+/* Process for 'kill' command.
+ * Kill command can also be used from the client to get the
+ * result of asynchronous command and actually kill the mentioned process
+ */
+static int
+remote_kill_cmd_exec(char *cmd_buf_ptr)
+{
+	char file_name[MAX_ASYNC_FILE_LENGTH];
+	int  PID_val = 0, val, msg_len;
+	FILE *fpt;
+	char *pid_token, next_pid[PID_TOKEN_SIZE][PID_TOKEN_SIZE];
+
+	system(cmd_buf_ptr);
+
+	/* Parse the PID val from the kill command.
+	 */
+	pid_token = strtok_r(cmd_buf_ptr, " ", (char **)next_pid);
+	while (pid_token != NULL && *pid_token != '\n') {
+		/* to extract the PID from the kill command */
+		PID_val = atoi(pid_token);
+		pid_token = strtok_r(NULL, " ", (char **)next_pid);
+	}
+
+	/* Check for the matching PID from the async structure and
+	 * give the last 256 bytes statistics of the async process
+	 * that was running
+	 */
+	for (val = 0; val < MAX_SHELL_ASYNC_RESP; ++val) {
+		if (g_async_resp[val].PID == PID_val) {
+			/* We found a match here. Hence get the response now from the
+			 * corresponding async response file
+			 */
+			sprintf(file_name, "%s%s", SHELL_RESP_PATH, g_async_resp[val].file_name);
+			msg_len = rwl_get_file_size(file_name);
+			if (msg_len > 0) {
+				if ((fpt = fopen(file_name, "rb")) == NULL) {
+					DPRINT_DBG(OUTPUT, "\nShell Cmd:File open error\n");
+					return BCME_ERROR;
+				}
+
+				if (fseek(fpt, 0, SEEK_SET) < 0) {
+					fclose(fpt);
+					return BCME_ERROR;
+				}
+
+				if (fread(cmd_buf_ptr, sizeof(char), MAX_SHELL_CMD_LENTH,
+					fpt) <= 0) {
+					sprintf(cmd_buf_ptr, "%s\n", "Shell Resp:Reading error");
+					fclose(fpt);
+					return BCME_ERROR;
+				}
+
+			fclose(fpt);
+			}
+			else
+				sprintf(cmd_buf_ptr, "ed %d: No Response\n", PID_val);
+			remove(g_async_resp[val].file_name);
+
+			g_async_resp[val].PID = 0;
+			break;
+		}
+	}
+	return MAX_SHELL_CMD_LENTH;
+}
+
+/* Handle --timeout command line option for linux servers */
+int
+shell_timeout_cmd(char *cmd_buf_ptr, char *sync_file_name)
+{
+	char *token1, *token2, *nexttoken;
+	FILE* fp;
+	int msg_len;
+
+	token1 = strtok_r(cmd_buf_ptr, "--timeout ", &nexttoken);
+	if (token1)
+		token2 = strtok_r(NULL, token1, &nexttoken);
+	if (token1 == NULL || atoi(token1) <= 0 || token2 == NULL) {
+		fp = fopen(sync_file_name, "w+");
+		fprintf(fp, "Usage: ./wl --<transport> <ip/mac> sh"
+			"--timeout <timeout value> <shell command>\n");
+		fprintf(fp, "Eg: ./wl --socket 172.22.65.226 sh --timeout 15 ls\n");
+		fflush(fp);
+		msg_len = rwl_get_file_size(sync_file_name);
+		strcpy(cmd_buf_ptr, sync_file_name);
+		fclose(fp);
+		strcpy(globalbuffer, sync_file_name);
+		printf("Fix timeout problem in socket!!!!!\n");
+		return msg_len;
+	}
+	else
+		g_shellsync_timeout = atoi(token1);
+	return BCME_OK;
+}
+
+/* Handle synchronous shell commands here */
+static int
+remote_shell_sync_exec(char *cmd_buf_ptr, void *wl)
+{
+	char *kill_cmd_token;
+	char sync_file_name[] = TEMPLATE;
+	int fd, msg_len;
+	char cmd[(strlen(cmd_buf_ptr) + 1)];
+	int pid, status, pid_final;
+	char buf[SHELL_RESP_SIZE], cmd_find_lastpid[PID_SEARCH_CMD_SIZE];
+	int nbytes = 0;
+	int child_status;
+	static int sent_once = 0;
+	struct utsname name;
+	FILE *fpt;
+
+	/* Default Size of Return Value of the shell command is 2bytes */
+
+	kill_cmd_token =  strstr(cmd_buf_ptr, "kill");
+
+	/* Synchronous Kill command processing is handled separately */
+	if (kill_cmd_token != NULL) {
+		msg_len = remote_kill_cmd_exec(cmd_buf_ptr);
+		remote_tx_response(wl, cmd_buf_ptr, msg_len);
+		return 0;
+	}
+
+
+	/* Process synchronous command other than kill command */
+	if ((fd = mkstemp(sync_file_name)) < 0) {
+		perror("mkstemp failed");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		sprintf(cmd_buf_ptr, "%s\n", "mkstemp failed");
+		return BCME_ERROR;
+	}
+
+	close(fd);
+
+	strcpy(cmd, cmd_buf_ptr);
+	/* Synchronous timeout command processing is handled separately */
+	if (strstr(cmd_buf_ptr, "--timeout") != NULL) {
+		if ((msg_len = shell_timeout_cmd (cmd, sync_file_name) > 0)) {
+			/* Signal end of command output */
+			g_rem_ptr->msg.len = 0;
+			g_rem_ptr->msg.cmd = g_return_stat;
+			remote_tx_response(wl, NULL, 0);
+			return msg_len;
+		} else {
+			/* Parse out --timeout <val> since command is successful
+			 * point buffer to the shell command
+			 */
+			strcpy(cmd, cmd_buf_ptr);
+			strtok_r(cmd, " ", &cmd_buf_ptr);
+			strcpy(cmd, cmd_buf_ptr);
+			strtok_r(cmd, " ", &cmd_buf_ptr);
+		}
+	}
+
+	/* Schedule an ALARM in case of timeout value of SHELL_TIMEOUT seconds */
+	/* Defalut time out only in case of Non socket transport */
+	alarm(g_shellsync_timeout);
+	/* registering the relevant signals to handle end of child process,
+	 * the ctrl+c event on the server side and the kill command on the
+	 * server process
+	 */
+	signal(SIGCHLD, rwl_chld_handler);
+	signal(SIGINT, handle_ctrlc);
+	signal(SIGTERM, handle_ctrlc);
+
+	/* Set g_sig_chld before forking */
+	g_sig_chld = 1;
+
+	if (strcmp("reboot", cmd_buf_ptr) == 0) { /* reboot command */
+		memset(buf, 0, sizeof(buf));
+		strncpy(buf, REBOOT_MSG, sizeof(REBOOT_MSG));
+		remote_tx_response(wl, buf, 0);
+
+		/* Signal end of command output */
+		g_rem_ptr->msg.len = 0;
+		g_rem_ptr->msg.cmd = 0;
+		remote_tx_response(wl, NULL, 0);
+		sleep(1);
+
+		/* Clean up the temp file */
+		remove(sync_file_name);
+	}
+
+	if ((pid = fork()) == 0) {
+		close(STDOUT_FILENO);
+		fd = open(sync_file_name, O_WRONLY|O_SYNC);
+		/* Redirect stdin to dev/null. This handles un usual commands like
+		 * sh cat from the client side
+		 */
+		close(STDIN_FILENO);
+		open("/dev/null", O_RDONLY);
+		close(STDERR_FILENO);
+		fcntl(fd, F_DUPFD, STDERR_FILENO);
+		if ((status = execl(SH_PATH, "sh", "-c", cmd_buf_ptr, NULL)) == -1) {
+			perror("Exec error");
+
+		}
+	} /* end of fork */
+
+	g_shellsync_pid = pid;
+	/* The g_return_stat is being set for short commands */
+	waitpid(g_shellsync_pid, &child_status, WNOHANG);
+	if (WIFEXITED(child_status))
+		g_return_stat = WEXITSTATUS(child_status);
+	else
+		g_return_stat = 1;
+
+	/* Read file in the interim from a temp file and send back the results */
+	fd = open(sync_file_name, O_RDONLY|O_SYNC);
+
+	while (1) {
+		/* read file in the interim and send back the results */
+		nbytes = read(fd, buf, SHELL_RESP_SIZE);
+		g_rem_ptr->msg.len = nbytes;
+		if (nbytes > 0) {
+			remote_tx_response(wl, buf, 0);
+#ifdef RWL_SERIAL
+			/* usleep introduced for flooding of data over serial port */
+			usleep(1);
+#endif
+		}
+		if (get_ctrlc_header(wl) >= 0) {
+			if (g_rem_ptr->msg.flags == (unsigned)CTRLC_FLAG) {
+				uname(&name);
+				/* Checking for mips architecture
+				 * The mips machine responds differently to
+				 * execl command. so the pid is incremented
+				 * to kill the right command.
+				 */
+				if (strncmp(name.machine, "mips", sizeof(name.machine)) == 0)
+					pid++;
+				if (strncmp(name.machine, "armv5tel", sizeof(name.machine)) == 0) {
+					snprintf(cmd_find_lastpid, sizeof(cmd_find_lastpid),
+						"ps | awk \'PRINT $1\' | tail -n 1");
+					if ((fpt = popen(cmd_find_lastpid, "r")) == NULL) {
+						sprintf(buf, "%s\n", "Can't return PID");
+						return BCME_ERROR;
+					}
+					fgets(cmd_find_lastpid, sizeof(cmd_find_lastpid), fpt);
+					pid_final = atoi(cmd_find_lastpid);
+					while (pid <= pid_final) {
+						kill(pid, SIGKILL);
+						pid++;
+					}
+					pclose(fpt);
+				}
+				else {
+					kill(pid, SIGKILL);
+				}
+				break;
+			}
+		}
+		if (get_ctrlc_header(wl) >= 0) {
+			if (g_rem_ptr->msg.flags == (unsigned)CTRLC_FLAG) {
+				uname(&name);
+				/* Checking for mips architecture
+				 * The mips machine responds differently to
+				 * execl command. so the pid is incremented
+				 * to kill the right command.
+				 */
+				if (strncmp(name.machine, "mips", sizeof(name.machine)) == 0) {
+					pid++;
+					kill(pid, SIGKILL);
+				}
+				/* Checking for arm architecture
+				 * The multiple commands would not work
+				 * for ctrl+C. So we kill the processes
+				 * spawned after the parent. This method has
+				 * its own limitations but the busybox in pxa
+				 * doesnot have many options to implement it better
+				 */
+				else {
+					if (strncmp(name.machine, "armv5tel",
+					sizeof(name.machine)) == 0) {
+						/* The command below is used to get the
+						 * PIDs and they are killed
+						 */
+						snprintf(cmd_find_lastpid,
+							sizeof(cmd_find_lastpid),
+							"ps | awk \'PRINT $1\' | tail -n 1");
+						if ((fpt = popen(cmd_find_lastpid, "r")) == NULL) {
+							sprintf(buf, "%s\n", "Can't return PID");
+							return BCME_ERROR;
+						}
+						fgets(cmd_find_lastpid, sizeof(cmd_find_lastpid),
+						fpt);
+						pid_final = atoi(cmd_find_lastpid);
+						while (pid <= pid_final) {
+							kill(pid, SIGKILL);
+							pid++;
+						}
+						pclose(fpt);
+					}
+					/* In the case of x86, on receiving ctrl+C
+					 * the child PIDs are obtained by searching
+					 * the parent PID to obtain the PIDs of the
+					 * and kill them
+					 */
+					else {
+						while (pid != 0) {
+							/* The commad below is used to get the
+							 * child PIDs by using their parent PID
+							 */
+							snprintf(cmd_find_lastpid,
+							sizeof(cmd_find_lastpid),
+							"ps al | awk \"{ if (\\$4 == %d)"
+							" {print \\$3}}\"| head -n 1",
+							g_shellsync_pid);
+							if ((fpt = popen(cmd_find_lastpid, "r"))
+								== NULL) {
+								sprintf(buf, "%s\n",
+									"Can't return PID");
+								return BCME_ERROR;
+							}
+							fgets(cmd_find_lastpid,
+								sizeof(cmd_find_lastpid),
+								fpt);
+							pid = atoi(cmd_find_lastpid);
+							if (pid == 0)
+								kill(g_shellsync_pid, SIGKILL);
+							else
+								kill(pid, SIGKILL);
+							pclose(fpt);
+						}
+					}
+				}
+				break;
+			}
+		}
+		if (set_ctrlc == 1) {
+			g_rem_ptr->msg.len = 0;
+			g_rem_ptr->msg.cmd = g_return_stat;
+			remote_tx_response(wl, NULL, g_return_stat);
+			unlink(sync_file_name);
+			kill(0, SIGKILL);
+		}
+		/* It is possible that the child would have exited
+		 * However we did not get a chance to read the file
+		 * In this case go once again and check the file
+		 */
+		if (!sent_once && !g_sig_chld) {
+			sent_once = 1;
+			continue;
+		}
+
+		if (!(g_sig_chld || nbytes))
+			break;
+	}
+	wait(NULL);
+	close(fd);
+
+	/* Signal end of command output */
+	g_rem_ptr->msg.len = 0;
+	g_rem_ptr->msg.cmd = g_return_stat;
+
+	remote_tx_response(wl, NULL, g_return_stat);
+	/* Cancel the time out alarm if any */
+	alarm(0);
+	sent_once = 0;
+	/* Clean up the temp file */
+	unlink(sync_file_name);
+	g_shellsync_timeout = DEFAULT_SHELL_TIMEOUT;
+	signal(SIGINT, SIG_DFL);
+	signal(SIGTERM, SIG_DFL);
+
+	return BCME_OK;
+}
diff --git a/wl/src/wl/exe/wlu.c b/wl/src/wl/exe/wlu.c
new file mode 100644
index 0000000..a4970fd
--- /dev/null
+++ b/wl/src/wl/exe/wlu.c
@@ -0,0 +1,27474 @@
+/*
+ * Common code for wl command-line swiss-army-knife utility
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu.c 663042 2016-11-30 13:48:19Z $
+ */
+
+
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <wlioctl.h>
+#include <wlioctl_utils.h>
+
+#if !defined(TARGETOS_nucleus)
+#define CLMDOWNLOAD
+#endif
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <typedefs.h>
+#include <epivers.h>
+#include <proto/ethernet.h>
+#include <proto/802.11.h>
+#include <proto/802.1d.h>
+#include <proto/802.11e.h>
+#include <proto/wpa.h>
+#include <proto/bcmip.h>
+#include <proto/wps.h>
+
+#include <bcmwifi_rates.h>
+#include "wlu_rates_matrix.h"
+#include <rte_ioctl.h>
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <bcmwifi_channels.h>
+#include <bcmsrom_fmt.h>
+#include <bcmsrom_tbl.h>
+#include "wlu_common.h"
+#include "wlu.h"
+#include <bcmcdc.h>
+#if defined(linux)
+#ifndef TARGETENV_android
+#include <unistd.h>
+#endif
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#include <time.h>
+#include <sched.h>
+#define TIME_STR_SZ 100 /*  string buffer size for timestamp formatting */
+#endif /* linux */
+#if defined(WLBSSLOAD_REPORT) && defined(linux)
+#include <sys/time.h>
+#endif   /* defined(WLBSSLOAD_REPORT) && defined(linux) */
+
+#ifdef LINUX
+#include <inttypes.h>
+#endif
+#include <miniopt.h>
+#include <errno.h>
+
+#if defined SERDOWNLOAD || defined CLMDOWNLOAD
+#include <sys/stat.h>
+#include <trxhdr.h>
+#ifdef SERDOWNLOAD
+#include <usbrdl.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef WIN32
+#include <fcntl.h>
+#endif /* WIN32 */
+#endif /* SERDOWNLOAD || defined CLMDOWNLOAD */
+
+#if LCNCONF || SSLPNCONF
+#define MAX_CHUNK_LEN 1456  /* 8 * 7 * 26 */
+#else
+#define MAX_CHUNK_LEN 1408 /* 8 * 8 * 22 */
+#endif
+
+#include <bcm_mpool_pub.h>
+#include <proto/bcmipv6.h>
+
+#define EVENT_LOG_DUMPER
+#include <proto/event_log_tag.h>
+
+#include <sdiovar.h>
+
+#include "wlu_subcounters.h"
+
+/* For backwards compatibility, the absense of the define 'NO_FILESYSTEM_SUPPORT'
+ * implies that a filesystem is supported.
+ */
+#if !defined(BWL_NO_FILESYSTEM_SUPPORT)
+#define BWL_FILESYSTEM_SUPPORT
+#endif
+
+#if defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION >= 0x00020000)
+extern int wlu_efi_stat(char *filename, struct stat *filest);
+extern long wlu_efi_ftell(void *fp);
+extern int wlu_efi_fseek(void *fp, long offset, int whence);
+extern size_t wlu_efi_fwrite(void *buf, size_t size, size_t nmemb, void *fp);
+extern size_t wlu_efi_fread(void *buf, size_t size, size_t nmemb, void *fp);
+extern void wlu_efi_fclose(void *fp);
+extern void * wlu_efi_fopen(char *filename, char *mode);
+
+#define fopen(filename, mode)       	(FILE *)wlu_efi_fopen(filename, mode)
+#define fread(buf, size, nmemb, fp) 	wlu_efi_fread(buf, size, nmemb, fp)
+#define fwrite(buf, size, nmemb, fp) 	wlu_efi_fwrite(buf, size, nmemb, fp)
+#define fseek(fp, offset, origin)   	wlu_efi_fseek(fp, offset, origin)
+#define ftell(fp)                   	wlu_efi_ftell(fp)
+#define stat(fname, filest)         	wlu_efi_stat(fname, (struct stat *)(filest))
+#define fclose(fp)                  	wlu_efi_fclose(fp)
+#ifdef stderr
+#undef stderr
+#define stderr stdout
+#endif
+#endif /* defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION >= 0x00020000) */
+
+const char blob_magic_string[] = {'B', 'L', 'O', 'B'};
+
+cmd_func_t wl_int, wl_buf;
+
+const ofdm_rates_t ofdm_rates[] = { /*	6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
+					0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c };
+
+/* ifdef protection since wlc_event_names[] only used under ifdef linux */
+#ifdef linux
+
+#define NAME_ENTRY(x) {x, #x}
+
+static const wlu_name_entry_t wlc_event_names[] = {
+	NAME_ENTRY(WLC_E_SET_SSID),
+	NAME_ENTRY(WLC_E_JOIN),
+	NAME_ENTRY(WLC_E_START),
+	NAME_ENTRY(WLC_E_AUTH),
+	NAME_ENTRY(WLC_E_AUTH_IND),
+	NAME_ENTRY(WLC_E_DEAUTH),
+	NAME_ENTRY(WLC_E_DEAUTH_IND),
+	NAME_ENTRY(WLC_E_ASSOC),
+	NAME_ENTRY(WLC_E_ASSOC_IND),
+	NAME_ENTRY(WLC_E_REASSOC),
+	NAME_ENTRY(WLC_E_REASSOC_IND),
+	NAME_ENTRY(WLC_E_DISASSOC),
+	NAME_ENTRY(WLC_E_DISASSOC_IND),
+	NAME_ENTRY(WLC_E_QUIET_START),
+	NAME_ENTRY(WLC_E_QUIET_END),
+	NAME_ENTRY(WLC_E_BEACON_RX),
+	NAME_ENTRY(WLC_E_LINK),
+	NAME_ENTRY(WLC_E_MIC_ERROR),
+	NAME_ENTRY(WLC_E_NDIS_LINK),
+	NAME_ENTRY(WLC_E_ROAM),
+	NAME_ENTRY(WLC_E_TXFAIL),
+	NAME_ENTRY(WLC_E_PMKID_CACHE),
+	NAME_ENTRY(WLC_E_RETROGRADE_TSF),
+	NAME_ENTRY(WLC_E_PRUNE),
+	NAME_ENTRY(WLC_E_AUTOAUTH),
+	NAME_ENTRY(WLC_E_EAPOL_MSG),
+	NAME_ENTRY(WLC_E_SCAN_COMPLETE),
+	NAME_ENTRY(WLC_E_ADDTS_IND),
+	NAME_ENTRY(WLC_E_DELTS_IND),
+	NAME_ENTRY(WLC_E_BCNSENT_IND),
+	NAME_ENTRY(WLC_E_BCNRX_MSG),
+	NAME_ENTRY(WLC_E_BCNLOST_MSG),
+	NAME_ENTRY(WLC_E_ROAM_PREP),
+	NAME_ENTRY(WLC_E_PFN_NET_FOUND),
+	NAME_ENTRY(WLC_E_PFN_NET_LOST),
+	NAME_ENTRY(WLC_E_RESET_COMPLETE),
+	NAME_ENTRY(WLC_E_JOIN_START),
+	NAME_ENTRY(WLC_E_ROAM_START),
+	NAME_ENTRY(WLC_E_ASSOC_START),
+	NAME_ENTRY(WLC_E_IBSS_ASSOC),
+	NAME_ENTRY(WLC_E_RADIO),
+	NAME_ENTRY(WLC_E_PSM_WATCHDOG),
+	NAME_ENTRY(WLC_E_PROBREQ_MSG),
+	NAME_ENTRY(WLC_E_SCAN_CONFIRM_IND),
+	NAME_ENTRY(WLC_E_PSK_SUP),
+	NAME_ENTRY(WLC_E_COUNTRY_CODE_CHANGED),
+	NAME_ENTRY(WLC_E_EXCEEDED_MEDIUM_TIME),
+	NAME_ENTRY(WLC_E_ICV_ERROR),
+	NAME_ENTRY(WLC_E_UNICAST_DECODE_ERROR),
+	NAME_ENTRY(WLC_E_MULTICAST_DECODE_ERROR),
+	NAME_ENTRY(WLC_E_TRACE),
+	NAME_ENTRY(WLC_E_IF),
+	NAME_ENTRY(WLC_E_P2P_DISC_LISTEN_COMPLETE),
+	NAME_ENTRY(WLC_E_RSSI),
+	NAME_ENTRY(WLC_E_PFN_SCAN_COMPLETE),
+	NAME_ENTRY(WLC_E_EXTLOG_MSG),
+	NAME_ENTRY(WLC_E_ACTION_FRAME),
+	NAME_ENTRY(WLC_E_ACTION_FRAME_COMPLETE),
+	NAME_ENTRY(WLC_E_PRE_ASSOC_IND),
+	NAME_ENTRY(WLC_E_PRE_REASSOC_IND),
+	NAME_ENTRY(WLC_E_CHANNEL_ADOPTED),
+	NAME_ENTRY(WLC_E_AP_STARTED),
+	NAME_ENTRY(WLC_E_DFS_AP_STOP),
+	NAME_ENTRY(WLC_E_DFS_AP_RESUME),
+	NAME_ENTRY(WLC_E_WAI_STA_EVENT),
+	NAME_ENTRY(WLC_E_WAI_MSG),
+	NAME_ENTRY(WLC_E_ESCAN_RESULT),
+	NAME_ENTRY(WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE),
+	NAME_ENTRY(WLC_E_PROBRESP_MSG),
+	NAME_ENTRY(WLC_E_P2P_PROBREQ_MSG),
+	NAME_ENTRY(WLC_E_DCS_REQUEST),
+	NAME_ENTRY(WLC_E_FIFO_CREDIT_MAP),
+	NAME_ENTRY(WLC_E_ACTION_FRAME_RX),
+	NAME_ENTRY(WLC_E_WAKE_EVENT),
+	NAME_ENTRY(WLC_E_RM_COMPLETE),
+	NAME_ENTRY(WLC_E_HTSFSYNC),
+	NAME_ENTRY(WLC_E_OVERLAY_REQ),
+	NAME_ENTRY(WLC_E_CSA_COMPLETE_IND),
+	NAME_ENTRY(WLC_E_EXCESS_PM_WAKE_EVENT),
+	NAME_ENTRY(WLC_E_PFN_SCAN_NONE),
+	NAME_ENTRY(WLC_E_PFN_SCAN_ALLGONE),
+	NAME_ENTRY(WLC_E_GTK_PLUMBED),
+	NAME_ENTRY(WLC_E_ASSOC_IND_NDIS),
+	NAME_ENTRY(WLC_E_REASSOC_IND_NDIS),
+	NAME_ENTRY(WLC_E_ASSOC_REQ_IE),
+	NAME_ENTRY(WLC_E_ASSOC_RESP_IE),
+	{ 0, NULL}
+};
+#endif /* linux */
+
+static cmd_func_t wl_print_deprecate;
+static cmd_func_t wl_rssi, wl_gmode;
+static cmd_func_t wlu_dump, wlu_dump_clr, wlu_mempool, wlu_srdump, wlu_srvar;
+static cmd_func_t wlu_ciswrite, wlu_cisupdate, wlu_cisdump;
+static cmd_func_t wl_rate, wl_rate_mrate, wl_bss_max;
+static cmd_func_t wl_channel, wl_chanspec, wl_rclass, wl_dfs_ap_move, wl_sc_chan;
+static cmd_func_t wl_phy_vcore;
+static cmd_func_t wl_dfs_max_safe_tx;
+static cmd_func_t wl_radio, wl_version, wl_list, wl_band, wl_bandlist, wl_phylist;
+static cmd_func_t wl_join, wl_txpwr, wl_country;
+static cmd_func_t wl_out, wl_txpwr1, wl_country_ie_override, wl_echo;
+static cmd_func_t wl_radar_status, wl_clear_radar_status;
+static cmd_func_t wl_radar_sc_status;
+static cmd_func_t wl_get_pktcnt, wl_upgrade;
+static cmd_func_t wl_default_rateset;
+static cmd_func_t wl_rateset, wl_txbf_rateset;
+static cmd_func_t wl_dfs_status;
+static cmd_func_t wl_dfs_status_all;
+static cmd_func_t wl_get_txpwr_limit, wl_get_current_power;
+static cmd_func_t wl_get_txpwr_target_max, wl_get_chanspec_txpwr_max;
+static cmd_func_t wl_var_getint;
+static cmd_func_t wl_nvdump, wl_nvget, wl_nvset, wl_chan_info;
+static cmd_func_t wl_wme_ac_req, wl_add_ie, wl_del_ie, _wl_list_ie;
+static cmd_func_t wl_wme_apsd_sta, wl_wme_dp, wl_lifetime;
+static cmd_func_t wl_rand;
+static cmd_func_t wl_wlc_ver;
+static cmd_func_t wl_assoc_info, wl_wme_counters;
+static cmd_func_t wl_rxfifo_counters;
+static cmd_func_t wl_eventbitvec, wl_bitvecext;
+static cmd_func_t wl_auto_channel_sel;
+static cmd_func_t wl_msglevel, wl_plcphdr, wl_macreg, wl_band_elm;
+static cmd_func_t wl_rateparam, wl_status, wl_spect;
+static cmd_func_t wl_sup_rateset, wl_scan, wl_send_csa, wl_iscan, wl_escan;
+static cmd_func_t wl_roamparms, wl_roam_prof;
+#ifdef WLRCC
+static cmd_func_t wl_roamchannels;
+#endif /* WLRCC */
+static cmd_func_t wl_dump_chanlist, wl_measure_req, wl_send_quiet;
+static cmd_func_t wl_pm_mute_tx;
+static cmd_func_t wl_dump_chanspecs, wl_dump_chanspecs_defset;
+static cmd_func_t wl_wsec;
+static cmd_func_t wl_channels_in_country;
+static cmd_func_t wl_wpa_auth, wl_deauth_rc, wl_bssid, wl_smfstats;
+static cmd_func_t wl_set_pmk;
+static cmd_func_t wl_rm_request, wl_rm_report;
+static cmd_func_t wl_join_pref, wl_assoc_pref;
+static cmd_func_t wl_dump_networks, wl_revinfo, wl_iov_pktqlog_params;
+static cmd_func_t wl_varstr;
+static cmd_func_t wl_winver;
+
+#if defined(linux)
+static cmd_func_t wl_escan_event_check;
+static cmd_func_t wl_escanresults;
+static cmd_func_t wl_event_check;
+#endif   /* linux */
+
+static cmd_func_t wl_hs20_ie;
+static cmd_func_t wl_reassoc;
+
+static cmd_func_t wl_overlay;
+static cmd_func_t wl_pmkid_info;
+
+
+static void wl_rate_histo_print(wl_mac_ratehisto_res_t *rate_histo_res);
+static cmd_func_t wl_rate_histo;
+static cmd_func_t wl_mac_rate_histo;
+static cmd_func_t wme_tx_params;
+static cmd_func_t wme_maxbw_params;
+
+static cmd_func_t wl_actframe;
+static cmd_func_t wl_antsel;
+static cmd_func_t wl_txfifo_sz;
+
+static cmd_func_t wl_mcast_ar;
+
+static cmd_func_t wl_pwrstats;
+static cmd_func_t wl_memuse;
+
+int wl_seq_batch_in_client(bool enable);
+
+static cmd_func_t wl_antgain;
+static cmd_func_t wl_srchmem;
+static cmd_func_t wl_ptk_start;
+
+#ifdef CLMDOWNLOAD
+static cmd_func_t wl_clmload;
+static cmd_func_t wl_txcapload;
+static cmd_func_t wl_txcapctl;
+static cmd_func_t wl_txcapdump;
+#endif /* CLMDOWNLOAD */
+static cmd_func_t wl_calload;
+static cmd_func_t wl_caldump;
+
+#ifdef RWL_WIFI
+/* Function added to support RWL_WIFI Transport */
+static cmd_func_t wl_wifiserver;
+#endif
+
+static cmd_func_t wl_cca_get_stats;
+static cmd_func_t wl_txdelay_params;
+static cmd_func_t wl_intfer_params;
+
+static cmd_func_t wl_rpmt;
+static cmd_func_t wl_sarlimit;
+static cmd_func_t wl_ie;
+static cmd_func_t wl_ccode_info;
+
+
+#ifdef SERDOWNLOAD
+static cmd_func_t dhd_upload;
+int debug = 0;
+#endif
+static cmd_func_t wl_wds_ap_ifname;
+
+static cmd_func_t wl_staprio;
+static cmd_func_t wl_stamon_sta_config;
+static cmd_func_t wl_monitor_promisc_level;
+static cmd_func_t wl_bcnlenhist;
+static cmd_func_t wl_aibss_bcn_force_config;
+
+#ifdef SR_DEBUG
+static cmd_func_t wl_dump_pmu;
+#endif /* SR_DEBUG */
+
+#ifdef TBTT_OFFSET_STAT
+static cmd_func_t wl_tbtt_offset_stat;
+#endif /* TBTT_OFFSET_STAT */
+
+static cmd_func_t wl_bss_peer_info;
+static cmd_func_t wl_aibss_txfail_config;
+static cmd_func_t wl_setiproute;
+static cmd_func_t wl_desired_bssid;
+static cmd_func_t wl_interface_create_action;
+static cmd_func_t wl_interface_remove_action;
+static cmd_func_t wl_macdbg_pmac;
+static cmd_func_t wl_svmp_mem;
+static cmd_func_t wl_mu_rate;
+static cmd_func_t wl_mu_group;
+static cmd_func_t wl_mu_policy;
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+static cmd_func_t wl_svmp_sampcol;
+#endif 
+static cmd_func_t wl_macregx;
+static cmd_func_t wl_scanmac;
+cmd_func_t wl_hostip;
+cmd_func_t wl_hostipv6_extended;
+static cmd_func_t wl_hc;
+static cmd_func_t wl_wake_timer;
+
+static cmd_func_t wl_idauth;
+static cmd_func_t wl_netx_ifconfig;
+
+static int wl_idauth_config_set(void *wl, uint16 category, char **argv);
+static int wl_idauth_config_get(void *wl, uint16 category, char **argv);
+static int wl_idauth_dump_counters(void *wl, uint16 category, char **argv);
+static int wl_idauth_dump_peer_info(void *wl, uint16 category, char **argv);
+
+static int wlu_dump_phytbls(void *wl, char *dump_buf);
+static int8 wl_ppr_get_pwr(ppr_t* pprptr, reg_rate_index_t rate_idx, wl_tx_bw_t bw);
+static void wl_txpwr_array_row_print(ppr_t* pprptr, int8 channel_bandwidth,
+	reg_rate_index_t rate_idx);
+static void wl_txpwr_array_print(ppr_t* pprptr, int8 channel_bandwidth, bool verbose, bool is5G);
+static void wl_txpwr_ppr_print(ppr_t* pprptr, int vb, ppr_rate_type_t type,
+	clm_rate_group_id_t gid, int8 bw, reg_rate_index_t *rate_index, bool is5G);
+void wl_txpwr_ppr_print_row(const char* label, int8 chains, int8 bw, bool vb,
+	int8** rates, uint rate_index);
+void wl_txpwr_ppr_get_rateset(ppr_t* pprptr, ppr_rate_type_t type,
+	clm_rate_group_id_t gid, wl_tx_bw_t bw, int8* rateset);
+static int wl_array_check_val(int8 *pwr, uint count, int8 val);
+static int wl_parse_rateset(void *wl, wl_rateset_args_t* rs, char **argv);
+static void wl_print_vhtmcsset(uint16 *mcsset);
+static void dump_networks(char *buf);
+static void wl_dump_wpa_rsn_ies(uint8* cp, uint len);
+static void wl_rsn_ie_dump(bcm_tlv_t *ie);
+static void wl_dump_ext_cap(uint8* cp, uint len);
+static void wl_ext_cap_ie_dump(bcm_tlv_t* ext_cap_ie);
+static void free_cca_array(cca_congest_channel_req_t **favg, int favg_chan_elts);
+static int wl_print_dfs_status(wl_dfs_status_t *dfs_status);
+static int wl_print_dfs_sub_status(wl_dfs_sub_status_t *sub);
+static int wl_print_dfs_status_all(wl_dfs_status_all_t *dfs_status_all);
+static int wl_parse_txbf_rateset(wl_txbf_rateset_t *rs, char **argv);
+static void wl_print_txbf_mcsset(char *mcsset, char *prefix);
+static void wl_print_txbf_vhtmcsset(uint16 *mcsset, char *prefix);
+
+static cmd_func_t wl_power_sel_params;
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+static cmd_func_t wl_dump_modesw_dyn_bwsw;
+#endif
+
+int wlu_get(void *wl, int cmd, void *buf, int len);
+int wlu_set(void *wl, int cmd, void *buf, int len);
+
+static cmd_func_t wl_modesw_timecal;
+static cmd_func_t wl_bcntrim_stats;
+static int fsize(void *fp);
+
+typedef struct wl_config_iovar_s wl_config_iovar_t;
+typedef struct nv_s nv_t;
+
+/* 802.11i/WPA RSN IE parsing utilities */
+typedef struct {
+	uint16 version;
+	wpa_suite_mcast_t *mcast;
+	wpa_suite_ucast_t *ucast;
+	wpa_suite_auth_key_mgmt_t *akm;
+	uint8 *capabilities;
+} rsn_parse_info_t;
+
+static int wl_rsn_ie_parse_info(uint8* buf, uint len, rsn_parse_info_t *rsn);
+static uint wl_rsn_ie_decode_cntrs(uint cntr_field);
+typedef void (wl_config_print_func_t)(wl_config_iovar_t *config_iovar,
+	wl_config_t *config);
+static void wl_bcm_config_print(wl_config_iovar_t *cfg_iovar, wl_config_t *cfg);
+static int wl_parse_assoc_params(char **argv, wl_assoc_params_t *params, bool *prescanned);
+static int wl_join_prescanned(void *wl, wl_join_params_t *join_params, uint *join_params_size);
+#define wl_parse_reassoc_params(argv, params) wl_parse_assoc_params(argv, \
+						(wl_assoc_params_t *)(params), NULL)
+
+static uint16 wl_qdbm_to_mw(int8 qdbm);
+static int8 wl_mw_to_qdbm(uint16 mw);
+
+static void wl_printrate(int val);
+static int wl_get_iscan(void *wl, char *buf, uint buf_len);
+int wlu_var_setbuf(void *wl, const char *iovar, void *param, int param_len);
+int wlu_iovar_get(void *wl, const char *iovar, void *outbuf, int len);
+int wlu_iovar_set(void *wl, const char *iovar, void *param, int paramlen);
+int wlu_iovar_getint(void *wl, const char *iovar, int *pval);
+int wlu_iovar_setint(void *wl, const char *iovar, int val);
+static int wl_bssiovar_mkbuf(const char *iovar, int bssidx, void *param,
+	int paramlen, void *bufptr, int buflen, int *perr);
+int wlu_bssiovar_setbuf(void* wl, const char *iovar, int bssidx,
+	void *param, int paramlen, void *bufptr, int buflen);
+static int wl_bssiovar_getbuf(void* wl, const char *iovar, int bssidx,
+	void *param, int paramlen, void *bufptr, int buflen);
+static int wl_bssiovar_set(void *wl, const char *iovar, int bssidx, void *param, int paramlen);
+int wlu_bssiovar_get(void *wl, const char *iovar, int bssidx, void *outbuf, int len);
+static int wl_bssiovar_setint(void *wl, const char *iovar, int bssidx, int val);
+static int wl_bssiovar_getint(void *wl, const char *iovar, int bssidx, int *pval);
+static int wl_vndr_ie(void *wl, const char *command, uint32 pktflag_ok, char **argv);
+static void wl_dump_ie_buf(vndr_ie_buf_t *ie_getbuf);
+static void wl_join_pref_print_ie(bcm_tlv_t *ie);
+static void wl_join_pref_print_akm(uint8* suite);
+static void wl_join_pref_print_cipher_suite(uint8* suite);
+
+static int wl_assertlog(void *wl, cmd_t *cmd, char **argv);
+static int wl_tsf(void *wl, cmd_t *cmd, char **argv);
+
+static cmd_func_t wl_scb_bs_data;
+
+static int wl_dfs_channel_forced(void *wl, cmd_t *cmd, char **argv);
+static int wl_event_log_set_init(void *wl, cmd_t *cmd, char **argv);
+static int wl_event_log_set_expand(void *wl, cmd_t *cmd, char **argv);
+static int wl_event_log_set_shrink(void *wl, cmd_t *cmd, char **argv);
+static int wl_event_log_tag_control(void *wl, cmd_t *cmd, char **argv);
+static int wl_event_log_get(void *wl, cmd_t *cmd, char **argv);
+static int wl_sleep_ret_ext(void *wl, cmd_t *cmd, char **argv);
+
+static cmd_func_t wl_pcie_bus_throughput_params;
+
+static cmd_func_t wl_phy_txpwrcap_tbl;
+static cmd_func_t wl_sim_pm;
+static cmd_func_t wl_utrace_capture;
+
+#ifdef ATE_BUILD
+static cmd_func_t wl_gpaio;
+#endif
+
+
+static cmd_func_t wl_nd_ra_limit_intv;
+
+static void dlystat_dump(txdelay_stats_t *txdelay_stats);
+static int wl_dlystats(void *wl, cmd_t *cmd, char **argv);
+static int wl_dlystats_clear(void *wl, cmd_t *cmd, char **argv);
+
+static int wl_get_tcmstbl_entry(void *wl, cmd_t *cmd, char **argv);
+
+char *ver2str(unsigned int vms, unsigned int vls);
+
+#define BCM_CONFIG_ARRAY_SIZE 10
+
+#define OUI_STR_SIZE	8	/* OUI string size */
+#define MAX_OUI_SIZE	3	/* MAX  OUI size */
+#define MAX_BYTE_CHARS	2	/* MAX num chars */
+#define MAX_DATA_COLS	16	/* MAX data cols */
+
+#define RADIO_CORE_SYN                           (0x0 << 12)
+#define RADIO_CORE_TX0                           (0x2 << 12)
+#define RADIO_CORE_TX1                           (0x3 << 12)
+#define RADIO_CORE_RX0                           (0x6 << 12)
+#define RADIO_CORE_RX1                           (0x7 << 12)
+#define RADIO_CORE_CR0                           (0x0 << 10)
+#define RADIO_CORE_CR1                           (0x1 << 10)
+#define RADIO_CORE_CR2                           (0x2 << 10)
+#define RADIO_CORE_ALL                           (0x3 << 10)
+#define RADIO_2069_CORE_CR0                      (0x0 << 9)
+#define RADIO_2069_CORE_CR1                      (0x1 << 9)
+#define RADIO_2069_CORE_CR2                      (0x2 << 9)
+#define RADIO_2069_CORE_ALL                      (0x3 << 9)
+#define RADIO_2069_CORE_PLL                      (0x4 << 9)
+#define RADIO_2069_CORE_PLL0                     (0x4 << 9)
+#define RADIO_2069_CORE_PLL1                     (0x5 << 9)
+
+#define NUM_CHANSPECS_LIST_SIZE	110 /* chanspecs list size passed to driver */
+
+/* IOCtl version read from targeted driver */
+static int ioctl_version;
+
+/* 64 bits aligned allocation */
+static union {
+	char bufdata[WLC_IOCTL_MAXLEN];
+	uint64 alignme;
+} bufstruct_wlu;
+static char *buf = (char*) &bufstruct_wlu.bufdata;
+
+/* integer output format, default to signed integer */
+static uint8 int_fmt;
+
+/*
+ * Country names and abbreviations from ISO 3166
+ */
+typedef struct {
+	const char *name;	/* Long name */
+	const char *abbrev;	/* Abbreviation */
+} cntry_name_t;
+cntry_name_t cntry_names[];	/* At end of this file */
+
+struct nv_s {
+	char *name;
+	uint32 value;
+};
+
+struct wl_config_iovar_s {
+	char *iovar_name;
+	wl_config_print_func_t *pfunc;
+	nv_t params[BCM_CONFIG_ARRAY_SIZE];
+};
+
+typedef struct {
+	uint value;
+	const char *string;
+} monitor_promisc_level_msg_t;
+
+
+#define WL_SCAN_PARAMS_SSID_MAX 10
+
+#define RATE_2G_USAGE							\
+"\tEither \"auto\", or a simple CCK/DSSS/OFDM rate value:\n"		\
+"\t1 2 5.5 11 6 9 12 18 24 36 48 54\n\n"				\
+"\tOr options to specify legacy, HT, or VHT rate:\n"			\
+"\t-r R, --rate=R        : legacy rate (CCK, DSSS, OFDM)\n"		\
+"\t-h M, --ht=M          : HT MCS index [0-23]\n"			\
+"\t-v M[xS], --vht=M[xS] : VHT MCS index M [0-9],\n"			\
+"\t                      : and optionally Nss S [1-8], eg. 5x2 is MCS=5, Nss=2\n" \
+"\t-c cM[sS]             : VHT (c notation) MCS index M [0-9],\n"			\
+"\t                      : and optionally Nss S [1-8], eg. c5s2 is MCS=5, Nss=2\n" \
+"\t-s S, --ss=S          : VHT Nss [1-8], number of spatial streams, default 1.\n" \
+"\t                      : Only used with -v/--vht when MxS format is not used\n" \
+"\t-x T, --exp=T         : Tx Expansion, number of tx chains (NTx) beyond the minimum\n" \
+"\t                      : required for the space-time-streams, exp = NTx - Nsts\n" \
+"\t--stbc                : Use STBC expansion, otherwise no STBC\n"	\
+"\t-l, --ldpc            : Use LDPC encoding, otherwise no LDPC\n"	\
+"\t-g, --sgi             : SGI, Short Guard Interval, otherwise standard GI\n" \
+"\t-b, --bandwidth       : transmit bandwidth MHz; 2.5, 5, 10, 20, 40, 80, 160"
+
+#define RATE_5G_USAGE							\
+"\tEither \"auto\", or a simple OFDM rate value:\n"			\
+"\t6 9 12 18 24 36 48 54\n\n"						\
+"\tOr options to specify legacy OFDM, HT, or VHT rate:\n"		\
+"\t-r R, --rate=R        : legacy OFDM rate\n"				\
+"\t-h M, --ht=M          : HT MCS index [0-23]\n"			\
+"\t-v M[xS], --vht=M[xS] : VHT MCS index M [0-9],\n"			\
+"\t                      : and optionally Nss S [1-8], eg. 5x2 is MCS=5, Nss=2\n" \
+"\t-c cM[sS]             : VHT (c notation) MCS index M [0-9],\n"			\
+"\t                      : and optionally Nss S [1-8], eg. c5s2 is MCS=5, Nss=2\n" \
+"\t-s S, --ss=S          : VHT Nss [1-8], number of spatial streams, default 1.\n" \
+"\t                      : Only used with -v/--vht when MxS format is not used\n" \
+"\t-x T, --exp=T         : Tx Expansion, number of tx chains (NTx) beyond the minimum\n" \
+"\t                      : required for the space-time-streams, exp = NTx - Nsts\n" \
+"\t--stbc                : Use STBC expansion, otherwise no STBC\n"	\
+"\t-l, --ldpc            : Use LDPC encoding, otherwise no LDPC\n"	\
+"\t-g, --sgi             : SGI, Short Guard Interval, otherwise standard GI\n" \
+"\t-b, --bandwidth       : transmit bandwidth MHz; 2.5, 5, 10, 20, 40, 80, 160"
+
+#define TXBF_RATESET_USAGE						\
+"Get rateset consisting of OFDM, HT and VHT rates, and Broadcom-to-Broadcom\n" \
+"\tgroup of OFDM, HT and VHT rates by issuing command with no arguments.\n" \
+"\tOFDM rates printed are in Mbps, and each Basic rate in OFDM list is marked\n" \
+"\tby (b) behind it.  Example: full list of OFDM rates:\n" \
+"\t\t6(b) 9 12(b) 18 24(b) 36 48 54\n" \
+"\twhere 6, 12 and 24 are Basic rates.\n" \
+"\n" \
+"\tSet synopsis:\n" \
+"\t\twl txbf_rateset < [ofdm_rate_list] [options ...] >\n" \
+"\tOFDM rate specification does not need to mark Basic rates because Basic\n" \
+"\trates are automatically recognized.\n" \
+"\tOptions are processed in order; thus redundant instances of an option will\n" \
+"\tresult in only the last instance taking effect for that option.\n" \
+"\tOptions:\n" \
+"\t-m <MCS_bitmask> ...\n" \
+"\t\tSet HT rates by bitmask bytes, each ranges from 00 through ff, where\n" \
+"\t\tthe least significant bit is MCS0.\n" \
+"\t\tExample: '-m 3f 01' specifies HT rates MCS0 - MCS5 and MCS8.\n" \
+"\n" \
+"\t-v <VHT_bitmask> ...\n" \
+"\t\tSet VHT rates for each supported count of spatial streams.\n" \
+"\t\tExample: '-v 3ff 1ff ff' specifies VHT rates: MCS0 - MCS9 for 1 stream,\n" \
+"\t\tMCS0 - MCS8 for 2 streams, and MCS0 - MCS7 for 3 streams.\n" \
+"\n" \
+"\t-b\n" \
+"\t\tSet for Broadcom-to-Broadcom group of rates.  Otherwise without\n" \
+"\t\tthe -b option, the standard group of rates are set accordingly.\n"
+
+#define MONITOR_PROMISC_LEVEL_USAGE	\
+"\tUsage: wl monitor_promisc_level [<bitmap> | <+|-name>]\n" \
+"\tbitmap values and corresponding name are the following:\n" \
+"\tArgs:\n" \
+"\t\tbit:0:promisc: " \
+"When set, address filter accepts all received frames." \
+"When cleared, the address filter accepts only those frames " \
+"that match the BSSID or local MAC address\n" \
+"\t\tbit:1:ctrl: " \
+"When set, the RX filter accepts all received control frames " \
+"that are accepted by the address filter. " \
+"When cleared, the RX filter rejects all control frames other " \
+"than PS poll frames." \
+"\t\tbit:3:fcs: " \
+"When set, the RX filter forwards received frames with FCS " \
+"errors to the driver." \
+"When cleared, frames with FCS errors are discarded.\n\n" \
+"\tExample: wl monitor_promisc_level +promisc\n" \
+"\tExample: wl monitor_promisc_level 0x2\n" \
+"\tExample: wl monitor_promisc_level 0"
+
+/* the default behavior is batching in driver,
+ * to indicate client batching, users should specify --interactive and --clientbatch
+ */
+static bool batch_in_client;
+
+/* The wl_config_iovar_list structure is used to define config iovars. Config iovars can be in
+ * either an auto mode or in an override mode. If it is in auto mode, the status of the iovar
+ * is determined automatically. In override mode, the status is passed as a parameter to the
+ * iovar. If a new config iovar is getting added, it can either reuse the last entry in the
+ * list if parameters match, or add a new entry. If you are adding a new entry, make sure it is
+ * added before the last entry.
+ * In each row, the last entry of name-value params must have NULL
+ */
+wl_config_iovar_t wl_config_iovar_list[] = {
+	{ "rsdb_mode", wl_bcm_config_print, {{"auto", -1}, {"mimo", 0}, {"rsdb", 1}, {"80p80", 2},
+	{NULL, 0}}},
+	{ NULL, wl_bcm_config_print, {{"auto", -1}, {"off", 0}, {"disable", 0}, {"on", 1},
+	{"enable", 1}, {NULL, 0}}},
+};
+
+/* If the new command needs to be part of 'wc.exe' tool used for WMM,
+ * be sure to modify wc_cmds[] array as well
+ *
+ * If you add a command, please update wlu_cmd.c cmd2cat to categorize the command.
+ */
+cmd_t wl_cmds[] = {
+	{ "debug_crash", wlu_reg2args, WLC_GET_VAR, WLC_SET_VAR,
+	"debug crash - TYPE DELAYED"},
+	{ "winver", wl_winver, -1, -1,
+	"get Windows OS and driver version information" },
+	{ "ver", wl_version, -1, -1,
+	"get version information" },
+	{ "cmds", wl_list, -1, -1,
+	"generate a short list of available commands"},
+	{ "ioctl_echo",	wl_echo, -1, WLC_ECHO,
+	"check ioctl functionality" },
+	{ "up",	wl_void, -1, WLC_UP,
+	"reinitialize and mark adapter up (operational)" },
+	{ "down", wl_void, -1, WLC_DOWN,
+	"reset and mark adapter down (disabled)" },
+	{ "out", wl_out, -1, WLC_OUT,
+	"mark adapter down but do not reset hardware(disabled)\n"
+	"\tOn dualband cards, cards must be bandlocked before use."},
+	{ "clk", wl_int, WLC_GET_CLK, WLC_SET_CLK,
+	"set board clock state. return error for set_clk attempt if the driver is not down\n"
+	"\t0: clock off\n"
+	"\t1: clock on" },
+	{ "reboot", wl_void, -1, WLC_REBOOT,
+	"Reboot platform"},
+	{ "radio", wl_radio, WLC_GET_RADIO, WLC_SET_RADIO,
+	"Set the radio on or off.\n"
+	"\t\"on\" or \"off\"" },
+	{ "dump", wlu_dump, WLC_GET_VAR, -1,
+	"Give suboption \"list\" to list various suboptions" },
+	{ "dump_clear", wlu_dump_clr, -1, WLC_SET_VAR,
+	"Clear a specific category of counters/stats.\n"
+	"\tUsage: dump_clear <category-name>\n"},
+	{ "srclear", wlu_srwrite, -1, WLC_SET_SROM,
+	"Clears first 'len' bytes of the srom, len in decimal or hex\n"
+	"\tUsage: srclear <len>" },
+	{ "srdump", wlu_srdump, WLC_GET_SROM, -1,
+	"print contents of SPROM to stdout" },
+	{ "srwrite", wlu_srwrite, -1, WLC_SET_SROM,
+	"Write the srom: srwrite byteoffset value" },
+	{ "ciswrite", wlu_ciswrite, -1, WLC_SET_VAR,
+	"Write specified <file> to the SDIO/PCIe CIS source (either SROM or OTP)"
+	"\tUsage: ciswrite [-p|--pciecis] <file>\n"
+	"\t-p|--pciecis -- Write OTP for PCIe full-dongle"},
+	{ "cisupdate", wlu_cisupdate, -1, WLC_SET_VAR,
+	"Write a hex byte stream to specified byte offset to the CIS source (either SROM or OTP)\n"
+	"--preview option allows you to review the update without committing it\n"
+	"\t<byte offset> <hex byte stream> [--preview]" },
+	{ "cisdump", wlu_cisdump, WLC_GET_VAR, -1,
+	"Display the content of the SDIO CIS source\n"
+	"\t-b <file> -- also write raw bytes to <file>\n"
+	"\t<len> -- optional count of bytes to display (must be even)"},
+	{ "cisconvert", wlu_srvar, -1, -1,
+	"Print CIS tuple for given name=value pair" },
+	{ "rdvar", wlu_srvar, WLC_GET_SROM, -1,
+	"Read a named variable to the srom" },
+	{ "wrvar", wlu_srvar, WLC_GET_SROM, WLC_SET_SROM,
+	"Write a named variable to the srom" },
+	{ "nvram_dump", wl_nvdump, WLC_NVRAM_DUMP, -1,
+	"print nvram variables to stdout" },
+	{ "nvset", wl_nvset, -1, WLC_NVRAM_SET,
+	"set an nvram variable\n"
+	"\tname=value (no spaces around \'=\')" },
+	{ "nvget", wl_nvget, WLC_NVRAM_GET, -1,
+	"get the value of an nvram variable" },
+	{ "nvram_get", wl_nvget, WLC_NVRAM_GET, -1,
+	"get the value of an nvram variable" },
+	{ "revinfo", wl_revinfo, WLC_GET_REVINFO, -1,
+	"get hardware revision information" },
+	{ "msglevel", wl_msglevel, WLC_GET_VAR, WLC_SET_VAR,
+	"set driver console debugging message bitvector\n"
+	"\ttype \'wl msglevel ?\' for values" },
+	{ "PM", wl_int, WLC_GET_PM, WLC_SET_PM,
+	"set driver power management mode:\n"
+	"\t0: CAM (constantly awake)\n"
+	"\t1: PS  (power-save)\n"
+	"\t2: FAST PS mode" },
+	{ "wake", wl_int, WLC_GET_WAKE, WLC_SET_WAKE,
+	"set driver power-save mode sleep state:\n"
+	"\t0: core-managed\n"
+	"\t1: awake" },
+	{ "promisc", wl_int, WLC_GET_PROMISC, WLC_SET_PROMISC,
+	"set promiscuous mode ethernet address reception\n"
+	"\t0 - disable\n"
+	"\t1 - enable" },
+	{ "monitor", wl_int, WLC_GET_MONITOR, WLC_SET_MONITOR,
+	"set monitor mode\n"
+	"\t0 - disable\n"
+	"\t1 - enable active monitor mode (interface still operates)" },
+	{ "frag", wl_print_deprecate, -1, -1, "Deprecated. Use fragthresh." },
+	{ "rts", wl_print_deprecate, -1, -1, "Deprecated. Use rtsthresh." },
+	{ "cwmin", wl_int, WLC_GET_CWMIN, WLC_SET_CWMIN,
+	"Set the cwmin.  (integer [1, 255])" },
+	{ "cwmax", wl_int, WLC_GET_CWMAX, WLC_SET_CWMAX,
+	"Set the cwmax.  (integer [256, 2047])" },
+	{ "srl", wl_int, WLC_GET_SRL, WLC_SET_SRL,
+	"Set the short retry limit.  (integer [1, 255])" },
+	{ "lrl", wl_int, WLC_GET_LRL, WLC_SET_LRL,
+	"Set the long retry limit.  (integer [1, 255])" },
+	{ "rate", wl_rate_mrate, WLC_GET_RATE, -1,
+	"force a fixed rate:\n"
+	"\tvalid values for 802.11a are (6, 9, 12, 18, 24, 36, 48, 54)\n"
+	"\tvalid values for 802.11b are (1, 2, 5.5, 11)\n"
+	"\tvalid values for 802.11g are (1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "mrate", wl_rate_mrate, -1, -1, /* Deprecated. Use "bg_mrate" or "a_mrate" */
+	"force a fixed multicast rate:\n"
+	"\tvalid values for 802.11a are (6, 9, 12, 18, 24, 36, 48, 54)\n"
+	"\tvalid values for 802.11b are (1, 2, 5.5, 11)\n"
+	"\tvalid values for 802.11g are (1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "a_rate", wl_phy_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"force a fixed rate for the A PHY:\n"
+	"\tvalid values for 802.11a are (6, 9, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "a_mrate", wl_phy_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"force a fixed multicast rate for the A PHY:\n"
+	"\tvalid values for 802.11a are (6, 9, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "bg_rate", wl_phy_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"force a fixed rate for the B/G PHY:\n"
+	"\tvalid values for 802.11b are (1, 2, 5.5, 11)\n"
+	"\tvalid values for 802.11g are (1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "bg_mrate", wl_phy_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"force a fixed multicast rate for the B/G PHY:\n"
+	"\tvalid values for 802.11b are (1, 2, 5.5, 11)\n"
+	"\tvalid values for 802.11g are (1, 2, 5.5, 6, 9, 11, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate" },
+	{ "2g_rate", wl_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Force a fixed rate for data frames in the 2.4G band:\n\n"
+	RATE_2G_USAGE
+	},
+	{ "2g_mrate", wl_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Force a fixed rate for mulitcast/broadcast data frames in the 2.4G band:\n\n"
+	RATE_2G_USAGE
+	},
+	{ "5g_rate", wl_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Force a fixed rate for data frames in the 5G band:\n\n"
+	RATE_5G_USAGE
+	},
+	{ "5g_mrate", wl_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Force a fixed rate for mulitcast/broadcast data frames in the 5G band:\n\n"
+	RATE_5G_USAGE
+	},
+	{ "infra", wl_int, WLC_GET_INFRA, WLC_SET_INFRA,
+	"Configure BSS type or query Infra mode.\n"
+	"Configure BSS type for next BSS Start or Join operation:\n"
+	"\t0 (IBSS)\n"
+	"\t1 (Infra BSS)\n"
+	"\t2 (Any BSS, for Join only)\n"
+	"\t3 (Mesh BSS)\n"
+	"Query the Infra mode of the current BSS:\n"
+	"\t0 (IBSS)\n"
+	"\t1 (Infra BSS)\n"
+	"Note: use \"wl infra_configuration\" to query the configuration.\n"},
+	{ "bssid", wl_bssid, WLC_GET_BSSID, -1,
+	"Get the BSSID value, error if STA and not associated"},
+	{ "bssmax", wl_bss_max, WLC_GET_VAR, -1,
+	"get number of BSSes " },
+	{ "channel", wl_channel, WLC_GET_CHANNEL, WLC_SET_CHANNEL,
+	"Set the channel:\n"
+	"\tvalid channels for 802.11b/g (2.4GHz band) are 1 through 14\n"
+	"\tvalid channels for 802.11a  (5 GHz band) are:\n"
+	"\t\t36, 40, 44, 48, 52, 56, 60, 64,\n"
+	"\t\t100, 104, 108, 112, 116,120, 124, 128, 132, 136, 140, 144,\n"
+	"\t\t149, 153, 157, 161,\n"
+	"\t\t184, 188, 192, 196, 200, 204, 208, 212, 216"},
+	{ "clmver", wl_var_getandprintstr, WLC_GET_VAR, -1,
+	"Get version information for CLM data and tools"},
+	{ "roam_channels_in_cache", wl_dump_chanspecs, WLC_GET_VAR, -1,
+	"Get a list of channels in roam cache" },
+	{ "roam_channels_in_hotlist", wl_dump_chanspecs, WLC_GET_VAR, -1,
+	"Get a list of channels in roam hot channel list" },
+	{ "chanspecs", wl_dump_chanspecs, WLC_GET_VAR, -1,
+	"Get all the valid chanspecs (default: all within current locale):\n"
+	"\t-b band (5(a) or 2(b/g))\n"
+	"\t-w bandwidth, 20, 40, 80, 160, or 80+80\n"
+	"\t[-c country_abbrev]"
+	},
+	{ "chanspecs_defset", wl_dump_chanspecs_defset, WLC_GET_VAR, -1,
+	"Get default chanspecs for current driver settings (default: all within current locale)"
+	},
+	{ "chanspec", wl_chanspec, WLC_GET_VAR, WLC_SET_VAR,
+	"Set current or configured channel:\n"
+	"\t20MHz : [2g|5g]<channel>[/20]\n"
+	"\t40MHz : [2g|5g]<channel>/40[u,l]\n"
+	"\t80MHz :    [5g]<channel>/80\n"
+	"\t160MHz:    [5g]<channel>/160\n"
+	"\t80+80MHz:  [5g]<channel>/80+80/<1st80channel>-<2nd80channel>\n"
+	"\toptional band 2g or 5g, default to 2g if channel <= 14\n"
+	"\tchannel number (0-200)\n"
+	"\tbandwidth, 2.5, 5, 10, 20, 40, 80, 160, or 80+80 default 20\n"
+	"\tprimary sideband for 40MHz on 2g, l=lower, u=upper\n"
+	"\t<1st80Channel>, <2nd80Channel> Required for 80+80, otherwise not allowed. "
+	"These fields specify the center channel of the first and second 80MHz band.\n"
+	"OR Set channel with legacy format:\n"
+	"\t-c channel number (0-224)\n"
+	"\t-b band (5(a) or 2(b/g))\n"
+	"\t-w bandwidth 20 or 40\n"
+	"\t-s ctl sideband, -1=lower, 0=none, 1=upper"},
+	{ "sc_chan", wl_sc_chan, WLC_GET_VAR, WLC_SET_VAR,
+	"Set current or configured channel:\n"
+	"\t20MHz : [2g|5g]<channel>[/20]\n"
+	"\t40MHz : [2g|5g]<channel>/40[u,l]\n"
+	"\t80MHz :    [5g]<channel>/80\n"
+	"\toptional band 2g or 5g, default to 2g if channel <= 14\n"
+	"\tchannel number (0-200)\n"
+	"\tbandwidth, 2.5, 5, 10, 20, 40, or 80, default 20\n"
+	"\tprimary sideband for 40MHz on 2g, l=lower, u=upper\n"
+	"OR Set channel with legacy format:\n"
+	"\t-c channel number (0-224)\n"
+	"\t-b band (5(a) or 2(b/g))\n"
+	"\t-w bandwidth 20 or 40\n"
+	"\t-s ctl sideband, -1=lower, 0=none, 1=upper"},
+	{ "phy_vcore", wl_phy_vcore, WLC_GET_VAR, -1,
+	"get virtual core related capabilities\n"},
+	{ "rclass", wl_rclass, WLC_GET_VAR, -1,
+	"Get operation class:\n"
+	"\t chanspec \n"},
+	{ "dfs_channel_forced", wl_dfs_channel_forced, WLC_GET_VAR, WLC_SET_VAR,
+	"Set <channel>[a,b][n][u,l]\n"
+	"\tchannel number (0-224)\n"
+	"\tband a=5G, b=2G, default to 2G if channel <= 14\n"
+	"\tbandwidth, n=10, non for 20 & 40\n"
+	"\tctl sideband, l=lower, u=upper\n"
+	"Set channel list using -l option \n"
+	"\twl dfs_channel_forced {-l <chanspec list> | 0}\n"
+	"\t20MHz : <channel>[/20]\n"
+	"\t40MHz : <channel>{{l|u}|/40}\n"
+	"\t80MHz : <channel>/80\n"
+	"\tChannels specified using '-l' option should be\n"
+	"seperated by ','/' ' and should be prefixed with '+'/'-'\n"
+	"Deletes existing configuration when '0' specified"},
+	{ "txpwr", wl_txpwr, -1, -1, /* Deprecated. Use "txpwr1" */
+	"Set tx power in milliwatts.  Range [1, 84]." },
+	{ "txpwr1", wl_txpwr1, WLC_GET_VAR, WLC_SET_VAR,
+	"Set tx power in in various units. Choose one of (default: dBm): \n"
+	"\t-d dBm units (range: -32 - 31)\n"
+	"\t-q quarter dBm units (range: -128 - 127)\n"
+	"\t-m milliwatt units\n"
+	"Can be combined with:\n"
+	"\t-o turn on override to disable regulatory and other limitations\n"
+	"Use wl txpwr -1 to restore defaults"},
+	{ "txpwrlimit", wl_get_txpwr_limit, WLC_CURRENT_PWR, -1,
+	"Return current tx power limit" },
+	{ "ucflags", wl_reg, WLC_GET_UCFLAGS, WLC_SET_UCFLAGS,
+	"Get/Set ucode flags 1, 2, 3(16 bits each)\n"
+	"\toffset [ value ] [ band ]" },
+	{ "shmem", wl_reg, WLC_GET_SHMEM, WLC_SET_SHMEM,
+	"Get/Set a shared memory location:\n"
+	"\toffset [ value ] [band ]" },
+	{ "macreg", wl_macreg, WLC_R_REG, WLC_W_REG,
+	"Get/Set any mac registers(include IHR and SB):\n"
+	"\tmacreg offset size[2,4] [ value ] [ band ]" },
+	{ "shmemx", wl_macregx, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set a shared memory location of PSMX:\n"
+	"\toffset [ value ] [band ]" },
+	{ "macregx", wl_macregx, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set any mac registers(include IHR and SB) of PSMX:\n"
+	"\tmacreg offset size[2,4] [ value ] [ band ]" },
+	{ "ucantdiv", wl_int, WLC_GET_UCANTDIV, WLC_SET_UCANTDIV,
+	"Enable/disable ucode antenna diversity (1/0 or on/off)" },
+	{ "actframe", wl_actframe, -1, WLC_SET_VAR,
+	"Send a Vendor specific Action frame to a channel\n"
+	"\tusage: wl actframe <Dest Mac Addr> <data> channel dwell-time <BSSID>" },
+	{ "antdiv", wl_int, WLC_GET_ANTDIV, WLC_SET_ANTDIV,
+	"Set antenna diversity for rx\n"
+	"\t0 - force use of antenna 0\n"
+	"\t1 - force use of antenna 1\n"
+	"\t3 - automatic selection of antenna diversity" },
+	{ "txant", wl_int, WLC_GET_TXANT, WLC_SET_TXANT,
+	"Set the transmit antenna\n"
+	"\t0 - force use of antenna 0\n"
+	"\t1 - force use of antenna 1\n"
+	"\t3 - use the RX antenna selection that was in force during\n"
+	"\t    the most recently received good PLCP header" },
+	{ "plcphdr", wl_plcphdr, WLC_GET_PLCPHDR, WLC_SET_PLCPHDR,
+	"Set the plcp header.\n"
+	"\t\"long\" or \"auto\" or \"debug\"" },
+	{ "phytype", wl_int, WLC_GET_PHYTYPE, -1,
+	"Get phy type" },
+	{ "rateparam", wl_rateparam, -1, WLC_SET_RATE_PARAMS,
+	"set driver rate selection tunables\n"
+	"\targ 1: tunable id\n"
+	"\targ 2: tunable value" },
+	{ "wsec_restrict", wl_bsscfg_int, WLC_GET_WEP_RESTRICT, WLC_SET_WEP_RESTRICT,
+	"Drop unencrypted packets if WSEC is enabled\n"
+	"\t0 - disable\n"
+	"\t1 - enable" },
+	{ "eap", wl_int, WLC_GET_EAP_RESTRICT, WLC_SET_EAP_RESTRICT,
+	"restrict traffic to 802.1X packets until 802.1X authorization succeeds\n"
+	"\t0 - disable\n"
+	"\t1 - enable" },
+	{ "cur_etheraddr", wl_iov_mac, -1, -1,
+	"Get/set the current hw address" },
+	{ "perm_etheraddr", wl_iov_mac, -1, -1,
+	"Get the permanent address from NVRAM" },
+	{ "authorize", wl_macaddr, -1, WLC_SCB_AUTHORIZE,
+	"restrict traffic to 802.1X packets until 802.1X authorization succeeds" },
+	{ "deauthorize", wl_macaddr, -1, WLC_SCB_DEAUTHORIZE,
+	"do not restrict traffic to 802.1X packets until 802.1X authorization succeeds" },
+	{ "deauthenticate", wl_deauth_rc, -1, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
+	"deauthenticate a STA from the AP with optional reason code (AP ONLY)" },
+	{ "wsec", wl_wsec, WLC_GET_WSEC, WLC_SET_WSEC,
+	"wireless security bit vector\n"
+	"\t1 - WEP enabled\n"
+	"\t2 - TKIP enabled\n"
+	"\t4 - AES enabled\n"
+	"\t8 - WSEC in software\n"
+	"\t0x80 - FIPS enabled\n"
+	"\t0x100 - WAPI enabled"
+	},
+	{ "auth", wl_bsscfg_int, WLC_GET_AUTH, WLC_SET_AUTH,
+	"set/get 802.11 authentication type. 0 = OpenSystem, 1= SharedKey, 3=Open/Shared" },
+	{ "wpa_auth", wl_wpa_auth, WLC_GET_WPA_AUTH, WLC_SET_WPA_AUTH,
+	"Bitvector of WPA authorization modes:\n"
+	"\t1	WPA-NONE\n"
+	"\t2	WPA-802.1X/WPA-Professional\n"
+	"\t4	WPA-PSK/WPA-Personal\n"
+	"\t64	WPA2-802.1X/WPA2-Professional\n"
+	"\t128	WPA2-PSK/WPA2-Personal\n"
+	"\t0	disable WPA"
+	},
+	{ "wpa_cap", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get 802.11i RSN capabilities" },
+	{ "set_pmk", wl_set_pmk, -1, WLC_SET_WSEC_PMK,
+	"Set passphrase for PMK in driver-resident supplicant." },
+	{ "scan", wl_scan, -1, WLC_SCAN,
+	"Initiate a scan.\n" SCAN_USAGE
+	},
+	{ "roamscan_parms", wl_roamparms, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get roam scan parameters\n"
+	"Use standard scan params syntax below,"
+	"but only active/passive/home times, nprobes, type,"
+	"and channels are used.\n"
+	"All other values are silently discarded.\n"
+	SCAN_USAGE
+	},
+#ifdef WLRCC
+	{ "roamscan_channels", wl_roamchannels, WLC_GET_VAR, -1,
+	"get roam channels\n"
+	},
+#endif /* WLRCC */
+	{ "roam_prof", wl_roam_prof, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set roaming profiles (need to specify band)\n"
+	"\tUsage: wl roam_prof_2g a|b|2g|5g flags rssi_upper rssi_lower delta, boost_thresh "
+	"boot_delta nfscan fullperiod initperiod backoff maxperiod\n"
+	},
+	{ "iscan_s", wl_iscan, -1, WLC_SET_VAR,
+	"Initiate an incremental scan.\n" SCAN_USAGE
+	},
+	{ "iscan_c", wl_iscan, -1, WLC_SET_VAR,
+	"Continue an incremental scan.\n" SCAN_USAGE
+	},
+	{ "escan", wl_escan, -1, WLC_SET_VAR,
+	"Start an escan.\n" SCAN_USAGE
+	},
+	{ "escanabort", wl_escan, -1, WLC_SET_VAR,
+	"Abort an escan.\n" SCAN_USAGE
+	},
+	{ "regulatory", wl_int, WLC_GET_REGULATORY, WLC_SET_REGULATORY,
+	"Get/Set regulatory domain mode (802.11d). Driver must be down." },
+	{ "spect", wl_spect, WLC_GET_SPECT_MANAGMENT, WLC_SET_SPECT_MANAGMENT,
+	"Get/Set 802.11h Spectrum Management mode.\n"
+	"\t0 - Off\n"
+	"\t1 - Loose interpretation of 11h spec - may join non-11h APs\n"
+	"\t2 - Strict interpretation of 11h spec - may not join non-11h APs\n"
+	"\t3 - Disable 11h and enable 11d\n"
+	"\t4 - Loose interpretation of 11h+d spec - may join non-11h APs"
+	},
+	{ "scanabort", wl_var_void, -1, WLC_SET_VAR,
+	"Abort a scan." },
+	{ "scanresults", wl_dump_networks, WLC_SCAN_RESULTS, -1,
+	"Return results from last scan." },
+	{ "iscanresults", wl_dump_networks, WLC_GET_VAR, -1,
+	"Return results from last iscan. Specify a buflen (max 8188)\n"
+	"\tto artificially limit the size of the results buffer.\n"
+	"\tiscanresults [buflen]"},
+	{ "assoc",  wl_status, -1, -1,
+	"Print information about current network association.\n"
+	"\t(also known as \"status\")" },
+	{ "status", wl_status, -1, -1,
+	"Print information about current network association.\n"
+	"\t(also known as \"assoc\")" },
+	{ "disassoc", wl_void, -1, WLC_DISASSOC,
+	"Disassociate from the current BSS/IBSS." },
+	{ "chanlist", wl_print_deprecate, WLC_GET_VALID_CHANNELS, -1,
+	"Deprecated. Use channels." },
+	{ "channels", wl_dump_chanlist, WLC_GET_VALID_CHANNELS, -1,
+	"Return valid channels for the current settings." },
+	{ "channels_in_country", wl_channels_in_country, WLC_GET_CHANNELS_IN_COUNTRY, -1,
+	"Return valid channels for the country specified.\n"
+	"\tArg 1 is the country abbreviation\n"
+	"\tArg 2 is the band(a or b)"},
+	{ "curpower", wl_get_current_power, WLC_CURRENT_PWR, -1,
+	"Return current tx power settings.\n"
+	"\t-v, --verbose: display the power settings for every "
+	"rate even when every rate in a rate group has the same power." },
+	{ "txpwr_target_max", wl_get_txpwr_target_max, WLC_GET_VAR, -1,
+	"Return current max tx target power settings.\n" },
+	{ "chanspec_txpwr_max", wl_get_chanspec_txpwr_max, WLC_GET_VAR, -1,
+	"Return valid chanspecs with max tx power settings.\n"
+	"\t-b band (5(a) or 2(b/g))\n"
+	"\t-w bandwidth, 20, 40, 80, 160 or 8080\n"
+	},
+	{ "rateset", wl_rateset, WLC_GET_RATESET, WLC_SET_RATESET,
+	"Returns or sets the supported and basic rateset, (b) indicates basic\n"
+	"\tWith no args, returns the rateset. Args are\n"
+	"\trateset \"default\" | \"all\" | <arbitrary rateset> [-m|-v <list of mcs masks>]\n"
+	"\t\tdefault - driver defaults\n"
+	"\t\tall - all rates are basic rates\n"
+	"\t\tarbitrary rateset - list of rates\n"
+	"\tList of rates are in Mbps and each rate is optionally followed\n"
+	"\tby \"(b)\" or \"b\" for a Basic rate. Example: 1(b) 2b 5.5 11\n"
+	"\tAt least one rate must be Basic for a legal rateset.\n\n"
+	"\t-m  sets HT rates (bitmasks, 00-ff). Least significant bit is MCS0.\n"
+	"\t    example: 'rateset -m 0x3f 0x01' limits rates to MCS0-MCS5 and MCS8\n\n"
+	"\t-v  sets VHT MCS values for each supported count of spatial streams.\n"
+	"\t    example: 'rateset -v 3ff 1ff ff' limits vht rates to MCS 0-9 for 1 stream,\n"
+	"\t                             MCS 0-8 for 2 streams, and MCS 0-7 for 3 streams."
+	},
+	{"txbf_rateset", wl_txbf_rateset, WLC_GET_TXBF_RATESET, WLC_SET_TXBF_RATESET,
+	TXBF_RATESET_USAGE
+	},
+	{ "default_rateset", wl_default_rateset, WLC_GET_VAR, -1,
+	"Returns supported rateset of given phy.\n"
+	"\tYou have to insert following Args\n"
+	"\t\tArg 1. Phy Type: have to be one of the following: "
+	"[a, b, g, n, lp, ssn, ht, lcn, lcn40, ac]\n"
+	"\t\tArg 2. Band Type: 2 for 2.4G or 5 for 5G\n"
+	"\t\tArg 3. CCK Only: 1 for CCK Only or 0 for CCK and OFDM rates\n"
+	"\t\tArg 4. Basic Rates: 1 for all rates WITH basic rates or "
+	"0 for all rates WITHOUT basic rates\n"
+	"\t\tArg 5. MCS Rates: 1 for all rates WITH MCS rates or "
+	"0 for all rates WITHOUT MCS rates\n"
+	"\t\tArg 6. Bandwidth: have to be one of the following: [10, 20, 40, 80, 160]\n"
+	"\t\tArg 7. TX/RX Stream: \"tx\" for TX streams or \"rx\" for RX streams\n"
+	"\t\tExample: PHY: AC, Band 2.4G, CCK rates only, With Basec rates, "
+	"WithOut MCS rates, BW: 40 and TX streams\n"
+	"\t\tInput: default_rateset ac 2 0 1 0 40 tx\n"
+	},
+	{ "roam_trigger", wl_band_elm, WLC_GET_ROAM_TRIGGER, WLC_SET_ROAM_TRIGGER,
+	"Get or Set the roam trigger RSSI threshold:\n"
+	"\tGet: roam_trigger [a|b]\n"
+	"\tSet: roam_trigger <integer> [a|b|all]\n"
+	"\tinteger -   0: default\n"
+	"\t            1: optimize bandwidth\n"
+	"\t            2: optimize distance\n"
+	"\t    [-1, -99]: dBm trigger value"},
+	{ "roam_delta",	wl_band_elm, WLC_GET_ROAM_DELTA, WLC_SET_ROAM_DELTA,
+	"Set the roam candidate qualification delta. roam_delta [integer [, a/b]]" },
+	{ "roam_scan_period", wl_int, WLC_GET_ROAM_SCAN_PERIOD, WLC_SET_ROAM_SCAN_PERIOD,
+	"Set the roam candidate qualification delta.  (integer)" },
+	{ "suprates", wl_sup_rateset, WLC_GET_SUP_RATESET_OVERRIDE, WLC_SET_SUP_RATESET_OVERRIDE,
+	"Returns or sets the 11g override for the supported rateset\n"
+	"\tWith no args, returns the rateset. Args are a list of rates,\n"
+	"\tor 0 or -1 to specify an empty rateset to clear the override.\n"
+	"\tList of rates are in Mbps, example: 1 2 5.5 11"},
+	{ "prb_resp_timeout", wl_int, WLC_GET_PRB_RESP_TIMEOUT, WLC_SET_PRB_RESP_TIMEOUT,
+	"Get/Set probe response timeout"},
+	{ "channel_qa", wl_int, WLC_GET_CHANNEL_QA, -1,
+	"Get last channel quality measurment"},
+	{ "channel_qa_start", wl_void, -1, WLC_START_CHANNEL_QA,
+	"Start a channel quality measurment"},
+	{ "ccode_info", wl_ccode_info, WLC_GET_VAR, -1,
+	"Get Country Code Info"},
+	{ "country", wl_country, WLC_GET_COUNTRY, WLC_SET_COUNTRY,
+	"Select Country Code for driver operational region\n"
+	"\tFor simple country setting: wl country <country>\n"
+	"\tWhere <country> is either a long name or country code from ISO 3166; "
+	"for example \"Germany\" or \"DE\"\n"
+	"\n\tFor a specific built-in country definition: "
+	"wl country <built-in> [<advertised-country>]\n"
+	"\tWhere <built-in> is a country country code followed by '/' and "
+	"regulatory revision number.\n"
+	"\tFor example, \"US/3\".\n"
+	"\tAnd where <advertised-country> is either a long name or country code from ISO 3166.\n"
+	"\tIf <advertised-country> is omitted, it will be the same as the built-in country code.\n"
+	"\n\tUse 'wl country list [band(a or b)]' for the list of supported countries"},
+	{ "country_ie_override", wl_country_ie_override, WLC_GET_VAR, WLC_SET_VAR,
+	"To set/get country ie"},
+	{ "autocountry_default", wl_varstr, WLC_GET_VAR, WLC_SET_VAR,
+	"Select Country Code for use with Auto Contry Discovery"},
+	{ "join", wl_join, -1, -1,
+	"Join a specified network SSID.\n"
+	"\tUsage: join <ssid> [key <0-3>:xxxxx] [imode bss|ibss] "
+	"[amode open|shared|openshared|wpa|wpapsk|wpa2|wpa2psk|wpanone|ftpsk] [options]\n"
+	"\tOptions:\n"
+	"\t-b MAC, --bssid=MAC \tBSSID (xx:xx:xx:xx:xx:xx) to scan and join\n"
+	"\t-c CL, --chanspecs=CL \tchanspecs (comma or space separated list)\n"
+	"\tprescanned \tuses channel and bssid list from scanresults\n"
+	"\t-p, -passive: force passive assoc scan (useful for P2P)"},
+	{ "ssid", wl_ssid, WLC_GET_SSID, WLC_SET_SSID,
+	"Set or get a configuration's SSID.\n"
+	"\twl ssid [-C num]|[--cfg=num] [<ssid>]\n"
+	"\tIf the configuration index 'num' is not given, configuraion #0 is assumed and\n"
+	"\tsetting will initiate an assoication attempt if in infrastructure mode,\n"
+	"\tor join/creation of an IBSS if in IBSS mode,\n"
+	"\tor creation of a BSS if in AP mode."},
+	{ "mac", wl_maclist, WLC_GET_MACLIST, WLC_SET_MACLIST,
+	"Set or get the list of source MAC address matches.\n"
+	"\twl mac xx:xx:xx:xx:xx:xx [xx:xx:xx:xx:xx:xx ...]\n"
+	"\tTo Clear the list: wl mac none" },
+	{ "macmode", wl_int, WLC_GET_MACMODE, WLC_SET_MACMODE,
+	"Set the mode of the MAC list.\n"
+	"\t0 - Disable MAC address matching.\n"
+	"\t1 - Deny association to stations on the MAC list.\n"
+	"\t2 - Allow association to stations on the MAC list."},
+	{ "band", wl_band, WLC_GET_BAND, WLC_SET_BAND,
+	"Returns or sets the current band\n"
+	"\tauto - auto switch between available bands (default)\n"
+	"\ta - force use of 802.11a band\n"
+	"\tb - force use of 802.11b band" },
+	{ "bands", wl_bandlist, WLC_GET_BANDLIST, -1,
+	"Return the list of available 802.11 bands" },
+	{ "phylist", wl_phylist, WLC_GET_PHYLIST, -1,
+	"Return the list of available phytypes" },
+	{ "shortslot", wl_int, WLC_GET_SHORTSLOT, -1,
+	"Get current 11g Short Slot Timing mode. (0=long, 1=short)" },
+	{ "shortslot_override", wl_int, WLC_GET_SHORTSLOT_OVERRIDE, WLC_SET_SHORTSLOT_OVERRIDE,
+	"Get/Set 11g Short Slot Timing mode override. (-1=auto, 0=long, 1=short)" },
+	{ "pktcnt", wl_get_pktcnt, WLC_GET_PKTCNTS, -1,
+	"Get the summary of good and bad packets." },
+	{ "upgrade", wl_upgrade, -1, WLC_UPGRADE,
+	"Upgrade the firmware on an embedded device" },
+	{ "gmode", wl_gmode, WLC_GET_GMODE, WLC_SET_GMODE,
+	"Set the 54g Mode (LegacyB|Auto||GOnly|BDeferred|Performance|LRS)" },
+	{ "gmode_protection", wl_int, WLC_GET_GMODE_PROTECTION, -1,
+	"Get G protection mode. (0=disabled, 1=enabled)" },
+	{ "gmode_protection_control", wl_int, WLC_GET_PROTECTION_CONTROL,
+	WLC_SET_PROTECTION_CONTROL,
+	"Get/Set 11g protection mode control alg."
+	"(0=always off, 1=monitor local association, 2=monitor overlapping BSS)" },
+	{ "gmode_protection_override", wl_int, WLC_GET_GMODE_PROTECTION_OVERRIDE,
+	WLC_SET_GMODE_PROTECTION_OVERRIDE,
+	"Get/Set 11g protection mode override. (-1=auto, 0=disable, 1=enable)" },
+	{ "protection_control", wl_int, WLC_GET_PROTECTION_CONTROL,
+	WLC_SET_PROTECTION_CONTROL,
+	"Get/Set protection mode control alg."
+	"(0=always off, 1=monitor local association, 2=monitor overlapping BSS)" },
+	{ "legacy_erp", wl_int, WLC_GET_LEGACY_ERP, WLC_SET_LEGACY_ERP,
+	"Get/Set 11g legacy ERP inclusion (0=disable, 1=enable)" },
+	{ "isup", wl_int, WLC_GET_UP, -1,
+	"Get driver operational state (0=down, 1=up)"},
+	{ "rssi", wl_rssi, WLC_GET_RSSI, -1,
+	"Get the current RSSI val, for an AP you must specify the mac addr of the STA" },
+	{ "fasttimer", wl_print_deprecate, -1, -1,
+	"Deprecated. Use fast_timer."},
+	{ "slowtimer", wl_print_deprecate, -1, -1,
+	"Deprecated. Use slow_timer."},
+	{ "glacialtimer", wl_print_deprecate, -1, -1,
+	"Deprecated. Use glacial_timer."},
+	{ "dfs_status", wl_dfs_status, WLC_GET_VAR, -1,
+	"Get dfs status"},
+	{ "dfs_status_all", wl_dfs_status_all, WLC_GET_VAR, -1,
+	"Get dfs status of multiple cores or parallel radar scans"},
+	{ "radar_status", wl_radar_status, WLC_GET_VAR, -1,
+	"Get radar detection status"},
+	{ "clear_radar_status", wl_clear_radar_status, -1, WLC_SET_VAR,
+	"Clear radar detection status"},
+	{ "radar_sc_status", wl_radar_sc_status, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/clear sc radar detection status"},
+	{ "pwr_percent", wl_int, WLC_GET_PWROUT_PERCENTAGE, WLC_SET_PWROUT_PERCENTAGE,
+	"Get/Set power output percentage"},
+	{ "toe", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/Disable tcpip offload feature"},
+	{ "arpoe", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/Disable arp agent offload feature"},
+	{ "wet", wl_int, WLC_GET_WET, WLC_SET_WET,
+	"Get/Set wireless ethernet bridging mode"},
+	{ "bi", wl_int, WLC_GET_BCNPRD, WLC_SET_BCNPRD,
+	"Get/Set the beacon period (bi=beacon interval)"},
+	{ "dtim", wl_int, WLC_GET_DTIMPRD, WLC_SET_DTIMPRD,
+	"Get/Set DTIM"},
+	{ "measure_req", wl_measure_req, -1, WLC_MEASURE_REQUEST,
+	"Send an 802.11h measurement request.\n"
+	"\tUsage: wl measure_req <type> <target MAC addr>\n"
+	"\tMeasurement types are: TPC, Basic, CCA, RPI\n"
+	"\tTarget MAC addr format is xx:xx:xx:xx:xx:xx"},
+	{ "quiet", wl_send_quiet, -1, WLC_SEND_QUIET,
+	"Send an 802.11h quiet command.\n"
+	"\tUsage: wl quiet <TBTTs until start>, <duration (in TUs)>, <offset (in TUs)>"},
+	{ "pm_mute_tx", wl_pm_mute_tx, -1, WLC_SET_VAR,
+	"Sets parameters for power save mode with muted transmission path. Usage:\n"
+	"\twl pm_mute_tx 1 <deadline>\t: attempts to enable mode as soon as\n"
+	"\t\t\t  timer of <deadline> (milliseconds) expires.\n"
+	"\twl pm_mute_tx 0\t: disables mode\n" },
+	{ "csa", wl_send_csa, -1, WLC_SET_VAR,
+	"Send an 802.11h channel switch anouncement with chanspec:\n"
+	"\t<mode> <count> <channel>[a,b][n][u,l][frame type]\n"
+	"\tmode (0 or 1)\n"
+	"\tcount (0-254)\n"
+	"\tchannel format:\n"
+	"\t20MHz : [2g|5g]<channel>[/20]\n"
+	"\t40MHz : [2g|5g]<channel>/40[u,l]\n"
+	"\t80MHz :    [5g]<channel>/80\n"
+	"\toptional band 2g or 5g, default to 2g if channel <= 14\n"
+	"\tchannel number (0-200)\n"
+	"\tbandwidth, 20, 40, or 80, default 20\n"
+	"\tprimary sideband for 40MHz on 2g, l=lower, u=upper\n"
+	"\tcsa frame type(optional), default is broadcast if not specified, u=unicast"},
+	{ "constraint", wl_int, -1, WLC_SEND_PWR_CONSTRAINT,
+	"Send an 802.11h Power Constraint IE\n"
+	"\tUsage: wl constraint 1-255 db"},
+	{ "rm_req", wl_rm_request, -1, WLC_SET_VAR,
+	"Request a radio measurement of type basic, cca, or rpi\n"
+	"\tspecify a series of measurement types each followed by options.\n"
+	"\texample: wl rm_req cca -c 1 -d 50 cca -c 6 cca -c 11\n"
+	"\tOptions:\n"
+	"\t-t n  numeric token id for measurement set or measurement\n"
+	"\t-c n  channel\n"
+	"\t-d n  duration in TUs (1024 us)\n"
+	"\t-p    parallel flag, measurement starts at the same time as previous\n"
+	"\n"
+	"\tEach measurement specified uses the same channel and duration as the\n"
+	"\tprevious unless a new channel or duration is specified."},
+	{ "rm_rep", wl_rm_report, WLC_GET_VAR, -1,
+	"Get current radio measurement report"},
+	{ "join_pref", wl_join_pref, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get join target preferences."},
+	{ "assoc_pref", wl_assoc_pref, WLC_GET_ASSOC_PREFER, WLC_SET_ASSOC_PREFER,
+	"Set/Get association preference.\n"
+	"Usage: wl assoc_pref [auto|a|b|g]"},
+	{ "wme", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set WME (Wireless Multimedia Extensions) mode (0=off, 1=on, -1=auto)"},
+	{ "wme_ac", wl_wme_ac_req, WLC_GET_VAR, WLC_SET_VAR,
+	"wl wme_ac ap|sta [be|bk|vi|vo [ecwmax|ecwmin|txop|aifsn|acm <value>] ...]"},
+	{ "wme_apsd", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set APSD (Automatic Power Save Delivery) mode on AP (0=off, 1=on)" },
+	{ "wme_apsd_sta", wl_wme_apsd_sta, WLC_GET_VAR, WLC_SET_VAR,
+	"Set APSD parameters on STA. Driver must be down.\n"
+	"Usage: wl wme_apsd_sta <max_sp_len> <be> <bk> <vi> <vo>\n"
+	"   <max_sp_len>: number of frames per USP: 0 (all), 2, 4, or 6\n"
+	"   <xx>: value 0 to disable, 1 to enable U-APSD per AC" },
+	{ "wme_dp", wl_wme_dp, WLC_GET_VAR, WLC_SET_VAR,
+	"Set AC queue discard policy.\n"
+	"Usage: wl wme_dp <be> <bk> <vi> <vo>\n"
+	"   <xx>: value 0 for newest-first, 1 for oldest-first" },
+	{ "wme_counters", wl_wme_counters, WLC_GET_VAR, -1,
+	"print WMM stats" },
+	{ "wme_clear_counters", wl_var_void, -1, WLC_SET_VAR,
+	"clear WMM counters"},
+	{ "wme_tx_params", wme_tx_params, -1, -1,
+	"wl wme_tx_params [be|bk|vi|vo [short|sfb|long|lfb|max_rate <value>] ...]"},
+	{ "wme_maxbw_params", wme_maxbw_params, WLC_GET_VAR, WLC_SET_VAR,
+	"wl wme_maxbw_params [be|bk|vi|vo <value> ....]"},
+	{ "lifetime", wl_lifetime, WLC_GET_VAR, WLC_SET_VAR,
+	"Set Lifetime parameter (milliseconds) for each ac.\n"
+	"wl lifetime be|bk|vi|vo [<value>]"},
+	{ "reinit", wl_void, -1, WLC_INIT,
+	"Reinitialize device"},
+	{ "sta_info", wl_sta_info, WLC_GET_VAR, -1,
+	"wl sta_info <xx:xx:xx:xx:xx:xx>"},
+	{ "staprio", wl_staprio, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get sta priority \n"
+	"Usage: wl staprio <xx:xx:xx:xx:xx:xx> <prio> \n"
+	"<prio>: 0~3"},
+	{ "pktq_stats", wl_iov_pktqlog_params, WLC_GET_VAR, -1,
+	"Dumps packet queue log info for [C] common, [A] AMPDU, [N] NAR or [P] power save queues\n"
+	"A:, N: or P: are used to prefix a MAC address (a colon : separator is necessary),\n"
+	"or else C: is used alone. The '+' option after the colon gives more details.\n"
+	"Up to 4 parameters may be given, the common queue is default when no parameters\n"
+	"are supplied\n"
+	"Use '/<PREC>' as suffix to restrict to certain prec indices; multiple /<PREC>/<PREC>/..."
+	"can be used\n"
+	"Also, '//' as a suffix to the MAC address or 'C://' will enable automatic logging of\n"
+	"all prec as they are seen.\n"
+	"Full automatic operation is also possible with the shorthand\n"
+	"'A:' (or 'A://'), 'P:' (or 'P://') etc which scans through all known addresses for\n"
+	"those parameters that take a MAC address.\n"
+	"wl pktq_stats [C:[+]]|[A:[+]|P:[+]|N:[+]<xx:xx:xx:xx:xx:xx>][/<PREC>[/<PREC>]][//]..." },
+	{ "bs_data", wl_scb_bs_data, WLC_GET_VAR, -1, "Display per station band steering data\n"
+	"usage: bs_data [options]\n"
+	"  options are:\n"
+	"    -comma    Use commas to separate values rather than blanks.\n"
+	"    -tab      Use <TAB> to separate values rather than blanks.\n"
+	"    -raw      Display raw values as received from driver.\n"
+	"    -noidle   Do not display idle stations\n"
+	"    -noreset  Do not reset counters after reading" },
+	{ "cap", wl_var_getandprintstr, WLC_GET_VAR, -1, "driver capabilities"},
+	{ "malloc_dump", wl_print_deprecate, -1, -1, "Deprecated. Folded under 'wl dump malloc"},
+	{ "chan_info", wl_chan_info, WLC_GET_VAR, -1, "channel info"},
+	{ "add_ie", wl_add_ie, -1, WLC_SET_VAR,
+	"Add a vendor proprietary IE to 802.11 management packets\n"
+	"Usage: wl add_ie <pktflag> length OUI hexdata\n"
+	"<pktflag>: Bit 0 - Beacons\n"
+	"           Bit 1 - Probe Rsp\n"
+	"           Bit 2 - Assoc/Reassoc Rsp\n"
+	"           Bit 3 - Auth Rsp\n"
+	"           Bit 4 - Probe Req\n"
+	"           Bit 5 - Assoc/Reassoc Req\n"
+	"           Bit 7 - Auth Req\n"
+	"Example: wl add_ie 3 10 00:90:4C 0101050c121a03\n"
+	"         to add this IE to beacons and probe responses" },
+	{ "del_ie", wl_del_ie, -1, WLC_SET_VAR,
+	"Delete a vendor proprietary IE from 802.11 management packets\n"
+	"Usage: wl del_ie <pktflag> length OUI hexdata\n"
+	"<pktflag>: Bit 0 - Beacons\n"
+	"           Bit 1 - Probe Rsp\n"
+	"           Bit 2 - Assoc/Reassoc Rsp\n"
+	"           Bit 3 - Auth Rsp\n"
+	"           Bit 4 - Probe Req\n"
+	"           Bit 5 - Assoc/Reassoc Req\n"
+	"           Bit 7 - Auth Req\n"
+	"Example: wl del_ie 3 10 00:90:4C 0101050c121a03" },
+	{ "list_ie", _wl_list_ie, WLC_GET_VAR, -1,
+	"Dump the list of vendor proprietary IEs" },
+	{ "rand", wl_rand, WLC_GET_VAR, -1,
+	"Get a 2-byte Random Number from the MAC's PRNG\n"
+	"Usage: wl rand"},
+	{ "bcmerrorstr", wl_var_getandprintstr, WLC_GET_VAR, -1, "errorstring"},
+	{ "freqtrack", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set Frequency Tracking Mode (0=Auto, 1=On, 2=OFF)"},
+	{ "eventing", wl_eventbitvec, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get hex filter bitmask for MAC event reporting up to application layer"},
+	{ "event_msgs_ext", wl_bitvecext, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get bit arbitrary size hex filter bitmask for MAC"	},
+	{ "event_msgs", wl_eventbitvec, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get hex filter bitmask for MAC event reporting via packet indications"},
+	{ "counters", wl_counters, WLC_GET_VAR, -1,
+	"Return driver counter values. \n"
+	"\t wl counters [options]. Options:\n"
+	"\t --nz      : only non zero counters\n"
+	"\t --err     : only error/warning related counters\n"
+	"\t --rx      : only rx specific counters\n"
+	"\t --tx\n"
+	"\t --ctrl    : only ctrl/mgmt related counters\n"
+	"\t --ucode   : only ucode generated counters\n"
+	"\t --ucast\n"
+	"\t --mcast   : only mcast+bcast related counters\n"
+	"\t --sec     : security: only tkip/aes/ related counters\n"
+	"\t --ampdu --rx     : combine options to narrow down selection\n"
+	"\t --ampdu --invert : use --invert to invert the selection"},
+	{ "subcounters", wl_subcounters, WLC_GET_VAR, WLC_SET_VAR,
+	"Return driver counter values of requested counters. \n"
+	"\t wl subcounters <version> <counters list> - To list requested counters\n"
+	"\t wl subcounters - To get the counters version FW is using\n"
+	"\t wl subcounters <version> - List supported counters in given version"},
+	{ "if_counters", wl_if_counters, WLC_GET_VAR, -1,
+	"Return driver counter values for current interface." },
+	{ "reset_cnts", wl_clear_counters, WLC_GET_VAR, -1,
+	"Clear driver counter values" },
+	{ "wlc_ver", wl_wlc_ver, WLC_GET_VAR, -1,
+	"returns wlc interface version" },
+	{ "delta_stats_interval", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the delta statistics interval in seconds (0 to disable)"},
+	{ "delta_stats", wl_delta_stats, WLC_GET_VAR, -1,
+	"get the delta statistics for the last interval" },
+	{ "swdiv_stats", wl_swdiv_stats, WLC_GET_VAR, -1,
+	"Returns swdiv stats"},
+	{ "rxfifo_counters", wl_rxfifo_counters, WLC_GET_VAR, -1,
+	"Returns rxfifo counters"},
+	{ "assoc_info", wl_assoc_info, WLC_GET_VAR, -1,
+	"Returns the assoc req and resp information [STA only]" },
+	{ "autochannel", wl_auto_channel_sel, WLC_GET_CHANNEL_SEL, WLC_START_CHANNEL_SEL,
+	"auto channel selection: \n"
+	"\t1 to issue a channel scanning;\n"
+	"\t2 to set chanspec based on the channel scan result;\n"
+	"\twithout argument to only show the chanspec selected; \n"
+	"\tssid must set to null before this process, RF must be up"},
+	{ "csscantimer", wl_int, WLC_GET_CS_SCAN_TIMER, WLC_SET_CS_SCAN_TIMER,
+	"auto channel scan timer in minutes (0 to disable)" },
+	{ "closed", wl_int, WLC_GET_CLOSED, WLC_SET_CLOSED,
+	"hides the network from active scans, 0 or 1.\n"
+	"\t0 is open, 1 is hide" },
+	{ "pmkid_info", wl_pmkid_info, WLC_GET_VAR, WLC_SET_VAR,
+	"Returns the pmkid table" },
+	{ "probresp_mac_filter", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get MAC filter based Probe response mode. \n"
+	"\t0 - Disable MAC filter based Probe response mode.\n"
+	"\t1 - Enable MAC filter based Probe response mode.\n"
+	"\tNo parameter - Returns the current setting."},
+	{ "eap_restrict", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get EAP restriction"},
+	{ "reset_d11cnts", wl_var_void, -1, WLC_SET_VAR,
+	"reset 802.11 MIB counters"},
+	{ "staname", wl_varstr, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set station name: \n"
+	"\tMaximum name length is 15 bytes"},
+	{ "apname", wl_varstr, WLC_GET_VAR, -1,
+	"get AP name"},
+	{ "overlay", wl_overlay, WLC_GET_VAR, WLC_SET_VAR,
+	"overlay virt_addr phy_addr size"},
+	{ "antgain", wl_antgain, WLC_GET_VAR, WLC_SET_VAR,
+	"Set temp ag0/1 value\n"
+	"usage: wl antgain ag0=0x1 ag1=0x2"
+	},
+	{ "phy_antsel", wl_antsel, WLC_GET_VAR, -1,
+	"get/set antenna configuration \n"
+	"\tset: -1(AUTO), 0xAB(fixed antenna selection)\n"
+	"\t\twhere A and B is the antenna numbers used for RF chain 1 and 0 respectively\n"
+	"\tquery: <utx>[AUTO] <urx>[AUTO] <dtx>[AUTO] <drx>[AUTO]\n"
+	"\t\twhere utx = TX unicast antenna configuration\n"
+	"\t\t\turx = RX unicast antenna configuration\n"
+	"\t\t\tdtx = TX default (non-unicast) antenna configuration\n"
+	"\t\t\tdrx = RX default (non-unicast) antenna configuration"
+	},
+	{ "txfifo_sz", wl_txfifo_sz, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the txfifo size; usage: wl txfifo_sz <fifonum> <size_in_bytes>" },
+#if defined(linux)
+	{ "escan_event_check", wl_escan_event_check, -1, -1,
+	"Listen and prints the escan events from the dongle\n"
+	"\tescan_event_check syntax is: escan_event_check ifname flag\n"
+	"\tflag 1 = sync_id info, 2 = bss info, 4 = state + bss info [default], "
+	"8 = TLV check for IEs"},
+	{ "escanresults", wl_escanresults, -1, WLC_SET_VAR,
+	"Start escan and display results.\n" SCAN_USAGE
+	},
+	{ "wl_event_check", wl_event_check, -1, -1,
+	"listen and display brcm events\n"
+	"\tusage:wl -i <ifname> wl_event_check"},
+#endif   /* linux */
+
+	{ "hs20_ie", wl_hs20_ie, -1, WLC_SET_VAR,
+	"set hotspot 2.0 indication IE\n"
+	"\tusage: wl hs20_ie <length> <hexdata>\n"
+	},
+	{"rate_histo", wl_rate_histo, -1, WLC_GET_VAR,
+	"Get rate hostrogram"
+	},
+	{ "wme_apsd_trigger", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set Periodic APSD Trigger Frame Timer timeout in ms (0=off)"},
+	{ "wme_autotrigger", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/Disable sending of APSD Trigger frame when all ac are delivery enabled"},
+	{ "reassoc", wl_reassoc, -1, WLC_REASSOC,
+	"Initiate a (re)association request.\n"
+	"\tUsage: wl reassoc <bssid> [options]\n"
+	"\tOptions:\n"
+	"\t-c CL, --chanspecs=CL \tchanspecs (comma or space separated list)"},
+	{ "send_nulldata", wl_iov_mac, -1, -1,
+	"Sed a null frame to the specified hw address" },
+	{ "srchmem", wl_srchmem, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set ucode srch engine memory"},
+	{"ptk_start", wl_ptk_start, -1, WLC_SET_VAR,
+	"Send specified \"wl_ptk_start \" params .\n"
+	"\tUsage: wl ptk_start <sec type> <awdl peer_addr> <pmk> <role>\n"},
+#ifdef CLMDOWNLOAD
+	{ "clmload", wl_clmload, -1, WLC_SET_VAR,
+	"Download CLM data into a driver.  Driver must be down.\n"
+	"\tUsage: wl clmload <clm blob file name>\n"
+	"\t  Note obsolete syntax 'wl clmload 0/1 <clm blob file name>' is still accepted\n"
+	"\t  but the download type 0/1 is no longer applicable and is ignored.  Incremental\n"
+	"\t  CLM download is no longer supported.  Also reverting to the original built-in\n"
+	"\t  CLM is no longer supported.  (This syntax was 'wl clmload 0/1')"},
+	{ "txcapload", wl_txcapload, -1, WLC_SET_VAR,
+	"Download txcap data into a driver.  Driver must be down.\n"
+	"\tUsage: wl txcapload <txcap file name>\n"},
+	{ "txcapver", wl_var_getandprintstr, WLC_GET_VAR, -1,
+	"List curent txcap downloaded information"},
+	{ "txcapconfig", wl_txcapctl, WLC_GET_VAR, WLC_SET_VAR,
+	"Set or get the txcap config setting for the low/high cap selection for each subband"},
+	{ "txcapstate", wl_txcapctl, WLC_GET_VAR, WLC_SET_VAR,
+	"Set or get the txcap state setting for the low/high cap selection for each subband"},
+	{ "txcapdump", wl_txcapdump, WLC_GET_VAR, -1,
+	"Get txcap dump information.  Intended for design verification/debugging as opposed to\n"
+	"\tproduction usage and as such may change with little (or no) notice."},
+#endif /* CLMDOWNLOAD */
+	{ "calload", wl_calload, -1, WLC_SET_VAR,
+	"Download CAL data into a driver.  Driver must be down.\n"
+	"\tUsage: wl calload <cal file name> to download existing calibration data file\n"},
+	{ "caldump", wl_caldump, WLC_GET_VAR, -1,
+	"Dump calibration data and save it with calibration storage format.\n"
+	"\tUsage: wl caldump <cal file name> to dump current calibration info to file\n"},
+	{ "calload_chkver", wl_buf, -1, WLC_SET_VAR,
+	"Confirm TxCal load with provided version string"},
+	{ "bmac_reboot", wl_var_void, -1, WLC_SET_VAR,
+	"Reboot BMAC"},
+#ifdef RWL_WIFI
+	{ "findserver", wl_wifiserver, -1, -1,
+	"Used to find the remote server with proper mac address given by the user,this "
+	"cmd is specific to wifi protocol."},
+#endif
+	{ "assertlog", wl_assertlog, WLC_GET_VAR, -1,
+	"get external assert logs\n"
+	"\tUsage: wl assertlog"},
+	{ "assert_type", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the asset_bypass flag; usage: wl assert_type <1/0> (On/Off)"
+	},
+#ifdef BCMWAPI_WAI
+	{ "wai_restrict", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get WAI restriction"},
+	{ "wai_rekey", wl_iov_mac, -1, -1,
+	"set rekey event"},
+#endif /* BCMWAPI_WAI */
+	{"cca_get_stats", wl_cca_get_stats, WLC_GET_VAR, -1,
+	"Usage: wl cca_stats [-c channel] [-s num seconds][-n]\n"
+	"\t -c channel: Optional. specify channel. 0 = All channels. Default = current channel \n"
+	"\t -n: no analysis of results\n"
+	"\t -s num_seconds: Optional. Default = 10, Max = 60\n"
+	"\t -i: list individual measurements in addition to the averages\n"
+	"\t -curband: Only recommend channels on current band"
+	},
+	{ "smfstats", wl_smfstats, WLC_GET_VAR, WLC_SET_VAR,
+	"get/clear selected management frame (smf) stats"
+	"\twl smfstats [-C num]|[--cfg=num] [auth]|[assoc]|[reassoc]|[clear]\n"
+	"\tclear - to clear the stats" },
+#ifdef RWL_DONGLE
+	{ "dongleset", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable uart driver"
+	},
+#endif
+	{ "manfinfo", wl_var_getandprintstr, WLC_GET_VAR, -1,
+	"show chip package info in OTP"},
+	{ "pm_dur", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Retrieve accumulated PM duration information (GET only)\n"
+	},
+	{ "mpc_dur", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Retrieve accumulated MPC duration information in ms (GET) or clear accumulator (SET)\n"
+	"\tUsage: wl mpc_dur <any-number-to-clear>"},
+	{"txdelay_params", wl_txdelay_params, WLC_GET_VAR, -1,
+	"get chanim stats \n"
+	"\t Usage: wl txdelay_params ratio cnt period tune"
+	},
+	{"dlystats", wl_dlystats, WLC_GET_VAR, -1,
+	"dump delay statistics\n"
+	"\tUsage: wl dlystats [xx:xx:xx:xx:xx:xx] (optional mac address)\n"
+	"\tIf mac_addr is not specified, dump all of scbs"
+	},
+	{"dlystats_clear", wl_dlystats_clear, -1, WLC_SET_VAR,
+	"clear delay stats \n"
+	"\t Usage: wl dlystats_clear"
+	},
+	{"intfer_params", wl_intfer_params, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get intfer params \n"
+	"\tUsage: wl intfer_params period (in sec) cnt(0~4) txfail_thresh tcptxfail_thresh\n"
+	"\tperiod=0: disable Driver monitor txfail"
+	},
+	{ "dngl_wd", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"enable or disable dongle keep alive watchdog timer\n"
+	"\tUsage: wl dngl_wd 0\\1 (to turn off\\on)"},
+	{ "tsf", wl_tsf, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get tsf register\n"
+	"\tUsage: wl tsf [<high> <low>]"},
+	{ "mac_rate_histo", wl_mac_rate_histo, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: wl mac_rate_histo <mac address> <access category> <num_pkts>\n"
+	"\t(MAC address e.g. 00:11:20:11:33:33)\n"
+	"\t(Access Category(AC) - 0x10:for entire MAC or 0x4:for video AC for this MAC)\n"
+	"\t(num_pkts (optional) - Number of packets to average - max 64 for AC 0x10,"
+	" max 32 for AC 0x4)"
+	},
+#ifdef SERDOWNLOAD
+	{ "rwl_download", rwl_download, -1, WLC_SET_VAR,
+	"rwl_download  <firmware> <nvram>\n"
+	"\trwl_download transfer firmware and nvram via remote interface\n"
+	},
+	{ "init", dhd_init, WLC_GET_VAR, WLC_SET_VAR,
+	"init <chip_id>\n"
+	"\tInitialize the chip.\n"
+	"\tCurrently only 4325, 4329, 43291, 4330a1 and 4330 (b1) are supported"
+	},
+	{ "download", dhd_download, WLC_GET_VAR, WLC_SET_VAR,
+	"download  <binfile> <varsfile>\n"
+	"\tdownload file to dongle ram and start CPU\n"
+	"\tvars file will replace vars parsed from the CIS"
+	},
+	{ "upload", dhd_upload, WLC_GET_VAR, WLC_SET_VAR,
+	"upload <file> \n"
+	"\tupload the entire memory and save it to the file"
+	},
+#endif /* SERDOWNLOAD */
+	{ "rpmt", wl_rpmt, -1, WLC_SET_VAR, "rpmt <pm1-to> <pm0-to>"},
+	{ "ie", wl_ie, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get IE\n"
+	"\tUsage: For set: wl ie type length hexdata\n"
+	"\t     For get: wl ie type" },
+	{ "mempool", wlu_mempool, WLC_GET_VAR, -1,
+	"Get memory pool statistics" },
+	{ "leaky_ap_stats", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/disable leaky ap stats collection and reporting\n"
+	"\t0 - disable\n"
+	"\t1 - enable" },
+	{ "leaky_ap_sep", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/disable leaky ap to suppress the early packet before guard start time\n"
+	"\t0 - disable\n"
+	"\t1 - enable" },
+#ifdef SR_DEBUG
+	{ "sr_dump_pmu", wl_dump_pmu, WLC_GET_VAR, WLC_SET_VAR,
+	"Dump value of PMU registers"},
+	{ "sr_pmu_keep_on", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Keep resource on"},
+	{ "sr_power_island", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Keep power islands on/off.\n"
+	"Usage: For get:wl sr_power_island\n"
+	"       For set:wl sr_power_island 0x????\n"
+	"        where ?-> 0 power_island off\n"
+	"              ?-> 1 power_island on\n"
+	"              eg: wl sr_power_island 0x1101"},
+#endif /* SR_DEBUG */
+	{ "antdiv_bcnloss", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"0	- Disable Rx antenna flip feature based on consecutive beacon loss\n"
+	"\tX - beacon loss count after which Rx ant will be flipped\n"
+	"\tUsage: wl antdiv_bcnloss <beaconloss_count>\n"
+	},
+	{ "lpc_params", wl_power_sel_params, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get Link Power Control params\n"
+	"\tUsage: wl lpc_params <rate_stab_thresh> <pwr_stab_thresh>\n"
+	"\t\t<lpc_exp_time> <pwrup_slow_step>\n"
+	"\t\t<pwrup_fast_step> <pwrdn_slow_step>\n"},
+	{ "nar_clear_dump", wl_var_void, -1, WLC_SET_VAR,
+	"Clear non-aggregated regulation counters"},
+	{ "sar_limit", wl_sarlimit, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get sar_limit\n"
+	"\tusage: (set) sar_limit <2Gcore0 2Gcore1 2Gcore2 2Gcore3 5G[0]core0 5G[0]core1...>\n"
+	"\t       (get) sar_limit, return sar limit table\n"
+	"\tunit: all input/output values are absolute and in unit of qdbm\n"
+	},
+	{ "event_log_set_init", wl_event_log_set_init, -1, WLC_SET_VAR,
+	"Initialize an event log set\n"
+	"\tUsage: wl event_log_set_init <set> <size>\n"},
+	{ "event_log_set_expand", wl_event_log_set_expand, -1, WLC_SET_VAR,
+	"Increase the size of an event log set\n"
+	"\tUsage: wl event_log_set_expand <set> <size>\n"},
+	{ "event_log_set_shrink", wl_event_log_set_shrink, -1, WLC_SET_VAR,
+	"Decrease the size of an event log set\n"
+	"\tUsage: wl event_log_set_shrink <set> <[size]>\n"},
+	{ "event_log_tag_control", wl_event_log_tag_control, -1, WLC_SET_VAR,
+	"Modify the state of an event log tag\n"
+	"\tUsage: wl event_log_tag_control <tag> <set> <flags>\n"},
+	{ "event_log_get", wl_event_log_get, -1, WLC_SET_VAR,
+	"\t usage: wl event_log_get [-f <set_num>] [-g <set_num> -s <buf_size>]\n"
+	"\t -f: flush a log buffer of specified set being written  to by trigerring logtrace\n"
+	"\t -g: get a log buffer of a specified set that is full but not delivered to host yet\n"
+	"\t     Store the contents in a buffer of size specified with -s option\n"
+	"\t Note: Only -f option is currently supported\n"
+	},
+	{ "rmc_ar", wl_mcast_ar, WLC_GET_VAR, WLC_SET_VAR,
+	"Set active receiver to the one that matches the provided mac address\n"
+	"If there is no match among current RMC receivers, it will return fail\n"
+	"If mac address is set to all 0 (00:00:00:00:00:00), auto selection mode is enabled\n"
+	"and the transmitter will choose the active receiver automatically by RSSI\n"
+	"\tusage: wl rmc_ar [mac address]\n"
+	"Get the device mac that is set to be the active receiver for this transmitter\n"
+	"\tusage: wl rmc_ar\n"
+	},
+
+	{ "pm2_sleep_ret_ext", wl_sleep_ret_ext, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set Dynamic Fast Return To Sleep params"},
+	{ "sta_monitor", wl_stamon_sta_config, WLC_GET_VAR, WLC_SET_VAR,
+	"wl sta_monitor [enable|disable|counters|reset_cnts] | [<add/del> <xx:xx:xx:xx:xx:xx>]"},
+	{ "monitor_promisc_level", wl_monitor_promisc_level, WLC_GET_VAR, WLC_SET_VAR,
+	"Set a bitmap of different MAC promiscuous level of monitor mode.\n\n"
+	MONITOR_PROMISC_LEVEL_USAGE},
+	{ "aibss_bcn_force_config", wl_aibss_bcn_force_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set AIBSS beacon force configuration \n"
+	"wl aibss_bcn_force_config <initial_min_bcn_dur,min_bcn_dur,initial_bcn_flood_dur>\n"},
+	{"bcnlenhist", wl_bcnlenhist, WLC_GET_VAR, -1,
+	"Usage: wl bcnlenhist [0]"},
+	{ "bss_peer_info", wl_bss_peer_info, WLC_GET_VAR, -1,
+	"Get BSS peer info of all the peer's in the indivudual interface\n"
+	"\tIf a non-zero MAC address is specified, gets the peer info of the PEER alone\n"
+	"\tUsage: wl bss_peer_info [MAC address]"},
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+	{ "dump_modesw_dyn_bwsw", wl_dump_modesw_dyn_bwsw, WLC_GET_VAR, -1,
+	"Usage : wl dump_modesw_dyn_bwsw" },
+#endif
+	{ "pwrstats", wl_pwrstats, WLC_GET_VAR, -1,
+	"Get power usage statistics\n"
+	"Usage: wl pwrstats [<type>] ..."},
+	{ "memuse", wl_memuse, WLC_GET_VAR, -1,
+	"Get memory usage statistics\n"
+	"Usage: wl memuse"},
+	{ "drift_stats_reset", wl_var_void, -1, WLC_SET_VAR,
+	"Reset drift statistics"},
+	{ "aibss_txfail_config", wl_aibss_txfail_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get txfail configuration for bcn_timeout, max tx retries and max atim failures\n"
+	"\tUsage: wl aibss_txfail_config [bcn_timeout max_retry max_atim_failure]"},
+	{ "ibss_route_tbl", wl_setiproute, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set ibss route table\n"
+	"\tUsage: wl ibss_route_tbl num_entries [{ip_addr1, mac_addr1}, ...]"},
+	{ "ip_route_table", wl_setiproute, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set ip route table\n"
+	"\tUsage: wl ip_route_tbl num_entries [{ip_addr1, mac_addr1}, ...]"},
+	{ "rsdb_mode", wl_bcm_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get the RSDB mode. Possible values auto(-1), mimo(0), rsdb(1), 80p80(2)"},
+	{ "desired_bssid", wl_desired_bssid, WLC_GET_DESIRED_BSSID, WLC_SET_DESIRED_BSSID,
+	"Set or get the desired BSS ID value\n"
+	"\tUsage: wl desired_bssid [BSSID]"},
+	{ "ht_features", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"disable/enable/force proprietary 11n rates support. Interface must be down." },
+	{ "modesw_timecal", wl_modesw_timecal, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: \n\t wl modesw_timecal 0~1 for disable /enable \n"
+	"\t wl modesw_timecal to get Time statistics" },
+	{ "atim", wl_int, WLC_GET_ATIM, WLC_SET_ATIM,
+	"Set/Get the current ATIM window size" },
+	{ "pcie_bus_tput", wl_pcie_bus_throughput_params, WLC_GET_VAR, WLC_SET_VAR,
+	"Measure the pcie bus througput\n"
+	"Usage: wl pcie_bus_tput -n 64\n"},
+	{ "interface_create", wl_interface_create_action, -1, WLC_GET_VAR,
+	"create an AP/STA interface on a WLC instance that receives the IOVAR\n"
+	"\tUsage: wl interface_create ap/sta [MAC-address]\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx"
+	},
+	{ "interface_remove", wl_interface_remove_action, -1, WLC_SET_VAR,
+	"Deletes the interface on which this command is received\n"
+	"\tUsage:\n\t wl interface_remove\n"
+	"\t wl -i <interface_name> interface_remove \n"
+	"\t wl interface_remove -C <bss_cfg_index> \n"
+	},
+	{"phy_txpwrcap_tbl", wl_phy_txpwrcap_tbl, WLC_GET_VAR, WLC_SET_VAR,
+	"Get the stored txpwr cap table:\n"
+	"\t\twl phy_txpwrcap_tbl\n"
+	"\tSet the txpwr cap table:\n"
+	"\t\twl phy_txpwrcap_tbl <Na0> <Na1> <Na2> <Na3> <Na4> <Na5> <Na6> <Na7>"
+	" <Cap_cell_ON> <Cap_cell_OFF>\n"
+	"\t\tNaX: Number of Antennas on Core X\n"
+	"\t\tCap_cell_ON: Pwr caps for valid antennas on all cores for Cell On status\n"
+	"\t\tCap_cell_OFF: Pwr caps for valid antennas on all cores for Cell Off status\n"
+	"\t\tPwr Caps are in qdBm, int8 format. Cap_cell_OFF values are optional.\n"},
+	{ "bcntrim_stats", wl_bcntrim_stats, WLC_GET_VAR, -1,
+	"Get Beacon Trim Statistics\n"
+	"\tUsage: wl bcntrim_stats\n"},
+#ifdef ATE_BUILD
+	{ "gpaio", wl_gpaio, NULL, WLC_SET_VAR,
+	"Configure the GPAIO using different options as follows:\n\n"
+	"\tgpaio pmu_afeldo\n\n"
+	"\tgpaio pmu_txldo\n\n"
+	"\tgpaio pmu_vcoldo\n\n"
+	"\tgpaio pmu_lnaldo\n\n"
+	"\tgpaio pmu_adcldo\n\n"
+	"\tgpaio clear\n\n"},
+#endif
+	{ "dfs_ap_move", wl_dfs_ap_move, WLC_GET_VAR, WLC_SET_VAR,
+	"Move the AP interface to dfs channel specified:\n"
+	"\t Default: Get the dfs scan status\n"
+	"\t -1: Abort recent AP move request (if in progress)\n"
+	"\t -2: Stunt recent AP move request (if in progress)\n"
+	"\t20MHz : [5g]<channel>[/20]\n"
+	"\t40MHz : [5g]<channel>/40[u,l]\n"
+	"\t80MHz :    [5g]<channel>/80\n"
+	"\tchannel number (36-200)\n"
+	"\tbandwidth, 20, 40, or 80, default 20\n"
+	"\tprimary sideband for 40MHz on 2g, l=lower, u=upper\n"
+	"OR Set channel with legacy format:\n"
+	"\t-c channel number (36-224)\n"
+	"\t-w bandwidth 20 or 40\n"
+	"\t-s ctl sideband, -1=lower, 0=none, 1=upper"},
+	{"pmac", wl_macdbg_pmac, WLC_GET_VAR, -1,
+	"Get mac obj values such as of SHM and IHR\n"
+	"\tusage: wl pmac <type> <addresses up to 16> -s <step size>"
+	" -n <num> -b <bitmap> -w <write val> -r\n"
+	"<addresses> : a single address, or multiple, upto 16 addresses, in Decimal or Hex\n"
+	"<step size> = 0 or 2 or 4\n"
+	"<num> : how many to print\n"
+	"<bitmap> : 32-bit value\n"
+	"<w_val> : write value to the registers\n"
+	"-r option is used to specify internal address:"},
+	{ "vasip_counters_clear", wl_var_void, -1, WLC_SET_VAR,
+	"clear vasip counters"},
+	{"svmp_mem", wl_svmp_mem, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: wl svmp_mem <offset> <len> [ <val> ]\n"
+	"With 2 params, read svmp memory at offset for len of 16-bit width.\n"
+	"With 3rd param, set the same range to the given value\n"},
+	{"mu_rate", wl_mu_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Force the tranmission rate for each user, rate0 is for user0; rate1 is for user1...\n"
+	"Usage: wl mu_rate { [auto | -1] | [[rate0] [rate1] [rate2] [rate3]]\n"
+	"no input: read current MU-MIMO rate.\n"
+	"auto or -1: turn on auto rate.\n"},
+	{"mu_group", wl_mu_group, WLC_GET_VAR, WLC_SET_VAR,
+	"Force the group recommendation result or set parameters for VASIP group recomendation\n"
+	"\tUsage: no parameters means getting configs\n"
+	"\t  'wl mu_group [-g P0 [P01 P02 ... P04] [... -g Px [Px1 Px2 ... Px4]]] [-f F]'\n"
+	"\t  'wl mu_group [-g -1] [-m M] [-n N]'\n"
+	"\t  Combination of '-g 0 XXX' with '-m M' or '-n N' is invalid\n"
+	"\t       Example1: wl mu_group -g 0 0x016 0x209 0x309 -g 1 0x009 0x217 -g 2 0x115 0x308\n"
+	"\t       Example2: wl mu_group -g 0 0x007 0x109 0x209 0x308 -f 0\n"
+	"\t       Example3: wl mu_group -g -1\n"
+	"\t       Example4: wl mu_group -g -1 -m 1 -n 4\n"
+	"\t       Example5: wl mu_group -m 1 -n 4 (only valid under auto grouping)\n"
+	"\t  -g: Force group recommendation (x<=7, up to 8 options)\n"
+	"\t       P0=-1 means VASIP group recommendation (not-forced mode, default)\n"
+	"\t       P0~Px are expected to be 0~x in forced mode\n"
+	"\t       Pxy: three nibbles for (user_id<<8 + (user_nss-1)<<4 + user_mcs)\n"
+	"\t  -f: Force MCS and only valid with '-g 0 XXX'\n"
+	"\t       F=0: auto MCS from VASIP MCS recommendation\n"
+	"\t       F=1: forced MCS according to '-g' argument (default when froced grouping)\n"
+	"\t  -m: Method for VASIP group recommendation, M>=0\n"
+	"\t       M=0: old method: 1 group for all admitted users with GID=9\n"
+	"\t       M>0: new method: M=1 for N best THPT groups\n"
+	"\t  -n: Number of groups reported to MAC for VASIP group recommendation, N=1~15"},
+	{"mu_policy", wl_mu_policy, WLC_GET_VAR, WLC_SET_VAR,
+	"Configure the MU admission control policies\n"
+	"\tUsage: no parameters means getting configs\n"
+	"\t  'wl mu_policy [-sched_timer T] [-pfmon P] [-pfmon_gpos G] [-samebw B]"
+	" [-nrx R] [-max_muclients C]'\n"
+	"\t       Example1: wl mu_policy -sched_timer 60 -pfmon 1 -pfmon_gpos 0 -samebw 0 -nrx 1\n"
+	"\t       Example2: wl mu_policy -sched_timer 0\n"
+	"\t       Example3: wl mu_policy -pfmon 0\n"
+	"\t       Example4: wl mu_policy -nrx 2\n"
+	"\t       Example5: wl mu_policy -max_muclients 4\n"
+	"\t  -sched_timer: Configure the timer interval for the score based MU client scheduler\n"
+	"\t       T=0 means the scheduler is disabled\n"
+	"\t       T>0 means the timer duration in seconds (default 60)\n"
+	"\t  -pfmon: Configure the perfomance monitors (mutxcnt and gpos)'\n"
+	"\t       P=0: Disable the perfomance monitors\n"
+	"\t       P=1: Enable the perfomance monitors and black lists\n"
+	"\t  -pfmon_gpos: Configure the gpos performance monitor\n"
+	"\t       G=0: Disable the gpos performance monitor\n"
+	"\t       G=1: Enable the gpos performance monitor\n"
+	"\t  -samebw: Configure the BW check at admission control\n"
+	"\t       B=0: Allow clients with different BW to be admitted\n"
+	"\t       B=1: Only clients with the same BW can be admitted\n"
+	"\t  -nrx: Configure the max nrx (number of RX streams) of the clients\n"
+	"\t       R=1: Only 1x1 MU STAs can be admitted\n"
+	"\t       R=2: Both 1x1 and 2x2 MU STAs can be admitted\n"
+	"\t  -max_muclients: Configure the max number of clients\n"
+	"\t       C: Can be a value between 2~8"},
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+	{ "svmp_sampcol", wl_svmp_sampcol, WLC_GET_VAR, WLC_SET_VAR,
+	"No parameters means getting configs\n"
+	"\tOptional parameters for BCM4365 are:\n"
+	"\t-e enable capture, 0: enable, 1: disable,"
+	    "without this field means setting configs only\n"
+	"\t-t trigger mode, 0: pkt-proc transition trigger (need 2 additional states setting),"
+	    "1: force immediate trigger, 2: radar-det trigger\n"
+	"\t-w waiting counter in sample (default: 0)\n"
+	"\t-l capture length in sample (default: 128)\n"
+	"\t-s source select, set phy1_mux and rx1_mux\n"
+	"\t\tphy1_mux, 0: gpioOut, 1: fftOut, 2: dbgHx, 3: rx1mux\n"
+	"\t\trx1_mux, 4: farrowOut, 6: dcFilterOut, 7: rxFilterOut, 8: aciFilterOut\n"
+	"\t-d dual capture mode, use ACPHY sample_collect HW (default: off)\n"
+	"\t\tdata_mux, 4: farrowOut, 5: iqCompOut, 6: dcFilterOut, 7: rxFilterOut\n"
+	"\t-r samplerate, 0: 1xBW, 1: 2xBW (only farrowOut supports 2xBW)\n"
+	"\t-p memory packing selection, set packing_mode, packing_order, packing_format,"
+	    "single-core selection (default 1 0 0 0)\n"
+	"\t\tpacking_mode, 0: for dual capture, 1: 4-core, 2: first 2-core, 3: single-core\n"
+	"\t\tpacking_order, 0: big endian, 1: little endian\n"
+	"\t\tpacking_format, 0: IQswap of cfix, 1: VASIP cfix format,"
+	    "4365A0/B0 only supports IQswap of cfix\n"
+	"\t\tsingle-core selection, 0~3 (4365A0/B0 only forces to core0)\n"
+	"\t-a SVMP buffer address in word size, set addr_start and addr_end"
+	    "(default 0x25800 0x26800)\n"
+	"\t-i send interrupt to VASIP when capture done (default 1)\n"},
+#endif 
+	{ "scanmac", wl_scanmac, WLC_GET_VAR, WLC_SET_VAR,
+	"Configure scan MAC using subcommands:\n"
+	"\tscanmac enable <0|1>\n"
+	"\tscanmac bsscfg\n"
+	"\tscanmac config <mac> <random_mask> <scan_bitmap>\n"},
+	{"mkeep_alive", wl_mkeep_alive, WLC_GET_VAR, WLC_SET_VAR,
+	"Send specified \"mkeep-alive\" packet periodically.\n"
+	"Usage: wl mkeep_alive <index0-7> [[<immediate>] <period> <packet>]\n"
+	"\tindex: 0 - 7 (for set or get).\n"
+	"\timmediate: Send first packet immediately.\n"
+	"\tperiod: Re-transmission period in msecs, 0 to disable.\n"
+	"\tpacket: Hex packet contents to transmit. The packet contents should\n"
+	"\t  include the entire ethernet packet (ethernet header, IP header, UDP\n"
+	"\t  header, and UDP payload) specified in network byte order. If no\n"
+	"\t  packet is specified, a nulldata frame will be sent instead.\n\n"
+	"E.g. Send keep alive packet every 30 seconds using id-1:\n"
+	"\twl mkeep_alive 1 30000 0x0014a54b164f000f66f45b7e08004500001e000040004011c"
+	"52a0a8830700a88302513c413c4000a00000a0d\n" },
+	{ "tcmstbl", wl_get_tcmstbl_entry, WLC_GET_VAR, -1,
+	"Returns the total power in hdBm and the Tx core Mask for the combination: \n"
+	"\t-c core number (0-7) default 0\n"
+	"\t-s cell status (0 or 1) default 0\n"
+	"\t-a antenna map (each nibble holds one core, core0 LSB) default 0x0 \n"},
+	{ "dfs_max_safe_tx", wl_dfs_max_safe_tx, WLC_GET_VAR, WLC_SET_VAR,
+	"Thresholds for tx traffic on main core. On crossing this threshold, scan core \n"
+	"background DFS scan results may be discarded depending on dfs_txblank_check_mode.\n"
+	"\t Default: Get the dfs max safe tx thresholds for non-adjacent (and adjacent) cases.\n"},
+	{ "dfs_txblank_check_mode", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Control if tx on main core must be considered at end of background CAC on scan core.\n"
+	"\t Default: Get the dfs txblank check mode.\n"},
+	{ "nd_ra_limit_intv", wl_nd_ra_limit_intv, WLC_GET_VAR, WLC_SET_VAR,
+	"Get / Set IPv6 RA rate limit interval\n"
+	"\tUsage(Set): nd_ra_limit_intv -t <type> -p <percentage(<100)> -m <fixed time>\n"
+	"\t          : nd_ra_limit_intv -t 0 -p XX -m YYY\n"
+	"\t          : nd_ra_limit_intv -t 1 -m ZZZ\n"
+	"\tUsage(Get): nd_ra_limit_intv\n"
+	"\t<type> 0: percentage of lifetime, 1: fixed time\n"},
+	{"sim_PM", wl_sim_pm, WLC_GET_VAR, WLC_SET_VAR,
+	"Set the fw into a simulated PM in idle associated mode\n"
+	"\t[0 / 1] - Disable / Enable\n\t-c - Cycle time in TUs (max 10,000)\n\t-u Up time in TUs "
+	"(max 1000)\n"},
+	{ "wowl_arp_hostip", wl_hostip, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a host-ip address or display them"},
+	{ "arp_hostip_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear all host-ip addresses"},
+	{ "hc", wl_hc, WLC_GET_VAR, WLC_SET_VAR,
+	"Health Check command group\n"
+	"\tusage: wl hc tx <attribute> [value]\n"
+	"\tusage: wl hc rx <attribute> [value]\n"
+	"\tGet or Set tx/rx attribute values"},
+	{"fbt_r0kh_id", wl_varstr, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set R0 Key Holder Idenitifer for an interface\n"
+	"\tUsage: wl fbt_r0kh_id <string>\n"
+	"String: Maximum 48 byte R0 Key Holder ID\n"},
+	{"fbt_r1kh_id", wl_iov_mac, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set 802.11r R1 Key Holder Idenitifer for an interface\n"
+	"\tUsage: wl fbt_r1kh_id <mac-address>\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx\n"},
+	{"fbt_auth_resp", wl_varstr, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set fbt auth response for an interface\n"
+	"\tUsage: wl fbt_auth_resp <string>\n"
+	"String: Maximum 48 byte FBT auth response\n"},
+	{ "icmp_hostip", wl_hostip, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a host-ip address or display current address set"},
+	{ "icmp_hostipv6", wl_hostipv6_extended, WLC_GET_VAR, WLC_SET_VAR,
+	"Set host-ipv6 address or display current addresses set for icmp offloads\n"
+	"\tUse NULL ipv6 address - :: to flush all addresses\n"
+	"Usage:\n\tSET: wl icmp_hostipv6 <ipv6addr1> <ipv6addr2>\n"
+	"\tGET: wl icmp_hostipv6"},
+	{"wake_timer", wl_wake_timer, WLC_GET_VAR, WLC_SET_VAR,
+	"\tSend wake event to host periodically\n"
+	"\tUsage : wl wake_timer <period> <limit>\n"
+	"\t<period>: value in ms\n"
+	"\t<limit>: value to specify num of events\n"
+	"\t\t 0 : disable\n"
+	"\t\t 0xFFFF : Infinite\n"
+	"\t\t non-zero value: num of events\n"},
+	{ "idauth", wl_idauth, WLC_GET_VAR, WLC_SET_VAR,
+	"IDAUTH command group\n"
+	"\tusage: wl idauth config -a 0/1 -b 1000 -c 3 -e 1000 -g 1000 -m 10\n"
+	"\t\t-a: authentication offload enable/disable \n"
+	"\t\t-c: EAPOL retry count\n"
+	"\t\t-e: EAPOL retry Interval\n"
+	"\t\t-g: GTK rotation interval\n"
+	"\t\t-m: MIC fail count for blacklist\n"
+	"\t\t-b: Blacklist age\n"
+	"\tusage: wl idauth peer_info\n"
+	"\tusage: wl idauth counters\n"},
+	{ "utrace_capture", wl_utrace_capture, WLC_GET_VAR, -1,
+	"Read the template RAM for ucode trace data.\n"},
+	{ "wds_ap_ifname", wl_wds_ap_ifname, WLC_GET_VAR, -1,
+	"Get associated AP interface name for WDS interface."},
+	{ "netx_ping", wl_hostip, -1, WLC_SET_VAR,
+	"Add a host-ip address or display them"},
+	{ "netx_ifconfig", wl_netx_ifconfig, WLC_GET_VAR, WLC_SET_VAR,
+	"Configure the Netx interface, or display current settings\n"
+	"\tUsage: wl netx_ifconfig [<ip> <netmask> <gateway>]\n"},
+#ifdef TBTT_OFFSET_STAT
+	{ "tbtt_offset_stat", wl_tbtt_offset_stat, WLC_GET_VAR, -1,
+	"Get TBTT offset stat (only for STA mode)\n"
+	"\tUsage: wl tbtt_offset_stat\n"},
+#endif /* TBTT_OFFSET_STAT */
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+cmd_t wl_varcmd = {"var", wl_varint, -1, -1, "unrecognized name, type -h for help"};
+
+#ifdef WC_TOOL
+/* Include any commands for wc tool used for WMM
+ * These need to be only the command names from port_cmds and wl_cmds array
+ */
+static const char *wc_cmds[] = {
+	"ver", "cmds", "up", "down",
+	"gmode", "listen", "wme", "wme_ac", "wme_apsd",
+	"wme_apsd_sta", "wme_dp"
+};
+#else
+static const char **wc_cmds = NULL;
+#endif /* WC_TOOL */
+
+
+static const char *dfs_cacstate_str[WL_DFS_CACSTATES] = {
+	"IDLE",
+	"PRE-ISM Channel Availability Check(CAC)",
+	"In-Service Monitoring(ISM)",
+	"Channel Switching Announcement(CSA)",
+	"POST-ISM Channel Availability Check",
+	"PRE-ISM Ouf Of Channels(OOC)",
+	"POST-ISM Out Of Channels(OOC)"
+};
+
+#define MAX_MODULES	256
+static cmd_t* module_cmds[MAX_MODULES];
+static int module_count = 0;
+
+/* register commands for a module */
+void
+wl_module_cmds_register(cmd_t *cmds)
+{
+	if (cmds == NULL)
+		return;
+
+	if (module_count < MAX_MODULES) {
+		module_cmds[module_count] = cmds;
+		module_count++;
+	}
+	else
+		fprintf(stderr, "err - module count over %d\n", MAX_MODULES);
+}
+
+/* common function to find a command */
+cmd_t *
+wlu_find_cmd(char *name)
+{
+	int i;
+	cmd_t *cmd = NULL;
+
+	/* search cmd in modules */
+	for (i = 0; i < module_count; i++) {
+
+		/* search cmd in one cmd table */
+		for (cmd = module_cmds[i]; cmd->name; cmd++) {
+			/* stop if we find a matching name */
+			if (!strcmp(cmd->name, name)) {
+				break;
+			}
+		}
+
+		/* if a match was found, break out of module loop */
+		if (cmd->name != NULL) {
+			break;
+		}
+	}
+
+	return (cmd->name != NULL) ? cmd : NULL;
+}
+
+/* return global ioctl_version */
+int
+wl_get_ioctl_version(void)
+{
+	return ioctl_version;
+}
+
+/* return the address of bufstruct_wlu, global buf */
+char *
+wl_get_buf(void)
+{
+	return buf;
+}
+
+/* initialize stuff needed before processing the command */
+void
+wl_cmd_init(void)
+{
+	int_fmt = INT_FMT_DEC;
+	g_wlc_idx = -1;
+}
+
+void
+wlu_init(void)
+{
+	/* Init global variables at run-time, not as part of the declaration.
+	 * This is required to support init/de-init of the driver. Initialization
+	 * of globals as part of the declaration results in non-deterministic
+	 * behaviour since the value of the globals may be different on the
+	 * first time that the driver is initialized vs subsequent initializations.
+	 */
+	int_fmt = INT_FMT_DEC;
+	g_wlc_idx = -1;
+	batch_in_client = FALSE;
+	init_cmd_batchingmode();
+
+	/* register general wl commands */
+	wl_module_cmds_register(wl_cmds);
+
+	/* add wluc module init here */
+	wluc_phy_module_init();
+	wluc_wnm_module_init();
+	wluc_cac_module_init();
+	wluc_rmc_module_init();
+	wluc_rrm_module_init();
+	wluc_wowl_module_init();
+	wluc_pkt_filter_module_init();
+	wluc_mfp_module_init();
+	wluc_ota_module_init();
+	wluc_bssload_module_init();
+	wluc_stf_module_init();
+	wluc_offloads_module_init();
+	wluc_tpc_module_init();
+	wluc_toe_module_init();
+	wluc_arpoe_module_init();
+	wluc_keep_alive_module_init();
+	wluc_ap_module_init();
+	wluc_ampdu_module_init();
+	wluc_ampdu_cmn_module_init();
+	wluc_bmac_module_init();
+	wluc_ht_module_init();
+	wluc_wds_module_init();
+	wluc_keymgmt_module_init();
+	wluc_scan_module_init();
+	wluc_obss_module_init();
+	wluc_prot_obss_module_init();
+	wluc_lq_module_init();
+	wluc_seq_cmds_module_init();
+	wluc_btcx_module_init();
+	wluc_led_module_init();
+	wluc_interfere_module_init();
+	wluc_ltecx_module_init();
+#ifdef WLEXTLOG
+	wluc_extlog_module_init();
+#endif /* WLEXTLOG */
+#ifdef WL_NAN
+	wluc_nan_module_init();
+#endif /* WL_NAN */
+#ifdef WLNDOE
+	wluc_ndoe_module_init();
+#endif /* WLNDOE */
+#ifdef WLPFN
+	wluc_pfn_module_init();
+#endif /* WLPFN */
+#ifdef BT_WIFI_HANDOVER
+	wluc_tbow_module_init();
+#endif /* BT_WIFI_HANDOVER */
+#ifdef WLP2P
+	wluc_p2p_module_init();
+#endif /* WLP2PO */
+#ifdef WLTDLS
+	wluc_tdls_module_init();
+#endif /* WLTDLS */
+#ifdef TRAFFIC_MGMT
+	wluc_trf_mgmt_module_init();
+#endif /* TRAFFIC_MGMT */
+#ifdef WL_PROXDETECT
+	wluc_proxd_module_init();
+#endif /* WL_PROXDETECT */
+#ifdef WLP2PO
+	wluc_p2po_module_init();
+#endif /* WLP2PO */
+#ifdef WLANQPO
+	wluc_anqpo_module_init();
+#endif /* WLANQPO */
+#ifdef WL_BTCDYN
+	wluc_btcdyn_module_init();
+#endif /* WL_BTCDYN */
+#ifdef WLMESH
+	wluc_mesh_module_init();
+#endif /* WLMESH */
+#ifdef WL_MSCH
+	wluc_msch_module_init();
+#endif /* WL_MSCH */
+#ifdef WLBDO
+	wluc_bdo_module_init();
+#endif /* WLBDO */
+#ifdef WL_RANDMAC
+	wluc_randmac_module_init();
+#endif /* WL_RANDMAC */
+#ifdef WLTKO
+	wluc_tko_module_init();
+#endif /* WLTKO */
+#ifdef WL_NATOE
+	wluc_natoe_module_init();
+#endif /* WL_NATOE */
+#ifdef WLRSDB
+	wluc_rsdb_module_init();
+#endif
+	wluc_he_module_init();
+#ifdef WL_MBO
+	wluc_mbo_module_init();
+#endif /* WL_MBO */
+#ifdef ECOUNTERS
+	wluc_ecounters_module_init();
+#endif
+#ifdef HOFFLOAD_MODULES
+	wluc_hoffload_module_init();
+#endif /* HOFFLOAD_MODULES */
+}
+
+int wlc_ver_major(void *wl)
+{
+	int err;
+	wl_wlc_version_t wlc_ver;
+
+	memset(&wlc_ver, 0, sizeof(wlc_ver));
+	err = wlu_iovar_get(wl, "wlc_ver", &wlc_ver, sizeof(wl_wlc_version_t));
+	if (err != BCME_OK) {
+		printf("Unable to get wlc_ver iovar %d\n", err);
+		/* old firmware may not support it */
+		return 0;
+	}
+	return wlc_ver.wlc_ver_major;
+}
+
+int
+wl_check(void *wl)
+{
+	int ret;
+	int val;
+
+	if ((ret = wlu_get(wl, WLC_GET_MAGIC, &val, sizeof(int))) < 0)
+		return ret;
+
+	/* Detect if IOCTL swapping is necessary */
+	if (val == (int)bcmswap32(WLC_IOCTL_MAGIC))
+	{
+		val = bcmswap32(val);
+		g_swap = TRUE;
+	}
+	if (val != WLC_IOCTL_MAGIC)
+		return -1;
+	if ((ret = wlu_get(wl, WLC_GET_VERSION, &val, sizeof(int))) < 0)
+		return ret;
+	ioctl_version = dtoh32(val);
+	if (ioctl_version != WLC_IOCTL_VERSION &&
+	    ioctl_version != 1) {
+		fprintf(stderr, "Version mismatch, please upgrade. Got %d, expected %d or 1\n",
+		        ioctl_version, WLC_IOCTL_VERSION);
+		return -1;
+	}
+	return 0;
+}
+
+int
+ARGCNT(char **argv)
+{
+	int i;
+
+	for (i = 0; argv[i] != NULL; i ++)
+		;
+	return i;
+}
+
+/* parse/validate the command line arguments */
+/*
+ * pargv is updated upon return if the first argument is an option.
+ * It remains intact otherwise.
+ */
+int
+wl_option(char ***pargv, char **pifname, int *phelp)
+{
+	char *ifname = NULL;
+	int help = FALSE;
+	int status = CMD_OPT;
+	char **argv = *pargv;
+
+	while (*argv) {
+		/* select different adapter */
+		if (!strcmp(*argv, "-a") || !strcmp(*argv, "-i")) {
+			char *opt = *argv++;
+			ifname = *argv;
+			if (!ifname) {
+				fprintf(stderr,
+					"error: expected interface name after option %s\n", opt);
+				status = CMD_ERR;
+				break;
+			}
+		}
+		/* integer output format */
+		else if (!strcmp(*argv, "-d"))
+			int_fmt = INT_FMT_DEC;
+		else if (!strcmp(*argv, "-u"))
+			int_fmt = INT_FMT_UINT;
+		else if (!strcmp(*argv, "-x"))
+			int_fmt = INT_FMT_HEX;
+
+		/* command usage */
+		else if (!strcmp(*argv, "-h") || !strcmp(*argv, "--help"))
+			help = TRUE;
+
+		else if (!strcmp(*argv, "--clientbatch")) {
+			wl_seq_batch_in_client(TRUE);
+		}
+		/* To handle endian mis-matches between wl utility and wl driver */
+		else if (!strcmp(*argv, "--es")) {
+			g_swap = TRUE;
+		}
+		else if (!stricmp(*argv, "-W") || !strcmp(*argv, "--wlc")) {
+			char *opt = *argv++;
+			char *endptr = NULL;
+			if (*argv) {
+				g_wlc_idx = strtol(*argv, &endptr, 0);
+			}
+			if (endptr == *argv) {
+				fprintf(stderr,
+					"error: expected wlc integer index after option %s\n", opt);
+				status = CMD_ERR;
+				/* just to ensure that we trigger error */
+				argv--;
+				break;
+			}
+		}
+		/* start of non wl options */
+		else {
+			status = CMD_WL;
+			break;
+		}
+		/* consume the argument */
+		argv ++;
+		break;
+	}
+
+	*phelp = help;
+	*pifname = ifname;
+	*pargv = argv;
+
+	return status;
+}
+
+void
+wl_cmd_usage(FILE *fid, cmd_t *cmd)
+{
+	if (strlen(cmd->name) >= 8)
+		fprintf(fid, "%s\n\t%s\n\n", cmd->name, cmd->help);
+	else
+		fprintf(fid, "%s\t%s\n\n", cmd->name, cmd->help);
+}
+
+static int
+wl_print_deprecate(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(argv);
+
+	wl_cmd_usage(stderr, cmd); /* warning string is in command table */
+	return 0;
+}
+
+/* Dump out short list of commands */
+static int
+wl_list(void *wl, cmd_t *garb, char **argv)
+{
+	cmd_t *cmd;
+	int nrows, i, len;
+	char *list_buf;
+	int letter, col, row, pad;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(garb);
+	UNUSED_PARAMETER(argv);
+
+	nrows = 0;
+	for (i = 0; i < module_count; i++) {
+		for (cmd = module_cmds[i]; cmd->name; cmd++)
+		/* Check for wc_cmd */
+		if (wc_cmd_check(cmd->name))
+		    nrows++;
+	}
+
+	nrows /= 4;
+	nrows++;
+
+	len = nrows * 80 + 2;
+	list_buf = malloc(len);
+	if (list_buf == NULL) {
+		fprintf(stderr, "Failed to allocate buffer of %d bytes\n", len);
+		return BCME_NOMEM;
+	}
+	for (i = 0; i < len; i++)
+		*(list_buf+i) = 0;
+
+	row = col = 0;
+	for (letter = 'a'; letter < 'z'; letter++) {
+		for (i = 0; i < module_count; i++) {
+			for (cmd = module_cmds[i]; cmd->name; cmd++) {
+				/* Check for wc_cmd */
+				if (!wc_cmd_check(cmd->name))
+					continue;
+				if (cmd->name[0] == letter || cmd->name[0] == letter - 0x20) {
+					strcat(list_buf+row*80, cmd->name);
+					pad = 18 * (col + 1) - strlen(list_buf+row*80);
+					if (pad < 1)
+						pad = 1;
+					for (; pad; pad--)
+						strcat(list_buf+row*80, " ");
+					row++;
+					if (row == nrows) {
+						col++; row = 0;
+					}
+				}
+			}
+		}
+	}
+	for (row = 0; row < nrows; row++)
+		printf("%s\n", list_buf+row*80);
+
+	printf("\n");
+
+	free(list_buf);
+	return (0);
+}
+
+void
+wl_cmds_usage(FILE *fid, cmd_t *port_cmds)
+{
+	cmd_t *port_cmd;
+	cmd_t *cmd;
+	int i;
+
+	/* print usage of port commands */
+	for (port_cmd = port_cmds; port_cmd && port_cmd->name; port_cmd++)
+		/* Check for wc_cmd */
+		if (wc_cmd_check(port_cmd->name))
+			wl_cmd_usage(fid, port_cmd);
+
+	/* print usage of common commands without port counterparts */
+	for (i = 0; i < module_count; i++) {
+		for (cmd = module_cmds[i]; cmd->name; cmd++) {
+			/* search if port counterpart exists */
+			for (port_cmd = port_cmds; port_cmd && port_cmd->name; port_cmd++)
+				if (!strcmp(port_cmd->name, cmd->name))
+					break;
+			/* Also, check for this being a wc_cmd */
+			if ((!port_cmd || !port_cmd->name) && (wc_cmd_check(cmd->name)))
+				wl_cmd_usage(fid, cmd);
+		}
+	}
+}
+
+void
+wl_usage(FILE *fid, cmd_t *port_cmds)
+{
+	fprintf(fid, "Usage: %s [-a|i <adapter>]"
+		" [-h] [-d|u|x] [-w|--wlc <index>] <command> [arguments]\n", wlu_av0);
+
+	fprintf(fid, "\n");
+	fprintf(fid, "  -h        this message and command descriptions\n");
+	fprintf(fid, "  -h [cmd]  command description for cmd\n");
+	fprintf(fid, "  -a, -i    adapter name or number\n");
+	fprintf(fid, "  -d        output format signed integer\n");
+	fprintf(fid, "  -u        output format unsigned integer\n");
+	fprintf(fid, "  -x        output format hexdecimal\n");
+	fprintf(fid, "  -w <idx>  index of WLC for RSDB only\n");
+	fprintf(fid, "\n");
+
+	wl_cmds_usage(fid, port_cmds);
+}
+
+void
+wl_printint(int val)
+{
+	switch (int_fmt) {
+	case INT_FMT_UINT:
+		printf("%u\n", val);
+		break;
+	case INT_FMT_HEX:
+		printf("0x%x\n", val);
+		break;
+	case INT_FMT_DEC:
+	default:
+		printf("%d\n", val);
+		break;
+	}
+}
+
+
+/* Common routine to check for an option arg specifying the configuration index.
+ * Takes the syntax -C num, --cfg=num, --config=num, or --configuration=num
+ * Returns BCME_BADARG if there is a command line parsing error.
+ * Returns 0 if no error, and sets *consumed to the number of argv strings
+ * used. Sets *bsscfg_idx to the index to use. Will set *bsscfg_idx to zero if there
+ * was no config arg.
+ */
+int
+wl_cfg_option(char **argv, const char *fn_name, int *bsscfg_idx, int *consumed)
+{
+	miniopt_t mo;
+	int opt_err;
+
+	*bsscfg_idx = 0;
+	*consumed = 0;
+
+	miniopt_init(&mo, fn_name, NULL, FALSE);
+
+	/* process the first option */
+	opt_err = miniopt(&mo, argv);
+
+	/* check for no args or end of options */
+	if (opt_err == -1)
+		return 0;
+
+	/* check for no options, just a positional arg encountered */
+	if (mo.positional)
+		return 0;
+
+	/* check for error parsing options */
+	if (opt_err == 1)
+		return BCME_USAGE_ERROR;
+
+	/* check for -C, --cfg=X, --config=X, --configuration=X */
+	if (mo.opt == 'C' ||
+	    !strcmp(mo.key, "cfg") ||
+	    !strcmp(mo.key, "config") ||
+	    !strcmp(mo.key, "configuration")) {
+		if (!mo.good_int) {
+			fprintf(stderr,
+			"%s: could not parse \"%s\" as an integer for the configuartion index\n",
+			fn_name, mo.valstr);
+			return BCME_BADARG;
+		}
+		*bsscfg_idx = mo.val;
+		*consumed = mo.consumed;
+	}
+
+	return 0;
+}
+
+int
+wl_void(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(argv);
+
+	if (cmd->set < 0)
+		return -1;
+	return wlu_set(wl, cmd->set, NULL, 0);
+}
+
+int
+wl_int(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char *endptr = NULL;
+
+	if (!*++argv) {
+		if (cmd->get == -1)
+			return -1;
+		if ((ret = wlu_get(wl, cmd->get, &val, sizeof(int))) < 0)
+			return ret;
+
+		val = dtoh32(val);
+		wl_printint(val);
+	} else {
+		if (cmd->set == -1)
+			return -1;
+		if (!stricmp(*argv, "on"))
+			val = 1;
+		else if (!stricmp(*argv, "off"))
+			val = 0;
+		else {
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		val = htod32(val);
+		ret = wlu_set(wl, cmd->set, &val, sizeof(int));
+	}
+
+	return ret;
+}
+
+int wl_buf(void *wl, cmd_t *cmd, char **argv)
+{
+	char* data;
+	int err;
+	int len;
+	int i;
+
+	strcpy(buf, cmd->name);
+
+	/* set */
+	if (argv[1]) {
+		len = strlen(buf);
+		data = argv[1];
+		for (i = len + 1, len += 1 + strlen(data) / 2;
+		    (i < len) && (i < (int)WLC_IOCTL_SMLEN); i ++) {
+			char hex[] = "XX";
+			hex[0] = *data++;
+			hex[1] = *data++;
+			buf[i] = (uint8)strtoul(hex, NULL, 16);
+		}
+		err = wlu_set(wl, WLC_SET_VAR, buf, i);
+	}
+	/* get */
+	else if (!(err = wlu_get(wl, WLC_GET_VAR, buf, WLC_IOCTL_SMLEN))) {
+		len = dtoh32(*(int *)buf);
+		if (len > WLC_IOCTL_SMLEN) {
+			data = buf + sizeof(int);
+			for (i = 0; i < len; i ++)
+				printf("%02x", (uint8)(data[i]));
+			printf("\n");
+		} else {
+			err = BCME_BUFTOOLONG;
+		}
+	}
+
+	return err;
+}
+
+/* Return a new chanspec given a legacy chanspec
+ * Returns INVCHANSPEC on error
+ */
+static chanspec_t
+wl_chspec_from_legacy(chanspec_t legacy_chspec)
+{
+	chanspec_t chspec;
+
+	/* get the channel number */
+	chspec = LCHSPEC_CHANNEL(legacy_chspec);
+
+	/* convert the band */
+	if (LCHSPEC_IS2G(legacy_chspec)) {
+		chspec |= WL_CHANSPEC_BAND_2G;
+	} else {
+		chspec |= WL_CHANSPEC_BAND_5G;
+	}
+
+	/* convert the bw and sideband */
+	if (LCHSPEC_IS20(legacy_chspec)) {
+		chspec |= WL_CHANSPEC_BW_20;
+	} else {
+		chspec |= WL_CHANSPEC_BW_40;
+		if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
+			chspec |= WL_CHANSPEC_CTL_SB_L;
+		} else {
+			chspec |= WL_CHANSPEC_CTL_SB_U;
+		}
+	}
+
+	if (wf_chspec_malformed(chspec)) {
+		fprintf(stderr, "wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
+		        chspec);
+		return INVCHANSPEC;
+	}
+
+	return chspec;
+}
+
+/* Return a legacy chanspec given a new chanspec
+ * Returns INVCHANSPEC on error
+ */
+chanspec_t
+wl_chspec_to_legacy(chanspec_t chspec)
+{
+	chanspec_t lchspec;
+
+	if (wf_chspec_malformed(chspec)) {
+		fprintf(stderr, "wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
+		        chspec);
+		return INVCHANSPEC;
+	}
+
+	/* get the channel number */
+	lchspec = CHSPEC_CHANNEL(chspec);
+
+	/* convert the band */
+	if (CHSPEC_IS2G(chspec)) {
+		lchspec |= WL_LCHANSPEC_BAND_2G;
+	} else {
+		lchspec |= WL_LCHANSPEC_BAND_5G;
+	}
+
+	/* convert the bw and sideband */
+	if (CHSPEC_IS20(chspec)) {
+		lchspec |= WL_LCHANSPEC_BW_20;
+		lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
+	} else if (CHSPEC_IS40(chspec)) {
+		lchspec |= WL_LCHANSPEC_BW_40;
+		if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
+			lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
+		} else {
+			lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
+		}
+	} else {
+		/* cannot express the bandwidth */
+		char chanbuf[CHANSPEC_STR_LEN];
+		fprintf(stderr,
+		        "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
+		        "to pre-11ac format\n",
+		        wf_chspec_ntoa(chspec, chanbuf), chspec);
+		return INVCHANSPEC;
+	}
+
+	return lchspec;
+}
+
+/* given a chanspec value, do the endian and chanspec version conversion to
+ * a chanspec_t value
+ * Returns INVCHANSPEC on error
+ */
+chanspec_t
+wl_chspec_to_driver(chanspec_t chanspec)
+{
+	if (ioctl_version == 1) {
+		chanspec = wl_chspec_to_legacy(chanspec);
+		if (chanspec == INVCHANSPEC) {
+			return chanspec;
+		}
+	}
+	chanspec = htodchanspec(chanspec);
+
+	return chanspec;
+}
+
+/* given a chanspec value, do the endian and chanspec version conversion to
+ * a chanspec_t value in a 32 bit integer
+ * Returns INVCHANSPEC on error
+ */
+uint32
+wl_chspec32_to_driver(chanspec_t chanspec)
+{
+	uint32 val;
+
+	if (ioctl_version == 1) {
+		chanspec = wl_chspec_to_legacy(chanspec);
+		if (chanspec == INVCHANSPEC) {
+			return chanspec;
+		}
+	}
+	val = htod32((uint32)chanspec);
+
+	return val;
+}
+
+/* given a chanspec value from the driver, do the endian and chanspec version conversion to
+ * a chanspec_t value
+ * Returns INVCHANSPEC on error
+ */
+chanspec_t
+wl_chspec_from_driver(chanspec_t chanspec)
+{
+	chanspec = dtohchanspec(chanspec);
+	if (ioctl_version == 1) {
+		chanspec = wl_chspec_from_legacy(chanspec);
+	}
+	return chanspec;
+}
+
+/* given a chanspec value from the driver in a 32 bit integer, do the endian and
+ * chanspec version conversion to a chanspec_t value
+ * Returns INVCHANSPEC on error
+ */
+chanspec_t
+wl_chspec32_from_driver(uint32 chanspec32)
+{
+	chanspec_t chanspec;
+
+	chanspec = (chanspec_t)dtoh32(chanspec32);
+
+	if (ioctl_version == 1) {
+		chanspec = wl_chspec_from_legacy(chanspec);
+	}
+	return chanspec;
+}
+
+#ifdef CLMDOWNLOAD
+/*
+Generic interface for downloading required data onto the dongle
+*/
+int
+download2dongle(void *wl, char *iovar, uint16 flag, uint16 dload_type,
+	unsigned char *dload_buf, int len)
+{
+	struct wl_dload_data *dload_ptr = (struct wl_dload_data *)dload_buf;
+	int err = 0;
+	int dload_data_offset;
+
+	dload_data_offset = OFFSETOF(wl_dload_data_t, data);
+	dload_ptr->flag = (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT) | flag;
+	dload_ptr->dload_type = dload_type;
+	dload_ptr->len = htod32(len - dload_data_offset);
+	dload_ptr->crc = 0;
+	len = len + 8 - (len%8);
+
+	err = wlu_iovar_setbuf(wl, iovar,
+		dload_buf, len, buf, WLC_IOCTL_MEDLEN);
+	return err;
+}
+
+int
+dload_clm(void *wl, uint32 datalen, unsigned char *org_buf, int ds_id)
+{
+	int num_chunks, chunk_len, cumulative_len = 0;
+	int size2alloc;
+	unsigned char *new_buf;
+	wl_clm_dload_info_t *clm_info_ptr;
+	int err = 0, clm_info_offset, chunk_offset;
+
+	clm_info_offset = OFFSETOF(wl_dload_data_t, data);
+	chunk_offset = OFFSETOF(wl_clm_dload_info_t, data_chunk);
+
+	num_chunks = datalen/MAX_CHUNK_LEN;
+	if (datalen % MAX_CHUNK_LEN != 0)
+		num_chunks++;
+	size2alloc = clm_info_offset + chunk_offset + MAX_CHUNK_LEN;
+
+	if ((new_buf = (unsigned char *)malloc(size2alloc)) != NULL) {
+		memset(new_buf, 0, size2alloc);
+		clm_info_ptr = (wl_clm_dload_info_t*)((uint8 *)new_buf + clm_info_offset);
+		clm_info_ptr->num_chunks = num_chunks;
+		clm_info_ptr->clm_total_len = datalen;
+		clm_info_ptr->ds_id = ds_id;
+		do {
+			if (datalen >= MAX_CHUNK_LEN)
+				chunk_len = MAX_CHUNK_LEN;
+			else
+				chunk_len = datalen;
+			memset(new_buf + clm_info_offset + chunk_offset, 0,
+				size2alloc - clm_info_offset - chunk_offset);
+			clm_info_ptr->chunk_len = htod32(chunk_len);
+
+			memcpy(&clm_info_ptr->data_chunk[0], org_buf + cumulative_len, chunk_len);
+			clm_info_ptr->chunk_offset = cumulative_len;
+			cumulative_len += chunk_len;
+
+			err = download2dongle(wl, "generic_dload", 0, DL_TYPE_CLM, new_buf,
+				chunk_len + clm_info_offset + chunk_offset);
+
+			datalen = datalen - chunk_len;
+		} while ((datalen > 0) && (err == 0));
+		free(new_buf);
+	} else {
+		err = BCME_NOMEM;
+	}
+
+	return err;
+}
+
+int
+dload_blob(void *wl, char *iovar, unsigned char *org_buf, uint32 datalen)
+{
+	int chunk_len, cumulative_len = 0;
+	int size2alloc;
+	unsigned char *new_buf;
+	int err = 0, data_offset;
+	uint16 dl_flag = DL_BEGIN;
+
+	data_offset = OFFSETOF(wl_dload_data_t, data);
+	size2alloc = data_offset + MAX_CHUNK_LEN;
+
+	if ((new_buf = (unsigned char *)malloc(size2alloc)) != NULL) {
+		memset(new_buf, 0, size2alloc);
+
+		do {
+			if (datalen >= MAX_CHUNK_LEN)
+				chunk_len = MAX_CHUNK_LEN;
+			else
+				chunk_len = datalen;
+
+			memcpy(new_buf + data_offset, org_buf + cumulative_len, chunk_len);
+			cumulative_len += chunk_len;
+
+			if (datalen - chunk_len == 0)
+				dl_flag |= DL_END;
+
+			err = download2dongle(wl, iovar, dl_flag, DL_TYPE_CLM,
+				new_buf, data_offset + chunk_len);
+			dl_flag &= ~DL_BEGIN;
+
+			datalen = datalen - chunk_len;
+		} while ((datalen > 0) && (err == 0));
+
+		free(new_buf);
+	} else {
+		err = BCME_NOMEM;
+	}
+
+	return err;
+}
+
+int
+dload_clm_blob(void *wl, unsigned char *org_buf, uint32 datalen)
+{
+	int chunk_len, cumulative_len = 0;
+	int size2alloc;
+	unsigned char *new_buf;
+	int err = 0, data_offset;
+	uint16 dl_flag = DL_BEGIN;
+
+	data_offset = OFFSETOF(wl_dload_data_t, data);
+	size2alloc = data_offset + MAX_CHUNK_LEN;
+
+	if ((new_buf = (unsigned char *)malloc(size2alloc)) != NULL) {
+		memset(new_buf, 0, size2alloc);
+
+		do {
+			if (datalen >= MAX_CHUNK_LEN)
+				chunk_len = MAX_CHUNK_LEN;
+			else
+				chunk_len = datalen;
+
+			memcpy(new_buf + data_offset, org_buf + cumulative_len, chunk_len);
+			cumulative_len += chunk_len;
+
+			if (datalen - chunk_len == 0)
+				dl_flag |= DL_END;
+
+			err = download2dongle(wl, "clmload", dl_flag, DL_TYPE_CLM,
+				new_buf, data_offset + chunk_len);
+			dl_flag &= ~DL_BEGIN;
+
+			datalen = datalen - chunk_len;
+		} while ((datalen > 0) && (err == 0));
+
+		free(new_buf);
+	} else {
+		err = BCME_NOMEM;
+	}
+
+	return err;
+}
+
+#define CLM_INPUT_FILE_MIN_LEN 32
+int
+process_clm_data(void *wl, char *clmfn, int ds_id)
+{
+	int ret = 0;
+
+	FILE *fp = NULL;
+
+	unsigned int clm_filelen;
+	unsigned long status = 0;
+	unsigned char *new_buf = NULL;
+	uint32 clm_data_len;
+	unsigned char *new_ptr;
+	int filelen = 0;
+	const char clm_magic_string[] = {'C', 'L', 'M', ' ', 'D', 'A', 'T', 'A'};
+	const char blob_magic_string[] = {'B', 'L', 'O', 'B'};
+
+	/* Open the clm download file */
+	if (!(fp = fopen(clmfn, "rb"))) {
+		fprintf(stderr, "unable to open input file %s\n", clmfn);
+		ret = BCME_BADARG;
+		goto error;
+	}
+
+	/* fstat is a linux/unix, not a stdio function. This is replaced everywhere with function
+	 * fsize() which calls fseek(fp, 0L, SEEK_END), ftell(fp), fseek(fp, 0L, SEEK_SET) sequence
+	 * to determine the file size.
+	 */
+
+	if ((filelen = fsize(fp)) < 0) {
+		fprintf(stderr, "fseek or ftell on input file %s return error %s\n",
+			clmfn, strerror(errno));
+		ret = BCME_ERROR;
+		goto error;
+	}
+	clm_filelen = (uint)filelen;
+
+	if (clm_filelen == 0) {
+		fprintf(stderr, "input file %s is empty (i.e. zero length)\n", clmfn);
+		ret = BCME_ERROR;
+		goto error;
+	}
+
+	if ((new_buf = malloc(clm_filelen)) == NULL) {
+		fprintf(stderr, "unable to allocate %u bytes based on input file size!\n",
+			clm_filelen);
+		ret = BCME_NOMEM;
+		goto error;
+	}
+
+	/* We can read a CLM binary file or CLM blob file.  The CLM binary file has
+	 * been obsoleted in favor of the "blob" format that allows additional data
+	 * to included in a modular/independent way.  The blob format is downloaded
+	 * via the new 'clmload' iovar.  The binary format uses the legacy and now obsolete
+	 * 'generic_dload' iovar.
+	 *
+	 * Newer driver builds no longer support the generic_dload iovar but this wl
+	 * command utility will support either format/iovar combination based on the
+	 * download file's magic string for some transition time.
+	 */
+
+	status = fread(new_buf, 1, clm_filelen, fp);
+
+	/* Basic sanity check on size. Make sure there is enough for any magic string plus
+	 * a little more for good measure.
+	 */
+	if (status < CLM_INPUT_FILE_MIN_LEN) {
+		fprintf(stderr, "size of input file %s is less than %d bytes."
+			"  This can't be a CLM file!\n", clmfn, CLM_INPUT_FILE_MIN_LEN);
+		ret = BCME_ERROR;
+		goto error;
+	} else if (status != clm_filelen) {
+		fprintf(stderr, "read of input file %s wasn't good based on fstat size %u\n",
+			clmfn, clm_filelen);
+		ret = BCME_ERROR;
+		goto error;
+	}
+
+	/* CLM blob or binary format file? */
+	if (memcmp(new_buf, blob_magic_string, sizeof(blob_magic_string)) == 0) {
+		/* CLM blob file? They start with magic string 'BLOB' */
+		printf("Downloading CLM blob format file %s\n", clmfn);
+		ret = dload_clm_blob(wl, new_buf, clm_filelen);
+	} else if (memcmp(new_buf, clm_magic_string, sizeof(clm_magic_string)) == 0) {
+		/* pure CLM binary file?  CLM binary files start with 'CLM DATA' */
+		clm_data_len = clm_filelen;
+		new_ptr = new_buf;
+		printf("Downloading legacy, obsolete CLM binary format file %s as a %s CLM\n",
+			clmfn, ds_id ? "incremental":"base");
+		ret = dload_clm(wl, clm_data_len, new_ptr, ds_id);
+	} else {
+		fprintf(stderr, "input file is missing CLM binary or CLM blob magic string\n");
+		ret = -1;
+		goto error;
+	}
+error:
+	if (new_buf)
+		free(new_buf);
+	if (fp)
+		fclose(fp);
+
+	return ret;
+}
+
+#define TXCAP_INPUT_FILE_MIN_LEN 32
+
+int
+process_txcap_data(void *wl, char *txcapfn)
+{
+	int ret = 0;
+
+	FILE *fp = NULL;
+
+	unsigned int txcap_filelen;
+	unsigned long status = 0;
+	unsigned char *new_buf = NULL;
+	int filelen = 0;
+
+	/* Open the txcap download file */
+	if (!(fp = fopen(txcapfn, "rb"))) {
+		fprintf(stderr, "unable to open input file %s\n", txcapfn);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* fstat is a linux/unix, not a stdio function. This is replaced everywhere with function
+	 * fsize() which calls fseek(fp, 0L, SEEK_END), ftell(fp), fseek(fp, 0L, SEEK_SET) sequence
+	 * to determine the file size.
+	 */
+
+	if ((filelen = fsize(fp)) < 0) {
+		fprintf(stderr, "fseek or ftell on input file %s return error %s\n",
+			txcapfn, strerror(errno));
+		ret = -EINVAL;
+		goto error;
+	}
+	txcap_filelen = (uint)filelen;
+
+	if (txcap_filelen == 0) {
+		fprintf(stderr, "input file %s is empty (i.e. zero length)\n", txcapfn);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	if ((new_buf = malloc(txcap_filelen)) == NULL) {
+		fprintf(stderr, "unable to allocate %u bytes based on input file size!\n",
+			txcap_filelen);
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	status = fread(new_buf, 1, txcap_filelen, fp);
+
+	if (status != txcap_filelen) {
+		fprintf(stderr, "read of input file %s wasn't good based on fstat size %u\n",
+			txcapfn, txcap_filelen);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* Basic sanity check on size. Make sure there is enough for any magic string plus
+	 * a little more for good measure.
+	 */
+	if (status < TXCAP_INPUT_FILE_MIN_LEN) {
+		fprintf(stderr, "size of input file %s is less than %d bytes."
+			"  This can't be a txcap file!\n", txcapfn, TXCAP_INPUT_FILE_MIN_LEN);
+		ret = -EINVAL;
+		goto error;
+	} else if (status != txcap_filelen) {
+		fprintf(stderr, "read of input file %s wasn't good based on fstat size %u\n",
+			txcapfn, txcap_filelen);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* txcap package? */
+	if (memcmp(new_buf, blob_magic_string, sizeof(blob_magic_string)) == 0) {
+		/* MSF packaged file? They start with magic string 'BLOB' */
+		printf("Downloading txcap package format file %s\n", txcapfn);
+		ret = dload_blob(wl, "txcapload", new_buf, txcap_filelen);
+	} else {
+		fprintf(stderr, "input file is missing txcap package magic string\n");
+		ret = -1;
+		goto error;
+	}
+
+error:
+	if (new_buf)
+		free(new_buf);
+	if (fp)
+		fclose(fp);
+
+	return ret;
+}
+
+static int
+wl_clmload(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	char *arg1;
+	char *arg2;
+	char* fname;
+
+	BCM_REFERENCE(cmd);
+
+	/* argv is pointing at the clmload command name to start */
+	if ((arg1 = *++argv) == NULL) {
+		fprintf(stderr, "too few arguments (none)\n");
+		return BCME_USAGE_ERROR;
+	} else if ((arg2 = *++argv) == NULL) {
+		/* one argument - use it, arg1, as the file name */
+		fname = arg1;
+	} else if ((*++argv) == NULL) {
+		/* two arguments - use the last, arg2, as the filename
+		 * while ignoring the first argument.  We no longer
+		 * support downloading anything but a base CLM,
+		 */
+		fname = arg2;
+	} else {
+		fprintf(stderr, "too mang arguments (3 or more)\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	ret = process_clm_data(wl, fname, 0);
+
+	return ret;
+}
+static int
+wl_txcapload(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	char *arg1;
+	char* fname;
+
+	BCM_REFERENCE(cmd);
+
+	/* argv is pointing at the clmload command name to start */
+	if ((arg1 = *++argv) == NULL) {
+		/* too few arguments (none) */
+		return -1;
+	} else if (*++argv == NULL) {
+		/* one argument - use it, arg1, as the file name */
+		fname = arg1;
+	} else {
+		/* too mang arguments (2 or more) */
+		return -1;
+	}
+
+	ret = process_txcap_data(wl, fname);
+
+	return ret;
+}
+
+static int
+wl_txcapctl(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	void *ptr = NULL;
+	wl_txpwrcap_ctl_t *txcap_ctl_ptr;
+	wl_txpwrcap_ctl_t txcap_ctl;
+	int i;
+
+	if (!(argv[1])) { /* Get */
+		if ((err = wlu_var_getbuf_med(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return err;
+		txcap_ctl_ptr =  ptr;
+		printf("%d %d %d %d %d\n",
+			txcap_ctl_ptr->ctl[0],
+			txcap_ctl_ptr->ctl[1],
+			txcap_ctl_ptr->ctl[2],
+			txcap_ctl_ptr->ctl[3],
+			txcap_ctl_ptr->ctl[4]);
+	} else { /* Set */
+		for (i = 0; i < 5; i++) {
+			if (*++argv) {
+				txcap_ctl.ctl[i] = strtol(*argv, NULL, 0);
+			} else {
+				return BCME_USAGE_ERROR;
+			}
+		}
+		if (argv[1]) {
+			return BCME_USAGE_ERROR;
+		}
+		else {
+			(void)txcap_ctl;
+			txcap_ctl.version = TXPWRCAPCTL_VERSION;
+			if ((err = wlu_var_setbuf(wl, cmd->name, &txcap_ctl, sizeof(txcap_ctl)))
+				< 0)
+				return BCME_ERROR;
+		}
+	}
+	return err;
+}
+
+static int
+wl_txcapdump(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	void *ptr = NULL;
+	uint8 txcap_dump_version;
+	int i;
+
+	if (!(argv[1])) { /* Get */
+		if ((err = wlu_var_getbuf_med(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			 return err;
+		txcap_dump_version = *((uint8 *)ptr);
+		if (txcap_dump_version == 2) {
+			wl_txpwrcap_dump_t *txcap_dump_ptr =  ptr;
+			printf("current country %c%c, channel(control) %d\n",
+				txcap_dump_ptr->current_country[0],
+				txcap_dump_ptr->current_country[1],
+				txcap_dump_ptr->current_channel);
+			printf("low/high cap config: ");
+			for (i = 0; i < TXPWRCAP_NUM_SUBBANDS; i++) {
+				printf(" %d", txcap_dump_ptr->config[i]);
+			}
+			printf("\n");
+			printf("low/high cap state:  ");
+			for (i = 0; i < TXPWRCAP_NUM_SUBBANDS; i++) {
+				printf(" %d", txcap_dump_ptr->state[i]);
+			}
+			printf("\n");
+			printf("high cap state enabled %d\n",
+				txcap_dump_ptr->high_cap_state_enabled);
+			printf("wci2 cell status last %d\n",
+				txcap_dump_ptr->wci2_cell_status_last);
+			if (!txcap_dump_ptr->download_present) {
+				printf("txcap download not present\n");
+			} else {
+				printf("subbands %d, antennas %d, antennas per core",
+					txcap_dump_ptr->num_subbands, txcap_dump_ptr->num_antennas);
+				for (i = 0; i < TXPWRCAP_MAX_NUM_CORES; i++) {
+					printf(" %d", txcap_dump_ptr->num_antennas_per_core[i]);
+				}
+				printf(", cc groups %d\n", txcap_dump_ptr->num_cc_groups);
+				printf("current cc group info index %d\n",
+					txcap_dump_ptr->current_country_cc_group_info_index);
+				printf(" tx caps (decimal qdbm, per subband, per antenna,"
+				       " e.g. sb0_a0, sb0_a1, sb1_a0, sb1_a1, ...)\n");
+				printf("  low cap:  ");
+				for (i = 0;
+					i < txcap_dump_ptr->num_subbands *
+						txcap_dump_ptr->num_antennas;
+					i++) {
+					printf("%4d ", txcap_dump_ptr->low_cap[i]);
+				}
+				printf("\n");
+				printf("  high cap: ");
+				for (i = 0;
+					i < txcap_dump_ptr->num_subbands *
+						txcap_dump_ptr->num_antennas;
+					i++) {
+					printf("%4d ", txcap_dump_ptr->high_cap[i]);
+				}
+				printf("\n");
+			}
+		} else if (txcap_dump_version == 3) {
+			wl_txpwrcap_dump_v3_t *txcap_dump_ptr =  ptr;
+			printf("current country %c%c, channel(control) %d\n",
+				txcap_dump_ptr->current_country[0],
+				txcap_dump_ptr->current_country[1],
+				txcap_dump_ptr->current_channel);
+			printf("low/high cap config: ");
+			for (i = 0; i < TXPWRCAP_NUM_SUBBANDS; i++) {
+				printf(" %d", txcap_dump_ptr->config[i]);
+			}
+			printf("\n");
+			printf("low/high cap state:  ");
+			for (i = 0; i < TXPWRCAP_NUM_SUBBANDS; i++) {
+				printf(" %d", txcap_dump_ptr->state[i]);
+			}
+			printf("\n");
+			printf("high cap state enabled %d\n",
+				txcap_dump_ptr->high_cap_state_enabled);
+			printf("wci2 cell status last %d\n",
+				txcap_dump_ptr->wci2_cell_status_last);
+			if (!txcap_dump_ptr->download_present) {
+				printf("txcap download not present\n");
+			} else {
+				printf("subbands %d, antennas %d, antennas per core",
+					txcap_dump_ptr->num_subbands, txcap_dump_ptr->num_antennas);
+				for (i = 0; i < TXPWRCAP_MAX_NUM_CORES; i++) {
+					printf(" %d", txcap_dump_ptr->num_antennas_per_core[i]);
+				}
+				printf(", cc groups %d\n", txcap_dump_ptr->num_cc_groups);
+				printf("current cc group info index %d\n",
+					txcap_dump_ptr->current_country_cc_group_info_index);
+				printf(" tx caps (decimal qdbm, per subband, per antenna,"
+				       " e.g. sb0_a0, sb0_a1, sb1_a0, sb1_a1, ...)\n");
+				if (txcap_dump_ptr->cap_states_per_cc_group == 2) {
+					printf("  low  cap: ");
+					for (i = 0;
+						i < txcap_dump_ptr->num_subbands *
+							txcap_dump_ptr->num_antennas;
+						i++) {
+						printf("%4d ",
+							txcap_dump_ptr->host_low_wci2_low_cap[i]);
+					}
+					printf("\n");
+					printf("  high cap: ");
+					for (i = 0;
+						i < txcap_dump_ptr->num_subbands *
+							txcap_dump_ptr->num_antennas;
+						i++) {
+						printf("%4d ",
+							txcap_dump_ptr->host_low_wci2_high_cap[i]);
+					}
+					printf("\n");
+				} else {
+					printf("  host low  wci2 low  cap: ");
+					for (i = 0;
+						i < txcap_dump_ptr->num_subbands *
+							txcap_dump_ptr->num_antennas;
+						i++) {
+						printf("%4d ",
+							txcap_dump_ptr->host_low_wci2_low_cap[i]);
+					}
+					printf("\n");
+					printf("  host low  wci2 high cap: ");
+					for (i = 0;
+						i < txcap_dump_ptr->num_subbands *
+							txcap_dump_ptr->num_antennas;
+						i++) {
+						printf("%4d ",
+							txcap_dump_ptr->host_low_wci2_high_cap[i]);
+					}
+					printf("\n");
+					printf("  host high wci2 low  cap: ");
+					for (i = 0;
+						i < txcap_dump_ptr->num_subbands *
+							txcap_dump_ptr->num_antennas;
+						i++) {
+						printf("%4d ",
+							txcap_dump_ptr->host_high_wci2_low_cap[i]);
+					}
+					printf("\n");
+					printf("  host high wci2 high cap: ");
+					for (i = 0;
+						i < txcap_dump_ptr->num_subbands *
+							txcap_dump_ptr->num_antennas;
+						i++) {
+						printf("%4d ",
+							txcap_dump_ptr->host_high_wci2_high_cap[i]);
+					}
+					printf("\n");
+				}
+			}
+		} else {
+			err = BCME_USAGE_ERROR;
+		}
+	} else { /* Set */
+		err = BCME_USAGE_ERROR;
+	}
+	return err;
+}
+
+#endif /* CLMDOWNLOAD */
+
+#define CAL_INPUT_FILE_MIN_LEN 32
+
+int
+process_cal_data(void *wl, char *calfn)
+{
+	int ret = 0;
+	FILE *fp = NULL;
+	unsigned int cal_filelen;
+	unsigned long status = 0;
+	unsigned char *new_buf = NULL;
+	int filelen = 0;
+
+	/* Open the CAL download file */
+	if (!(fp = fopen(calfn, "rb"))) {
+		fprintf(stderr, "unable to open input file %s\n", calfn);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* fstat is a linux/unix, not a stdio function. This is replaced everywhere with function
+	 * fsize() which calls fseek(fp, 0L, SEEK_END), ftell(fp), fseek(fp, 0L, SEEK_SET) sequence
+	 * to determine the file size.
+	 */
+
+	if ((filelen = fsize(fp)) < 0) {
+		fprintf(stderr, "fseek or ftell on input file %s return error %s\n",
+			calfn, strerror(errno));
+		ret = -EINVAL;
+		goto error;
+	}
+	cal_filelen = (uint)filelen;
+
+	if (cal_filelen == 0) {
+		fprintf(stderr, "input file %s is empty (i.e. zero length)\n", calfn);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	if ((new_buf = malloc(cal_filelen)) == NULL) {
+		fprintf(stderr, "unable to allocate %u bytes based on input file size!\n",
+			cal_filelen);
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	status = fread(new_buf, 1, cal_filelen, fp);
+
+	if (status != cal_filelen) {
+		fprintf(stderr, "read of input file %s wasn't good based on fstat size %u\n",
+			calfn, cal_filelen);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* Basic sanity check on size. Make sure there is enough for any magic string plus
+	 * a little more for good measure.
+	 */
+	if (status < CAL_INPUT_FILE_MIN_LEN) {
+		fprintf(stderr, "size of input file %s is less than %d bytes."
+			"  This can't be a cal file!\n", calfn, CAL_INPUT_FILE_MIN_LEN);
+		ret = -EINVAL;
+		goto error;
+	} else if (status != cal_filelen) {
+		fprintf(stderr, "read of input file %s wasn't good based on fstat size %u\n",
+			calfn, cal_filelen);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* Calibration package? */
+	if (memcmp(new_buf, blob_magic_string, sizeof(blob_magic_string)) == 0) {
+		/* MSF packaged file? They start with magic string 'BLOB' */
+		printf("Downloading calibration package format file %s\n", calfn);
+		ret = dload_blob(wl, "calload", new_buf, cal_filelen);
+	} else {
+		fprintf(stderr, "input file is missing calibration package magic string\n");
+		ret = -1;
+		goto error;
+	}
+
+error:
+	if (new_buf)
+		free(new_buf);
+	if (fp)
+		fclose(fp);
+
+	return ret;
+}
+
+static int
+wl_calload(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	char* fname;
+
+	BCM_REFERENCE(cmd);
+
+	/* argv is pointing at the calload command name to start */
+	if ((fname = *++argv) == NULL) {
+		/* too few arguments (none) */
+		return -EINVAL;
+	}
+
+	ret = process_cal_data(wl, fname);
+
+	return ret;
+}
+
+int
+process_cal_dump(void *wl, char *fname_txcal, char *fname_rxcal)
+{
+	int ret = 0;
+	unsigned long status = 0;
+	FILE *fblobp = NULL;
+	void *ptr = NULL;
+	uint32 dump_sz_total;
+	uint16 dump_sz_txcal, dump_sz_rxcal;
+
+	/* Read back TX calibration information */
+	if ((ret = wlu_var_getbuf_med(wl, "caldump", NULL, 0, &ptr)) < 0)
+		goto error;
+
+	dump_sz_total = dtoh32(*(int *)ptr);
+	printf("caldump: total dump size %d bytes\n", dump_sz_total);
+	if (dump_sz_total > (WLC_IOCTL_MEDLEN - 4)) {
+		fprintf(stderr, "caldump: total dump size too large\n");
+		ret = -EINVAL;
+		goto error;
+	}
+	ptr = (void *)((uint8 *)ptr + sizeof(dump_sz_total));
+
+	/* The TxCal data starts first. Its size is indicated in first two bytes
+	 * (excluding size field itself - an uint16 field)
+	 */
+	dump_sz_txcal = dtoh16(*(uint16 *)ptr) + sizeof(dump_sz_txcal);
+	printf("\tTxCal dump size %d bytes\n", dump_sz_txcal);
+	if (dump_sz_total < (uint32)dump_sz_txcal) {
+		fprintf(stderr, "caldump: total dump size too small for TxCal\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* Open the txcal bin file */
+	if (!(fblobp = fopen(fname_txcal, "wb"))) {
+		fprintf(stderr, "unable to open TxCal output file %s\n", fname_txcal);
+		perror(fname_txcal);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	status = (unsigned long)fwrite((uint8 *)ptr, 1, dump_sz_txcal, fblobp);
+	if (status != dump_sz_txcal) {
+		fprintf(stderr, "unable to complete TxCal output (write %lu out of %u bytes)\n",
+			status, dump_sz_txcal);
+		ret = -EINVAL;
+		goto error;
+	}
+	ptr = (void *)((uint8 *)ptr + dump_sz_txcal);
+	fclose(fblobp);
+	fblobp = NULL;
+
+	/* The RxCal data starts after TxCal. Its size is indicated in first two bytes
+	 * (but here, its size is derived from dump_sz_total and dump_sz_txcal))
+	 */
+
+	/* For backward comatible where only TxCal file is given, we just dump TxCal
+	 * and return. If the RXCal file name is "NULL", we just return without any error
+	 */
+	if (fname_rxcal == NULL) {
+		fprintf(stderr, "can't find RxCal output file\n");
+		return ret;
+	}
+	dump_sz_rxcal = (uint16)(dump_sz_total - (uint32)dump_sz_txcal);
+	printf("\tRxCal dump size %d bytes\n", dump_sz_rxcal);
+	if (dump_sz_rxcal == 0) {
+		fprintf(stderr, "no RxCal data available\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* Open the rxcal bin file */
+	if (!(fblobp = fopen(fname_rxcal, "wb"))) {
+		fprintf(stderr, "unable to open RxCal output file %s\n", fname_rxcal);
+		perror(fname_rxcal);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	status = (unsigned long)fwrite((uint8 *)ptr, 1, dump_sz_rxcal, fblobp);
+	if (status != dump_sz_rxcal) {
+		fprintf(stderr, "unable to complete RxCal output (write %lu out of %u bytes)\n",
+			status, dump_sz_rxcal);
+		ret = -EINVAL;
+		goto error;
+	}
+
+error:
+	if (fblobp)
+		fclose(fblobp);
+	return ret;
+}
+
+static int
+wl_caldump(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	char *fname_txcal, *fname_rxcal;
+
+	BCM_REFERENCE(cmd);
+
+	/* argv is pointing at the command name to start */
+	if ((fname_txcal = *++argv) == NULL) {
+		/* too few arguments (none) */
+		return -EINVAL;
+	}
+	printf("caldump: dump TxCal to file %s\n", fname_txcal);
+
+	if ((fname_rxcal = *++argv) != NULL)
+		printf("caldump: dump RxCal to file %s\n", fname_rxcal);
+
+	ret = process_cal_dump(wl, fname_txcal, fname_rxcal);
+
+	return ret;
+}
+
+int
+wl_bsscfg_int(void *wl, cmd_t *cmd, char **argv)
+{
+	char *endptr = NULL;
+	char *val_name;
+	int bsscfg_idx = 0;
+	int val = 0;
+	int consumed;
+	int ret;
+
+	val_name = *argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv, val_name, &bsscfg_idx, &consumed)) != 0)
+		return ret;
+
+	/* handle a bsscfg int with a legacy ioctl */
+	if (consumed == 0 && cmd->set != WLC_SET_VAR) {
+		/* back up to the orig command and run as an ioctl int */
+		argv--;
+		return wl_int(wl, cmd, argv);
+	}
+
+	argv += consumed;
+
+	if (!*argv) {
+		/* This is a GET */
+		if (cmd->get == -1)
+			return -1;
+
+		if (consumed == 0)
+			ret = wlu_iovar_getint(wl, val_name, &val);
+		else
+			ret = wl_bssiovar_getint(wl, val_name, bsscfg_idx, &val);
+
+		if (ret < 0)
+			return ret;
+
+		wl_printint(val);
+	} else {
+		/* This is a SET */
+		if (cmd->set == -1)
+			return -1;
+
+		if (!stricmp(*argv, "on"))
+			val = 1;
+		else if (!stricmp(*argv, "off"))
+			val = 0;
+		else {
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		if (consumed == 0)
+			ret = wlu_iovar_setint(wl, val_name, val);
+		else
+			ret = wl_bssiovar_setint(wl, val_name, bsscfg_idx, val);
+	}
+
+	return ret;
+}
+
+/* Get/Set the gmode config */
+static int
+wl_gmode(void *wl, cmd_t *cmd, char **argv)
+{
+	char *endptr = NULL;
+	int ret = 0, val;
+
+	if (!*++argv) {
+		const char *gconfig;
+
+		/* Get the current G mode */
+		if ((ret = wlu_get(wl, cmd->get, &val, sizeof(val))) < 0)
+			return ret;
+
+		val = dtoh32(val);
+		switch (val) {
+		case GMODE_LEGACY_B:
+			gconfig = "54g Legacy B";
+			break;
+		case GMODE_AUTO:
+			gconfig = "54g Auto";
+			break;
+		case GMODE_ONLY:
+			gconfig = "54g Only";
+			break;
+		case GMODE_PERFORMANCE:
+			gconfig = "54g Performance";
+			break;
+		case GMODE_LRS:
+			gconfig = "54g LRS";
+			break;
+		default:
+			gconfig = "unknown";
+			break;
+		}
+
+		printf("%s (%d)\n", gconfig, val);
+
+	} else {
+		/* Set the new G mode */
+
+		if (!strnicmp(*argv, "legacy", 6))
+			val = GMODE_LEGACY_B;
+		else if (!strnicmp(*argv, "auto", 4))
+			val = GMODE_AUTO;
+		else if (!strnicmp(*argv, "gonly", 5))
+			val = GMODE_ONLY;
+		else if (!strnicmp(*argv, "perf", 4))
+			val = GMODE_PERFORMANCE;
+		else if (!strnicmp(*argv, "lrs", 3))
+			val = GMODE_LRS;
+		else {
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		/* Set the gmode configration */
+		val = htod32(val);
+		if ((ret = wlu_set(wl, cmd->set, &val, sizeof(val))))
+			goto done;
+
+	}
+
+done:
+	return (ret);
+}
+
+static int
+wl_overlay(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int argc;
+	char *endptr = NULL;
+	void *ptr = NULL;
+	int param[3];
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argc < 1 || argc > 3) {
+		printf("required args: virt_addr phy_addr size\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	param[0] = strtol(argv[1], &endptr, 0);
+	if (*endptr != '\0' || (param[0] & ~0x003FFE00) != 0) {
+		printf("Invaild virtual address: %s\n", argv[1]);
+		return BCME_BADARG;
+	}
+
+	if (argc == 1) {
+		if ((ret = wlu_var_getbuf(wl, cmd->name, param, sizeof(int), &ptr)) >= 0) {
+			wl_hexdump((uchar *)ptr, 512);
+		}
+		return (ret);
+	}
+
+	param[1] = strtol(argv[2], &endptr, 0);
+	if (*endptr != '\0' || (param[1] & ~0x003FFE00) != 0) {
+		printf("Invaild physical Address: %s\n", argv[2]);
+		return BCME_BADARG;
+	}
+
+	if (argc == 3) {
+		param[2] = strtol(argv[3], &endptr, 0);
+		if (*endptr != '\0' || param[2] < 0 || param[2] > 7) {
+			printf("Invaild size: %s\n", argv[3]);
+			return BCME_BADARG;
+		}
+	} else {
+		param[2] = 0;
+	}
+
+	printf("Setting virtual Address 0x%x to physical Address 0x%x, size is %d\n",
+		param[0], param[1], param[2]);
+	ret = wlu_var_setbuf(wl, cmd->name, param, sizeof(param));
+
+	return (ret);
+}
+
+int
+wl_reg(void *wl, cmd_t *cmd, char **argv)
+{
+	int reg;
+	int ret;
+	struct {
+		int val;
+		int band;
+	} x;
+	char *endptr = NULL;
+	uint argc;
+	bool core_cmd;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* required arg: reg offset */
+	if (argc < 1)
+		return BCME_USAGE_ERROR;
+
+	reg = strtol(argv[0], &endptr, 0);
+
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	x.val = 0;
+	x.band = WLC_BAND_AUTO;
+	core_cmd = FALSE;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	/* Second arg: value or band or "radio core" */
+	if (argc >= 2) {
+		if (!stricmp(argv[1], "a"))
+			x.band = WLC_BAND_5G;
+		else if (!stricmp(argv[1], "b"))
+			x.band = WLC_BAND_2G;
+		else {
+			/* For NPHY Rev >= 3, the 2nd argument can be
+			   the radio core
+			 */
+			if (strcmp(cmd->name, "radioreg") == 0) {
+				if (strcmp(argv[1], "syn") == 0) {
+					reg |= RADIO_CORE_SYN;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[1], "tx0") == 0) {
+					reg |= RADIO_CORE_TX0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[1], "tx1") == 0) {
+					reg |= RADIO_CORE_TX1;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[1], "rx0") == 0) {
+					reg |= RADIO_CORE_RX0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[1], "rx1") == 0) {
+					reg |= RADIO_CORE_RX1;
+					core_cmd = TRUE;
+				}
+			}
+			/* For HTPHY/ACPHY, the 2nd argument can be
+			   the radio core
+			 */
+			if (strcmp(cmd->name, "radioreg") == 0) {
+				if (phytype == WLC_PHY_TYPE_AC) {
+					if (strcmp(argv[1], "cr0") == 0) {
+						reg |= RADIO_2069_CORE_CR0;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "cr1") == 0) {
+						reg |= RADIO_2069_CORE_CR1;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "cr2") == 0) {
+						reg |= RADIO_2069_CORE_CR2;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "pll") == 0) {
+						reg |= RADIO_2069_CORE_PLL;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "pll0") == 0) {
+						reg |= RADIO_2069_CORE_PLL0;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "pll1") == 0) {
+						reg |= RADIO_2069_CORE_PLL1;
+						core_cmd = TRUE;
+					}
+				} else {
+					if (strcmp(argv[1], "cr0") == 0) {
+						reg |= RADIO_CORE_CR0;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "cr1") == 0) {
+						reg |= RADIO_CORE_CR1;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[1], "cr2") == 0) {
+						reg |= RADIO_CORE_CR2;
+						core_cmd = TRUE;
+					}
+				}
+			}
+			/* If the second argument is a value */
+			if (!core_cmd) {
+				x.val = strtol(argv[1], &endptr, 0);
+				if (*endptr != '\0')
+					return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	/* Third arg: band OR "radio core" */
+	if (argc >= 3) {
+		if (!stricmp(argv[2], "a"))
+			x.band = WLC_BAND_5G;
+		else if (!stricmp(argv[2], "b"))
+			x.band = WLC_BAND_2G;
+		else {
+			/* For NPHY Rev >= 3, the 3rd argument can be
+			   the radio core
+			 */
+			core_cmd = FALSE;
+			if (strcmp(cmd->name, "radioreg") == 0) {
+				if (strcmp(argv[2], "syn") == 0) {
+					reg |= RADIO_CORE_SYN;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "tx0") == 0) {
+					reg |= RADIO_CORE_TX0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "tx1") == 0) {
+					reg |= RADIO_CORE_TX1;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "rx0") == 0) {
+					reg |= RADIO_CORE_RX0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "rx1") == 0) {
+					reg |= RADIO_CORE_RX1;
+					core_cmd = TRUE;
+				}
+			}
+			/* For HTPHY/ACPHY, the 3rd argument can be
+			   the radio core
+			*/
+			if (phytype == WLC_PHY_TYPE_AC) {
+				if (strcmp(argv[2], "cr0") == 0) {
+					reg |= RADIO_2069_CORE_CR0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "cr1") == 0) {
+					reg |= RADIO_2069_CORE_CR1;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "cr2") == 0) {
+					reg |= RADIO_2069_CORE_CR2;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "pll") == 0) {
+					reg |= RADIO_2069_CORE_PLL;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "pll0") == 0) {
+					reg |= RADIO_2069_CORE_PLL0;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "pll1") == 0) {
+					reg |= RADIO_2069_CORE_PLL1;
+					core_cmd = TRUE;
+				} else if (strcmp(argv[2], "all") == 0) {
+					reg |= RADIO_2069_CORE_ALL;
+					core_cmd = TRUE;
+				}
+			} else {
+				if (strcmp(cmd->name, "radioreg") == 0) {
+					if (strcmp(argv[2], "cr0") == 0) {
+						reg |= RADIO_CORE_CR0;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[2], "cr1") == 0) {
+						reg |= RADIO_CORE_CR1;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[2], "cr2") == 0) {
+						reg |= RADIO_CORE_CR2;
+						core_cmd = TRUE;
+					} else if (strcmp(argv[2], "all") == 0) {
+						reg |= RADIO_CORE_ALL;
+						core_cmd = TRUE;
+					}
+				}
+			}
+
+			if (!core_cmd) {
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	x.val = (x.val << 16) | (reg & 0xffff);
+
+	/* issue the get or set ioctl */
+	if ((argc == 1) || ((argc == 2) && ((x.band != WLC_BAND_AUTO) || core_cmd))) {
+		x.band = htod32(x.band);
+		x.val = htod32(x.val);
+		if ((ret = wlu_get(wl, cmd->get, &x, sizeof(x))) < 0)
+			return (ret);
+		printf("0x%04x\n", (uint16)(dtoh32(x.val)));
+	} else {
+		x.band = htod32(x.band);
+		x.val = htod32(x.val);
+		ret = wlu_set(wl, cmd->set, &x, sizeof(x));
+	}
+
+	return (ret);
+}
+
+static int
+wl_macreg(void *wl, cmd_t *cmd, char **argv)
+{
+	int reg;
+	int size;
+	uint32 val;
+	int ret;
+	char *endptr = NULL;
+	rw_reg_t rwt;
+	uint argc;
+
+	val = 0;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* required arg: reg offset */
+	if (argc < 1)
+		return BCME_USAGE_ERROR;
+
+	reg = strtol(argv[0], &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	/* required arg: reg size */
+	if (argc < 2)
+		return BCME_USAGE_ERROR;
+
+	size = strtol(argv[1], &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	rwt.band = WLC_BAND_AUTO;
+
+	/* Third arg: new value or band */
+	if (argc >= 3) {
+		if (!stricmp(argv[2], "a"))
+			rwt.band = WLC_BAND_5G;
+		else if (!stricmp(argv[2], "b"))
+			rwt.band = WLC_BAND_2G;
+		else {
+			val = strtoul(argv[2], &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+
+	}
+
+	/* Fourth arg: band */
+	if (argc >= 4) {
+		if (!stricmp(argv[3], "a"))
+			rwt.band = WLC_BAND_5G;
+		else if (!stricmp(argv[3], "b"))
+			rwt.band = WLC_BAND_2G;
+		else
+			return BCME_USAGE_ERROR;
+	}
+
+	if ((argc == 2) || ((argc == 3) && (rwt.band != WLC_BAND_AUTO))) {
+		rwt.band = htod32(rwt.band);
+		rwt.byteoff = htod32(reg);
+		rwt.size = htod32(size);
+		if ((ret = wlu_get(wl, cmd->get, &rwt, sizeof(rw_reg_t))) < 0)
+			return (ret);
+		printf("0x%04x\n", dtoh32(rwt.val));
+	}
+	else {
+		rwt.band = htod32(rwt.band);
+		rwt.byteoff = htod32(reg);
+		rwt.size = htod32(size);
+		rwt.val = htod32(val);
+		ret = wlu_set(wl, cmd->set, &rwt, sizeof(rw_reg_t));
+	}
+
+	return (ret);
+}
+
+static int
+wl_macregx(void *wl, cmd_t *cmd, char **argv)
+{
+	int reg;
+	int size = 2;
+	int err;
+	char *p;
+	rw_reg_t rwt;
+
+	/* eat command name */
+	argv++;
+
+	/* required arg: reg offset */
+	if ((p = *argv) == NULL) {
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	reg = strtol(p, NULL, 0);
+	argv++;
+
+	if (strcmp(cmd->name, "macregx") == 0) {
+		/* required arg: size of the register */
+		if ((p = *argv) == NULL) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		size = strtol(p, NULL, 0);
+		argv++;
+	}
+
+	rwt.byteoff = htod32(reg);
+	rwt.size = htod32(size);
+	rwt.band = WLC_BAND_AUTO;
+
+	if ((p = *argv) == NULL) {
+		uint32 val;
+		/* GET cmd */
+		if ((err = wlu_iovar_getbuf(wl, cmd->name, &rwt,
+			sizeof(rwt), buf, WLC_IOCTL_SMLEN) < 0)) {
+			goto exit;
+		}
+		val = *((uint32 *)buf);
+
+		if (size == 4) {
+			printf("0x%08x\n", dtoh32(val));
+		} else {
+			printf("0x%04x\n", (uint16)dtoh32(val));
+		}
+	} else {
+		/* SET cmd */
+		/* required arg: set value */
+		if ((p = *argv) == NULL) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		rwt.val = htod32(strtol(p, NULL, 0));
+		argv++;
+
+		if ((err = wlu_iovar_set(wl, cmd->name, &rwt, sizeof(rwt))) < 0) {
+			printf("Error setting variable %s\n", cmd->name);
+			return err;
+		}
+	}
+exit:
+	return (err);
+}
+
+/*
+ * get or get a band specific variable
+ * the band can be a/b/all or omitted. "all"(set only)
+ * means all supported bands. blank means current band
+ */
+static int
+wl_band_elm(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct {
+		int val;
+		int band;
+	} x;
+	char *endptr = NULL;
+	uint argc;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	x.val = 0;
+	x.band = WLC_BAND_AUTO;
+
+	/* First arg: value or band */
+	if (argc >= 1) {
+		if (!stricmp(argv[0], "a"))
+			x.band = WLC_BAND_5G;
+		else if (!stricmp(argv[0], "b"))
+			x.band = WLC_BAND_2G;
+		else if (!stricmp(argv[0], "all"))
+			x.band = WLC_BAND_ALL;
+		else {
+			x.val = strtol(argv[0], &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+	}
+
+	/* Second arg: band */
+	if (argc >= 2) {
+		if (!stricmp(argv[1], "a"))
+			x.band = WLC_BAND_5G;
+		else if (!stricmp(argv[1], "b"))
+			x.band = WLC_BAND_2G;
+		else if (!stricmp(argv[1], "all"))
+			x.band = WLC_BAND_ALL;
+		else
+			return BCME_USAGE_ERROR;
+	}
+
+	/* issue the get or set ioctl */
+	if ((argc == 0) || ((argc == 1) && (x.band != WLC_BAND_AUTO))) {
+		if (x.band == WLC_BAND_ALL) {
+			printf("band option \"all\" is for set only, not get\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		x.band = htod32(x.band);
+		if ((ret = wlu_get(wl, cmd->get, &x, sizeof(x))) < 0)
+			return (ret);
+
+		printf("%s is 0x%04x(%d)\n", cmd->name, (uint16)(dtoh32(x.val)), dtoh32(x.val));
+	} else {
+		x.band = htod32(x.band);
+		x.val = htod32(x.val);
+		ret = wlu_set(wl, cmd->set, &x, sizeof(x));
+	}
+
+	return (ret);
+}
+
+/* Command may or may not take a MAC address */
+static int
+wl_rssi(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	scb_val_t scb_val;
+	int32 rssi;
+
+	if (!*++argv) {
+		if ((ret = wlu_get(wl, cmd->get, &rssi, sizeof(rssi))) < 0)
+			return ret;
+		printf("%d\n", dtoh32(rssi));
+		return 0;
+	} else {
+		if (!wl_ether_atoe(*argv, &scb_val.ea))
+			return BCME_USAGE_ERROR;
+		if ((ret = wlu_get(wl, cmd->get, &scb_val, sizeof(scb_val))) < 0)
+			return ret;
+		printf("%d\n", dtoh32(scb_val.val));
+		return 0;
+	}
+}
+
+/* Commands that take a MAC address */
+int
+wl_macaddr(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct ether_addr ea;
+
+	if (!*++argv) {
+		if ((ret = wlu_get(wl, cmd->get, &ea, ETHER_ADDR_LEN)) < 0)
+			return ret;
+		printf("%s\n", wl_ether_etoa(&ea));
+		return 0;
+	} else {
+		if (!wl_ether_atoe(*argv, &ea))
+			return BCME_USAGE_ERROR;
+		return wlu_set(wl, cmd->set, &ea, ETHER_ADDR_LEN);
+	}
+}
+
+/* IO variables that take a MAC address */
+int
+wl_iov_mac(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct ether_addr ea = {{0, 0, 0, 0, 0, 0}};
+
+	if (argv[1]) { /* set */
+		if (!wl_ether_atoe(argv[1], &ea)) {
+			printf(" ERROR: no valid ether addr provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		if ((ret = wlu_iovar_set(wl, cmd->name, &ea, ETHER_ADDR_LEN)) < 0) {
+			printf("Error setting variable %s\n", argv[0]);
+			return ret;
+		}
+		return 0;
+	} else { /* get */
+		if ((ret = wlu_iovar_get(wl, cmd->name, &ea, ETHER_ADDR_LEN)) < 0) {
+			printf("Error getting variable %s\n", argv[0]);
+			return ret;
+		}
+		printf("%s %s\n", argv[0], wl_ether_etoa(&ea));
+	}
+
+	return 0;
+}
+
+static void
+wl_txq_prec_dump(wl_iov_pktq_log_t* iov_pktq_log, bool hide_unknown, bool is_aqm)
+{
+#define PREC_DUMPV(v4, v5)  ((iov_pktq_log->version == 4) ? (v4) : (v5))
+
+#define v4hstubL            "prec:   rqstd,  stored,selfsave,   saved,fulldrop, dropped," \
+	                    "sacrficd, retried, rtsfail,rtrydrop, psretry,supprssd,   " \
+	                    "acked,utlisatn,q length,Data Mbits/s,Phy Mbits/s,Rate Mbits/s"
+
+#define v4hstubS            "prec:   rqstd,  stored, dropped, retried, rtsfail,rtrydrop, " \
+	                    "psretry,   acked,utlisatn,q length,Data Mbits/s,Phy Mbits/s"
+
+#define v4fstubL            "  %02u: %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, " \
+	                    "%7u, %7u, %7u, %7u, %8.2f,   %8.2f,    %8.2f"
+
+#define v4fstubS            "  %02u: %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, %7u, " \
+	                    "%8.2f,   %8.2f"
+
+#define v4fstubL_aqm        "  %02u: %7u, %7u, %7u, %7u, %7u, %7u, %7u,       -,       -, " \
+	                    "%7u, %7u, %7u, %7u, %7u, %7u, %8.2f,          -,           -"
+
+#define v4fstubS_aqm        "  %02u: %7u, %7u, %7u,       -,       -, %7u, %7u, %7u, %7u, " \
+	                    "%7u, %8.2f,          -"
+
+	const char* v4headingsL = v4hstubL" (+v%d.)\n";
+	const char* v4headingsS = v4hstubS" (+v%d.)\n";
+	const char* v5headingsL = v4hstubL", %%air, %%effcy  (v%d)\n";
+	const char* v5headingsS = v4hstubS", %%air, %%effcy  (v%d)\n";
+
+	const char* v4formL =     v4fstubL"\n";
+	const char* v4formS =     v4fstubS"\n";
+	const char* v4formL_aqm = v4fstubL_aqm"\n";
+	const char* v4formS_aqm = v4fstubS_aqm"\n";
+
+	const char* v5formL =     v4fstubL",  %6.1f,  %5.1f\n";
+	const char* v5formS =     v4fstubS",  %6.1f,  %5.1f\n";
+	const char* v5formL_aqm = v4fstubL_aqm",       -,      -\n";
+	const char* v5formS_aqm = v4fstubS_aqm",       -,      -\n";
+
+	char*  headings;
+	uint8  index;
+	uint8  prec;
+	uint32 prec_mask = 0;
+	char   marker[4] = "[X]";
+	pktq_log_format_v05_t* logv05 = NULL;
+	pktq_log_format_v04_t* logv04 = NULL;
+
+	if (iov_pktq_log->version == 0x04) {
+		logv04 = &iov_pktq_log->pktq_log.v04;
+	}
+	else if (iov_pktq_log->version == 0x05) {
+		logv05 = &iov_pktq_log->pktq_log.v05;
+	}
+	else {
+		fprintf(stderr, "Unknown/unsupported binary format (%x)\n",
+		        iov_pktq_log->version);
+		return;
+	}
+
+	headings = PREC_DUMPV(&logv04->headings[0], &logv05->headings[0]);
+
+	for (index = 0; index < (uint8)iov_pktq_log->params.num_addrs; index++) {
+
+		char* heading_start;
+		char* heading_end;
+		uint32 num_prec = 0;
+
+		prec_mask = PREC_DUMPV(logv04->counter_info[index],
+		                       logv05->counter_info[index]);
+		num_prec = PREC_DUMPV(logv04->num_prec[index],
+		                      logv05->num_prec[index]);
+
+		/* test for 'unknown' data; unknown means either that
+		 * the queue is invalid or else that the logging
+		 * is not active at all.
+		 */
+		if (((prec_mask & 0xFFFF) == 0) && hide_unknown) {
+			continue;
+		}
+
+		if ((num_prec == 0) && hide_unknown) {
+			continue;
+		}
+
+		/* search for string marker - the marker is of the form
+		   "[<index>]" where index is a single ascii numeral
+		*/
+		marker[1] = '0' + index;
+		heading_start = strstr(headings, marker);
+
+		/* The driver may pass back an optional character
+		 * string for additional info
+		 */
+		if (heading_start != NULL) {
+
+			heading_start += strlen(marker);
+			heading_end = strstr(heading_start, marker);
+
+			if (heading_end == NULL) {
+				heading_end = heading_start + strlen(heading_start);
+			}
+			while (heading_start < heading_end) {
+				fputc(*heading_start++, stdout);
+			}
+		}
+
+		/* Note that this is zero if the data is invalid */
+		if (!num_prec) {
+			fprintf(stdout, "Parameter %c:%s not valid\n",
+			        iov_pktq_log->params.addr_type[index] != 0 ?
+			        iov_pktq_log->params.addr_type[index] & 0x7F : ' ',
+			        wl_ether_etoa(&iov_pktq_log->params.ea[index]));
+			continue;
+		}
+
+		/* check for short form or long form (top bit set) */
+		fprintf(stdout,
+		        iov_pktq_log->params.addr_type[index] & 0x80 ?
+		        PREC_DUMPV(v4headingsL, v5headingsL) :
+		        PREC_DUMPV(v4headingsS, v5headingsS),
+		        iov_pktq_log->version);
+
+		for (prec = 0; prec < num_prec; prec++) {
+			float tput = 0.0;
+			float txrate_succ = 0.0;
+			float txrate_main = 0.0;
+			pktq_log_counters_v05_t counters;
+			uint32 try_count = 0;
+			float airuse = 0.0;
+			float efficiency = 0.0;
+
+			if (!(prec_mask & (1 << prec))) {
+				continue;
+			}
+
+			if (iov_pktq_log->version == 5) {
+				counters = logv05->counters[index][prec];
+			}
+			else {
+				/* the following is a trick - it is possible because
+				 * V4 and V5 are both common except that V5 has extra fields
+				 * at the end
+				*/
+				memcpy(&counters, &logv04->counters[index][prec],
+				       sizeof(pktq_log_counters_v04_t));
+				counters.airtime = 0;
+			}
+
+			txrate_succ = (float)((float)counters.txrate_succ * 0.5);
+
+			if (counters.time_delta != 0) {
+				/* convert bytes to bits */
+				tput = (float)counters.throughput;
+				tput *= 8.0;
+
+				if (counters.airtime) {
+					efficiency = (float)(100.0 * tput /
+							(float)counters.airtime);
+				}
+
+				/* converts to rate of bits per us,
+				   because time_delta is in micro-seconds
+				*/
+				tput /= (float)counters.time_delta;
+
+				/* Calculate % airtime */
+				airuse = (float)((float)counters.airtime * 100.0 /
+						(float)counters.time_delta);
+			}
+
+			if (!(is_aqm && (prec & 1))) {
+				uint32 acked = counters.acked;
+
+				try_count = counters.acked + counters.retry;
+
+				if (is_aqm && (prec_mask & (1 << (prec + 1)))) {
+					pktq_log_counters_v05_t hi;
+
+					if (iov_pktq_log->version == 5) {
+						hi = logv05->counters[index][prec + 1];
+					}
+					else {
+						/* the following is a trick - it is possible
+						 * fields V4 and V5 are both common except
+						 * that V5 has extra fields at the end
+						 */
+						memcpy(&hi, &logv04->counters[index][prec + 1],
+						       sizeof(pktq_log_counters_v04_t));
+					}
+
+					acked += hi.acked;
+					try_count += hi.acked + hi.retry;
+
+					if (counters.airtime) {
+						float t = (float)hi.throughput;
+						t /= (float)counters.airtime;
+						efficiency += (float)(100.0 * 8.0 * t);
+					}
+				}
+				if (acked) {
+					txrate_succ /= (float) acked;
+
+					if (counters.txrate_succ) {
+						efficiency /= txrate_succ;
+					}
+					else {
+						efficiency = 0;
+					}
+				}
+				else {
+					txrate_succ = 0;
+					efficiency = 0;
+				}
+			}
+
+			if (try_count) {
+				txrate_main = (float)((float)counters.txrate_main * 0.5);
+				txrate_main /= (float)try_count;
+			}
+
+			if (iov_pktq_log->params.addr_type[index] & 0x80) {
+				/* long form */
+				if (is_aqm && (prec & 1)) {
+					/* aqm format for hi-prec */
+					fprintf(stdout, PREC_DUMPV(v4formL_aqm, v5formL_aqm),
+					        prec,
+					        counters.requested,
+					        counters.stored,
+					        counters.selfsaved,
+					        counters.saved,
+					        counters.full_dropped,
+					        counters.dropped,
+					        counters.sacrificed,
+					        counters.retry_drop,
+					        counters.ps_retry,
+					        counters.suppress,
+					        counters.acked,
+					        counters.max_used,
+					        counters.queue_capacity,
+					        tput);
+				}
+				else {
+					fprintf(stdout, PREC_DUMPV(v4formL, v5formL),
+					        prec,
+					        counters.requested,
+					        counters.stored,
+					        counters.selfsaved,
+					        counters.saved,
+					        counters.full_dropped,
+					        counters.dropped,
+					        counters.sacrificed,
+					        counters.retry,
+					        counters.rtsfail,
+					        counters.retry_drop,
+					        counters.ps_retry,
+					        counters.suppress,
+					        counters.acked,
+					        counters.max_used,
+					        counters.queue_capacity,
+					        tput, txrate_succ,
+					        txrate_main,
+					        airuse, efficiency);
+				}
+			}
+			else {
+				/* short form */
+				if (is_aqm && (prec & 1)) {
+					/* aqm format for hi-prec */
+					fprintf(stdout, PREC_DUMPV(v4formS_aqm, v5formS_aqm),
+					        prec,
+					        counters.requested,
+					        counters.stored,
+					        counters.dropped,
+					        counters.retry_drop,
+					        counters.ps_retry,
+					        counters.acked,
+					        counters.max_used,
+					        counters.queue_capacity,
+					        tput);
+				}
+				else {
+					fprintf(stdout, PREC_DUMPV(v4formS, v5formS),
+					        prec,
+					        counters.requested,
+					        counters.stored,
+					        counters.dropped,
+					        counters.retry,
+					        counters.rtsfail,
+					        counters.retry_drop,
+					        counters.ps_retry,
+					        counters.acked,
+					        counters.max_used,
+					        counters.queue_capacity,
+					        tput, txrate_succ,
+					        airuse, efficiency);
+				}
+			}
+		}
+		fputs("\n", stdout);
+
+		if (iov_pktq_log->version == 5 &&
+		       (logv05->pspretend_time_delta[index] != (uint32)-1)) {
+
+			fprintf(stdout, "Total time in ps pretend state is %d milliseconds\n\n",
+			        (logv05->pspretend_time_delta[index] + 500)/1000);
+		}
+	}
+}
+
+static int
+wl_scb_bs_data(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int32 flag_bits = 0;
+	int argn;
+	enum { DISPLAY_COOKED, DISPLAY_RAW } display_mode = DISPLAY_COOKED;
+	iov_bs_data_struct_t *data = (iov_bs_data_struct_t *)buf;
+	char sep = ' ';
+	bool skip_idle = FALSE;
+	float total_throughput = 0.0;
+
+	UNUSED_PARAMETER(cmd);	/* cmd->name should match argv[0] ? */
+
+	if (!argv[0]) {
+		fprintf(stderr, "%s: argv[0] missing\n", __FUNCTION__);
+		return BCME_BADARG;
+	}
+
+	for (argn = 1; argv[argn]; ++argn) {
+		if (!strcmp(argv[argn], "-noreset")) {	/* do not reset counters after reading */
+			flag_bits |= SCB_BS_DATA_FLAG_NO_RESET;
+		} else
+		if (!strcmp(argv[argn], "-raw")) {	/* Display raw counters */
+			display_mode = DISPLAY_RAW;
+		} else
+		if (!strcmp(argv[argn], "-tab")) {	/* Tab separator */
+			sep = '\t';
+		} else
+		if (!strcmp(argv[argn], "-comma")) {	/* Comma separator */
+			sep = ',';
+		} else
+		if (!strcmp(argv[argn], "-noidle")) {	/* Skip idle stations */
+			skip_idle = TRUE;
+		} else
+		if (!strcmp(argv[argn], "-help") || !strcmp(argv[argn], "-h")) {
+			/* Display usage, do not complain about unknown option. */
+			return BCME_USAGE_ERROR;
+		} else {
+			fprintf(stderr, "%s: unknown option: %s\n", argv[0], argv[argn]);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	flag_bits = htod32(flag_bits);
+	err = wlu_iovar_getbuf(wl, argv[0], &flag_bits, sizeof(flag_bits), buf, WLC_IOCTL_MAXLEN);
+	if (err) {
+		return (err);
+	}
+
+	data->structure_version = dtoh16(data->structure_version);
+	if (data->structure_version != SCB_BS_DATA_STRUCT_VERSION) {
+		fprintf(stderr, "wlu / wl driver mismatch, expect V%d format, got %d.\n",
+			SCB_BS_DATA_STRUCT_VERSION, data->structure_version);
+		return BCME_IOCTL_ERROR;
+	}
+
+	data->structure_count = dtoh16(data->structure_count);
+	if (data->structure_count == 0) {
+		printf("No stations are currently associated.\n");
+		return BCME_OK;
+	}
+
+	/* Display Column headers - mac address always, then, depending on display mode */
+
+	printf("%17s%c", "Station Address", sep);
+	switch (display_mode) {
+	case DISPLAY_RAW:
+		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
+			"retry_drop", "rtsfail", "retry", "txrate_main",
+			"txrate_succ", "acked", "throughput", "time_delta", "airtime");
+		break;
+	case DISPLAY_COOKED:
+		printf("%10s%c%10s%c%10s%c%10s%c%10s\n", "PHY Mbps", sep, "Data Mbps", sep,
+			"Air Use", sep, "Data Use", sep, "Retries");
+		break;
+	}
+
+	/* Convert returned counters to host byte order, and sum up total throughput */
+
+	for (argn = 0; argn < data->structure_count; ++argn) {
+
+		iov_bs_data_record_t *rec;
+		iov_bs_data_counters_t *ctr;
+		float data_rate;
+
+		rec = &data->structure_record[argn];
+		ctr = &rec->station_counters;
+
+#define DEVICE_TO_HOST(xyzzy) ctr->xyzzy = dtoh32(ctr->xyzzy)
+		DEVICE_TO_HOST(retry_drop);
+		DEVICE_TO_HOST(rtsfail);
+		DEVICE_TO_HOST(retry);
+		DEVICE_TO_HOST(txrate_main);
+		DEVICE_TO_HOST(txrate_succ);
+		DEVICE_TO_HOST(acked);
+		DEVICE_TO_HOST(throughput);
+		DEVICE_TO_HOST(time_delta);
+		DEVICE_TO_HOST(airtime);
+#undef DEVICE_TO_HOST
+
+		/* Calculate data rate in bits per second, rather than bytes per second */
+		data_rate = (ctr->time_delta) ?
+			(float)((float)ctr->throughput * 8.0 / (float)ctr->time_delta) : 0.0;
+
+		total_throughput += data_rate;
+	}
+
+	for (argn = 0; argn < data->structure_count; ++argn) {
+		iov_bs_data_record_t *rec;
+		iov_bs_data_counters_t *ctr;
+		rec = &data->structure_record[argn];
+		ctr = &rec->station_counters;
+
+		if (skip_idle && (ctr->acked == 0)) continue;
+
+		printf("%17s%c", wl_ether_etoa(&rec->station_address), sep);
+		switch (display_mode) {
+		case DISPLAY_RAW:
+			printf("%9d %9d %9d %9d %9d %9d %9d %9d %9d\n",
+				ctr->retry_drop, ctr->rtsfail, ctr->retry,
+				ctr->txrate_main, ctr->txrate_succ, ctr->acked,
+				ctr->throughput, ctr->time_delta, ctr->airtime);
+			break;
+		case DISPLAY_COOKED:
+			{
+			float data_rate;
+			float phy_rate;
+			float use, air, rtr;
+
+			/* Calculate PHY rate */
+			phy_rate = (ctr->acked) ?
+				(float)((float)ctr->txrate_succ * 0.5 / (float)ctr->acked) : 0.0;
+
+			/* Calculate Data rate */
+			data_rate = (ctr->time_delta) ?
+				(float)((float)ctr->throughput * 8.0 / (float)ctr->time_delta) :
+				0.0;
+
+			/* Calculate use percentage amongst throughput from all stations */
+			use = (total_throughput) ? (float)(data_rate / total_throughput * 100.0) :
+				0.0;
+
+			/* Calculate % airtime */
+			air = (ctr->time_delta) ? (float)((float)ctr->airtime * 100.0 /
+			          (float) ctr->time_delta) : 0.0;
+
+			/* Calculate retry percentage */
+			rtr = (ctr->acked) ? (float)((float)ctr->retry / (float)ctr->acked * 100) :
+				0.0;
+
+			printf("%10.1f%c%10.1f%c%9.1f%%%c%9.1f%%%c%9.1f%%\n",
+				phy_rate, sep, data_rate, sep, air, sep, use, sep, rtr);
+			}
+			break;
+		}
+	}
+	return BCME_OK;
+}
+
+/* IO variables that take MAC addresses (with optional single letter prefix)
+ * and output a string buffer
+ */
+static int
+wl_iov_pktqlog_params(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	char** macaddrs = argv + 1;
+
+	wl_iov_mac_full_params_t*  full_params = (wl_iov_mac_full_params_t*)buf;
+	wl_iov_mac_params_t*       params = &full_params->params;
+	wl_iov_mac_extra_params_t* extra_params = &full_params->extra_params;
+
+	wl_iov_mac_params_t       loop_params;
+	wl_iov_mac_extra_params_t loop_extra_params;
+	uint32   index;
+	bool  loop_assoclist = FALSE;
+	struct maclist* maclist = NULL;
+	wlc_rev_info_t revinfo;
+	uint32 corerev;
+
+	if (cmd->get < 0)
+		return -1;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	corerev = dtoh32(revinfo.corerev);
+
+	memset(full_params, 0, sizeof(*full_params));
+	memset(&loop_params, 0, sizeof(loop_params));
+	memset(&loop_extra_params, 0, sizeof(loop_extra_params));
+
+	/* only pass up to WL_IOV_MAC_PARAM_LEN parameters */
+	while (params->num_addrs < WL_IOV_MAC_PARAM_LEN && *macaddrs) {
+		bool    full_auto = FALSE;
+		char*   ptr = *macaddrs;
+		uint32  bitmask;
+
+		/* is there a prefix character? */
+		if (ptr[1] == ':') {
+			params->addr_type[params->num_addrs] = toupper((int)(ptr[0]));
+
+			/* move ptr to skip over prefix */
+			ptr += 2;
+
+			/* is there the 'long form' option ? */
+			if (ptr[0] == '+') {
+				/* check for + additional info option, set top bit */
+				params->addr_type[params->num_addrs]  |= 0x80;
+				ptr++;
+			}
+			if ((ptr[0] == 0) || (ptr[0] == '/' || ptr[0] == ',')) {
+				/* this is the fully automatic mode */
+				full_auto = TRUE;
+			}
+		}
+
+		/* the prefix C: denotes no given MAC address (to refer to "common") */
+		if ((params->addr_type[params->num_addrs] & 0x7F) == 'C')  {
+			full_auto = FALSE;
+		}
+		else if (full_auto) {
+			loop_assoclist = TRUE;
+			loop_params.addr_type[loop_params.num_addrs] =
+			                     params->addr_type[params->num_addrs];
+		}
+		else if (wl_ether_atoe(ptr, &params->ea[params->num_addrs])) {
+			 /* length of MAC addr string excl end char */
+			ptr += (ETHER_ADDR_STR_LEN - 1);
+		}
+		else {
+			params->addr_type[params->num_addrs] = 0;
+			printf("Bad parameter '%s'\n", *macaddrs);
+			++macaddrs;
+			continue;
+		}
+
+
+		bitmask = 0;
+
+		while (ptr && (ptr[0] == ',' || ptr[0] == '/') &&
+		         ((ptr[1] >= '0' && ptr[1] <= '9') ||
+		         ptr[1] == '/' || ptr[1] == ',')) {
+
+			uint8 prec;
+			char* endptr = 0;
+
+			if (ptr[1] == '/' || ptr[1] == ',') {
+				/* this is the 'auto' setting */
+				bitmask |= PKTQ_LOG_AUTO;
+				ptr += 2;
+			}
+			else {
+				ptr++;
+
+				prec = (uint8)strtoul(ptr, &endptr, 10);
+
+				if (prec <= 15) {
+					bitmask |= (1 << prec);
+				}
+				else {
+					printf("Bad precedence %d (will be ignored)\n",
+					       prec);
+				}
+				ptr = endptr;
+			}
+
+		}
+
+		if (bitmask == 0) {
+			/* PKTQ_LOG_DEF_PREC is ignored in V4, it is used to indicate no prec was
+			 * selected
+			 */
+			bitmask = 0xFFFF | PKTQ_LOG_DEF_PREC;
+		}
+
+		if (full_auto) {
+			loop_extra_params.addr_info[loop_params.num_addrs] = bitmask;
+			loop_params.num_addrs++;
+		}
+		else {
+			extra_params->addr_info[params->num_addrs] = bitmask;
+			params->num_addrs ++;
+		}
+		++macaddrs;
+	}
+
+	while (*macaddrs) {
+		printf("Ignoring excess parameter '%s' (maximum number of params is %d)\n",
+		       *macaddrs, WL_IOV_MAC_PARAM_LEN);
+		++macaddrs;
+	}
+
+	/* if no valid params found, pass default prefix 'C' with no mac address */
+	if (params->num_addrs == 0 && !loop_assoclist)
+	{
+		params->addr_type[0] = 'C';
+		extra_params->addr_info[0] = 0xFFFF;
+		params->num_addrs = 1;
+	}
+
+	if (params->num_addrs) {
+		/* set a "version" indication (ie extra_params present) */
+		params->num_addrs |= (4 << 8);
+
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, full_params,
+		                            sizeof(*full_params),
+		                            buf, WLC_IOCTL_MAXLEN)) < 0) {
+			fprintf(stderr, "Error getting variable %s\n", argv[0]);
+			return ret;
+		}
+
+		wl_txq_prec_dump((wl_iov_pktq_log_t*)buf, FALSE, corerev >= 40);
+
+	}
+	if (!loop_assoclist) {
+		return 0;
+	}
+
+	maclist = malloc(WLC_IOCTL_MEDLEN);
+
+	if (!maclist) {
+		fprintf(stderr, "unable to allocate memory\n");
+		return -ENOMEM;
+	}
+	maclist->count = htod32((WLC_IOCTL_MEDLEN - sizeof(int)) / ETHER_ADDR_LEN);
+
+	if ((ret = wlu_get(wl, WLC_GET_ASSOCLIST, maclist, WLC_IOCTL_MEDLEN)) < 0) {
+		fprintf(stderr, "Cannot get assoclist\n");
+		free(maclist);
+		return ret;
+	}
+	maclist->count = dtoh32(maclist->count);
+
+	if (maclist->count == 0) {
+		fprintf(stderr, "No available addresses in assoclist for automatic operation\n");
+		free(maclist);
+		return 0;
+	}
+
+	for (index = 0; index < loop_params.num_addrs; index++) {
+		uint32 ea_index = 0;
+
+		while (ea_index < maclist->count) {
+
+			memset(full_params, 0, sizeof(*full_params));
+
+			while ((params->num_addrs < WL_IOV_MAC_PARAM_LEN) &&
+			       (ea_index < maclist->count)) {
+
+				params->addr_type[params->num_addrs] = loop_params.addr_type[index];
+				params->ea[params->num_addrs] = maclist->ea[ea_index];
+				extra_params->addr_info[params->num_addrs] =
+					loop_extra_params.addr_info[index] | PKTQ_LOG_AUTO;
+
+				params->num_addrs++;
+				ea_index++;
+			}
+
+			/* set a "version" indication (ie extra_params present) */
+			params->num_addrs |= (4 << 8);
+
+			if ((ret = wlu_iovar_getbuf(wl, cmd->name, full_params,
+			                            sizeof(*full_params),
+			                            buf, WLC_IOCTL_MAXLEN)) < 0) {
+				fprintf(stderr, "Error getting %s\n", argv[0]);
+				free(maclist);
+				return ret;
+			}
+
+			wl_txq_prec_dump((wl_iov_pktq_log_t*)buf, TRUE, corerev >= 40);
+		}
+	}
+	free(maclist);
+	return 0;
+}
+
+static int
+wlu_dump_phytbls(void *wl, char *dump_buf)
+{
+	/* The IOVAR's used in iteration */
+	const char str_phytbl[] = "phytbl";
+	const char str_phytbl_page[] = "phydump_page";
+	const char str_phytbl_entry[] = "phydump_entry";
+	int phytbl_page = 0;
+	int phytbl_entry = 0;
+	int ret;
+
+	/* Initialize page and entry */
+	ret = wlu_iovar_setint(wl, str_phytbl_page, phytbl_page);
+	if (ret != BCME_OK) {
+		fprintf(stderr, "IOVAR %s is not supported by firmware\n", str_phytbl_page);
+	} else {
+		ret = wlu_iovar_setint(wl, str_phytbl_entry, phytbl_entry);
+		if (ret != BCME_OK) {
+			fprintf(stderr, "IOVAR %s is not supported by firmware\n",
+					str_phytbl_entry);
+		}
+		else {
+			/* Dump the whole table by iterating str_phytbl IOVAR */
+			do {
+				strncpy(dump_buf, str_phytbl, sizeof(str_phytbl));
+				if ((ret = wlu_iovar_getbuf(wl, "dump",
+						dump_buf, (int)strlen(dump_buf),
+						dump_buf, WL_DUMP_BUF_LEN)) >= 0) {
+					fputs(dump_buf, stdout);
+					memset(dump_buf, 0, WL_DUMP_BUF_LEN);
+					if (((ret = wlu_iovar_getint(wl, str_phytbl_page,
+							&phytbl_page)) >= 0) &&
+							(phytbl_page == 0)) {
+						ret = wlu_iovar_getint(wl, str_phytbl_entry,
+								&phytbl_entry);
+					}
+				}
+			/* Iteration ends when both page and entry wrap around */
+			} while ((ret >= BCME_OK) && ((phytbl_page != 0) || (phytbl_entry != 0)));
+		}
+	}
+	return ret;
+}
+
+static int
+wlu_dump(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, err, bcmerr;
+	char *dump_buf;
+
+	/* This suboption is only known to wl, IOVAR list won't show it */
+	const char str_phytbls[] = "phytbls";
+
+	if (cmd->get < 0)
+		return -1;
+
+	dump_buf = malloc(WL_DUMP_BUF_LEN);
+	if (dump_buf == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n", WL_DUMP_BUF_LEN);
+		return BCME_NOMEM;
+	}
+	memset(dump_buf, 0, WL_DUMP_BUF_LEN);
+
+	/* skip the command name */
+	argv++;
+
+	/* If no args given, get the subset of 'wl dump all'
+	 * Otherwise, if args are given, they are the dump section names.
+	 */
+	if (*argv == NULL) {
+		/* query for the 'dump' without any argument */
+		ret = wlu_iovar_getbuf(wl, "dump", NULL, 0, dump_buf, WL_DUMP_BUF_LEN);
+
+		/* if the query is successful, continue on and print the result. */
+
+		/* if the query fails, check for a legacy driver that does not support
+		 * the "dump" iovar, and instead issue a WLC_DUMP ioctl.
+		 */
+		if (ret) {
+			err = wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+			if (!err && (bcmerr == BCME_UNSUPPORTED)) {
+				ret = wlu_get(wl, WLC_DUMP, dump_buf, WL_DUMP_BUF_LEN);
+				if (ret) {
+					fprintf(stderr, "dump: error on query of WLC_DUMP\n");
+				}
+			} else {
+				fprintf(stderr, "dump: error on query of dump list\n");
+			}
+		}
+	} else if (!strncmp(*argv, str_phytbls, sizeof(str_phytbls))) {
+		ret = wlu_dump_phytbls(wl, dump_buf);
+	} else {
+		/* create the dump section name list */
+		while (*argv) {
+			/* add space delimiter if this is not the first section name */
+			if (dump_buf[0] != '\0')
+				strcat(dump_buf, " ");
+
+			strcat(dump_buf, *argv);
+
+			argv++;
+		}
+
+		/* This is a "space" added at end of last argument */
+		strcat(dump_buf, " ");
+
+		ret = wlu_iovar_getbuf(wl, "dump", dump_buf, (int)strlen(dump_buf),
+				dump_buf, WL_DUMP_BUF_LEN);
+	}
+
+	if (ret >= BCME_OK) {
+		ret = BCME_OK;
+		fputs(dump_buf, stdout);
+	}
+
+	free(dump_buf);
+
+	return ret;
+}
+
+static int
+wlu_dump_clr(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+
+	/* skip the command name */
+	argv++;
+
+	/* call dump_clear for each category */
+	while (*argv != NULL) {
+		memset(buf, 0, WLC_IOCTL_MAXLEN);
+
+		ret = wlu_iovar_setbuf(wl, cmd->name, *argv, strlen(*argv),
+		                       buf, WLC_IOCTL_MAXLEN);
+		if (ret != BCME_OK) {
+			fprintf(stderr, "%s: error on %s\n", cmd->name, *argv);
+			return ret;
+		}
+		argv++;
+	}
+
+	return BCME_OK;
+}
+
+static int
+wl_staprio(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_USAGE_ERROR;
+	wl_staprio_cfg_t staprio_cfg;
+	char 	*endptr = NULL;
+
+	if (!*++argv) return -1;
+
+	/* get link mac address */
+	if (!wl_ether_atoe(*argv++, &staprio_cfg.ea))
+		goto error;
+
+	if (argv[0]) {
+		staprio_cfg.prio = (uint8)strtol(argv[0], &endptr, 0);
+		if (*endptr != '\0')
+			goto error;
+
+		if (staprio_cfg.prio > 3) {
+			printf("prio %d out of range [0, 3]\n", staprio_cfg.prio);
+			goto error;
+		}
+		else {
+			printf("Set SCB prio: 0x%x\n", staprio_cfg.prio);
+			ret = wlu_iovar_setbuf(wl, cmd->name, (void *) &staprio_cfg,
+				sizeof(wl_staprio_cfg_t), buf, WLC_IOCTL_MEDLEN);
+		}
+	}
+	else {
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, (void *) &staprio_cfg,
+			sizeof(wl_staprio_cfg_t), buf, WLC_IOCTL_MEDLEN)) >= 0) {
+			printf("SCB prio: 0x%x\n", ((wl_staprio_cfg_t *)buf)->prio);
+		}
+	}
+
+error:
+	return ret;
+}
+
+static int
+wl_aibss_bcn_force_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_USAGE_ERROR;
+	aibss_bcn_force_config_t bcn_config;
+
+	if (!*++argv) {
+		/* Get */
+		memset(&bcn_config, 0, sizeof(aibss_bcn_force_config_t));
+		/* get current rateset */
+		if ((ret = wlu_iovar_get(wl, cmd->name, &bcn_config,
+			sizeof(aibss_bcn_force_config_t))) < 0)
+			goto error;
+
+		printf("AIBSS Initial beacon check duration: %d \r\n"
+				"AIBSS beacon check duration:%d \r\n"
+				"AIBSS beacon flood duration:%d\r\n",
+				bcn_config.initial_min_bcn_dur, bcn_config.min_bcn_dur,
+				bcn_config.bcn_flood_dur);
+	}
+	else {
+		char *p = argv[0];
+		char *endptr = NULL;
+
+		/* Extract the content */
+		if (!p || *p == '\0')
+			goto error;
+
+		bcn_config.initial_min_bcn_dur = strtoul(p, &endptr, 0);
+
+		p = endptr;
+		/* check and skip , */
+		if (*p == '\0' || *++p == '\0')
+			goto error;
+
+		bcn_config.min_bcn_dur = strtoul(p, &endptr, 0);
+
+		p = endptr;
+		/* check and skip , */
+		if (*p == '\0' || *++p == '\0')
+			goto error;
+
+		bcn_config.bcn_flood_dur = strtoul(p, &endptr, 0);
+
+		if (*endptr != '\0')
+			goto error;
+		bcn_config.version = AIBSS_BCN_FORCE_CONFIG_VER_0;
+		bcn_config.len = sizeof(aibss_bcn_force_config_t);
+		ret = wlu_iovar_set(wl, cmd->name, (void *) &bcn_config,
+			sizeof(aibss_bcn_force_config_t));
+	}
+
+error:
+	return ret;
+}
+
+
+static int
+wlu_srdump(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i, nw, nb = 0;
+	uint16 *words = (uint16 *)&buf[8];
+
+	srom_rw_t   *srt;
+
+	/*
+	 * Avoid wl utility to driver compatibility issues by reading a 'safe' amount of words from
+	 * SPROM to determine the SPROM version that the driver supports, once the version is known
+	 * the full SPROM contents can be read. At the moment sromrev12 is the largest.
+	 */
+	nw = MAX(MAX(SROM10_SIGN, SROM11_SIGN), SROM11_SIGN)  + 1;
+
+	srt = (srom_rw_t *)buf;
+	srt->byteoff = htod32(0);
+	srt->nbytes = htod32(2 * nw);
+
+	if (cmd->get < 0)
+		return -1;
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	if (words[SROM11_SIGN] == SROM15_SIGNATURE) {
+		nw = SROM15_WORDS;
+	} else if (words[SROM11_SIGN] == SROM13_SIGNATURE) {
+		nw = SROM13_WORDS;
+	} else if (words[SROM11_SIGN] == SROM12_SIGNATURE) {
+		nw = SROM12_WORDS;
+	} else if (words[SROM11_SIGN] == SROM11_SIGNATURE) {
+		nw = SROM11_WORDS;
+	} else if (words[SROM10_SIGN] == SROM10_SIGNATURE) {
+		nw = SROM10_WORDS;
+	} else if (words[SROM16_SIGN] == SROM16_SIGNATURE) {
+		nw = SROM16_WORDS;
+	} else {
+		nw = SROM4_WORDS;
+		if ((words[SROM4_SIGN] != SROM4_SIGNATURE) &&
+			(words[SROM8_SIGN] != SROM4_SIGNATURE))
+			nw = SROM_WORDS;
+	}
+
+	/* allow reading a larger (or any other-size one) if specified */
+	if (*++argv != NULL) {
+		nb = (int)strtol(*argv, NULL, 0);
+		if (nb & 1) {
+			printf("Byte count %d is odd\n", nb);
+			return BCME_BADARG;
+		}
+		nw = nb / 2;
+	}
+
+	/* Since the SROM version known at this point, the entire SPROM contents can be read */
+	srt->nbytes = htod32(2 * nw);
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	for (i = 0; i < nw; i++) {
+		if ((i % 8) == 0)
+			printf("\n  srom[%03d]:  ", i);
+		printf("0x%04x  ", words[i]);
+	}
+	printf("\n");
+
+	return 0;
+}
+
+int
+wlu_srwrite(void *wl, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return (-1);
+#elif	defined(DONGLEBUILD)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return 0;
+#else
+	char *arg;
+	char *endptr;
+	FILE *fp = NULL;
+	int ret = 0, erase, srcrc;
+	uint i, len;
+	srom_rw_t *srt = (srom_rw_t *)buf;
+	char *tempbuf = NULL;
+
+	erase = !strcmp(*argv, "srclear");
+	srcrc = !strcmp(*argv, "srcrc");
+
+	/* We need at least one arg */
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	arg = *argv++;
+
+	if (erase) {
+		if (*argv)
+			return BCME_USAGE_ERROR;
+		len = strtoul(arg, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "error parsing value \"%s\" as an integer for byte count\n",
+			        arg);
+			return BCME_USAGE_ERROR;
+		}
+		srt->byteoff = 0x55aa;
+	} else if (!*argv) {  /* srwrite or srcrc */
+		/* Only one arg, it better be a file name */
+		if (!(fp = fopen(arg, "rb"))) {
+			fprintf(stderr, "%s: No such file or directory\n", arg);
+			return BCME_BADARG;
+		}
+
+		len = fread(srt->buf, 1, SROM_MAX + 1, fp);
+		if ((ret = ferror(fp))) {
+			printf("\nerror %d reading %s\n", ret, arg);
+			ret = BCME_ERROR;
+			goto out;
+		}
+
+		if (!feof(fp)) {
+			printf("\nFile %s is too large\n", arg);
+			ret = BCME_ERROR;
+			goto out;
+		}
+
+		if (len == SROM4_WORDS * 2) {
+			if ((srt->buf[SROM4_SIGN] != SROM4_SIGNATURE) &&
+			    (srt->buf[SROM8_SIGN] != SROM4_SIGNATURE)) {
+				printf("\nFile %s is %d bytes but lacks a REV4/ signature\n",
+				       arg, SROM4_WORDS * 2);
+				ret = BCME_ERROR;
+				goto out;
+			}
+		} else if (len == SROM11_WORDS * 2) {
+			if (srt->buf[SROM11_SIGN] != SROM11_SIGNATURE) {
+				printf("\nFile %s is %d bytes but lacks a REV11/ signature\n",
+				       arg, SROM11_WORDS * 2);
+				ret = BCME_ERROR;
+				goto out;
+			}
+		} else if (len == SROM12_WORDS * 2) {
+			if ((srt->buf[SROM11_SIGN] != SROM12_SIGNATURE) &&
+			    (srt->buf[SROM16_SIGN] != SROM16_SIGNATURE)) {
+				printf("\nFile %s is %d bytes but lacks a REV12/REV16 signature\n",
+				       arg, SROM12_WORDS * 2);
+				ret = BCME_ERROR;
+				goto out;
+			}
+		} else if (len == SROM13_WORDS * 2) {
+			if (srt->buf[SROM11_SIGN] != SROM13_SIGNATURE) {
+				printf("\nFile %s is %d bytes but lacks a REV13/ signature\n",
+				       arg, SROM13_WORDS * 2);
+				ret = BCME_ERROR;
+				goto out;
+			}
+		} else if (len == SROM15_WORDS * 2) {
+			if ((srt->buf[SROM11_SIGN] != SROM15_SIGNATURE) &&
+				(srt->buf[SROM16_SIGN] != SROM16_SIGNATURE)) {
+				printf("\nFile %s is %d bytes but lacks a REV15/REV16 signature\n",
+				       arg, SROM15_WORDS * 2);
+				ret = BCME_ERROR;
+				goto out;
+			}
+		}
+		else if ((len != SROM_WORDS * 2) && (len != SROM10_WORDS * 2) &&
+			(len != SROM_MAX)) {
+			printf("\nFile %s is %d bytes, not %d or %d or %d or %d bytes\n", arg, len,
+				SROM_WORDS * 2, SROM4_WORDS * 2, SROM10_WORDS, SROM_MAX);
+			ret = BCME_ERROR;
+			goto out;
+		}
+
+		srt->byteoff = 0;
+	} else {
+		if (srcrc) {
+			printf("srcrc only takes one arg\n");
+			ret = BCME_USAGE_ERROR;
+			goto out;
+		}
+
+		/* More than 1 arg, first is offset, rest are data. */
+		srt->byteoff = strtoul(arg, &endptr, 0);
+		if (*endptr != '\0')
+			goto nout;
+
+		i = 0;
+		while ((arg = *argv++) != NULL) {
+			srt->buf[i++] = (uint16)strtoul(arg, &endptr, 0);
+			if (*endptr != '\0') {
+nout:
+				printf("\n%s is not an integer\n", arg);
+				ret = BCME_USAGE_ERROR;
+				goto out;
+			}
+		}
+
+		if (srt->byteoff & 1) {
+			printf("Byte offset (%d) is odd or negative\n", srt->byteoff);
+			ret = BCME_BADARG;
+			goto out;
+		}
+
+		len = 2 * i;
+		if ((srt->byteoff + len) > SROM_MAX) {
+			printf("Data extends past %d bytes\n", SROM_MAX);
+			ret = BCME_BUFTOOLONG;
+			goto out;
+		}
+	}
+	srt->nbytes = len;
+
+	if (srcrc) {
+		srt->byteoff = 0x55ab;	/* Hack for srcrc */
+		if ((ret = wlu_get(wl, cmd->get, buf, len + 8)) == 0)
+			printf("0x%x\n", (uint8)buf[0]);
+	} else {
+		tempbuf = malloc(SROM_MAX);
+		if (tempbuf == NULL) {
+			ret = BCME_NOMEM;
+			goto out;
+		}
+		if ((arg != NULL) && (len > MAX_IOCTL_TXCHUNK_SIZE) && (srt->byteoff != 0x55aa)) {
+			if (!(fp = fopen(arg, "rb"))) {
+				fprintf(stderr, "%s: No such file or directory\n", arg);
+				ret = BCME_BADARG;
+				goto out;
+			}
+			len = fread(tempbuf, 1, SROM_MAX + 1, fp);
+			memcpy(srt->buf, tempbuf, MAX_IOCTL_TXCHUNK_SIZE);
+			srt->byteoff = htod32(0);
+			srt->nbytes = htod32(MAX_IOCTL_TXCHUNK_SIZE);
+			ret	= wlu_set(wl, cmd->set, buf, MAX_IOCTL_TXCHUNK_SIZE + 8);
+			memcpy(srt->buf, tempbuf + MAX_IOCTL_TXCHUNK_SIZE,
+				len - MAX_IOCTL_TXCHUNK_SIZE);
+			srt->byteoff = htod32(MAX_IOCTL_TXCHUNK_SIZE);
+			srt->nbytes = htod32(len - MAX_IOCTL_TXCHUNK_SIZE);
+			ret	= wlu_set(wl, cmd->set, buf, len - MAX_IOCTL_TXCHUNK_SIZE + 8);
+		}
+		else {
+			ret = wlu_set(wl, cmd->set, buf, len + 8);
+		}
+	}
+
+out:
+	fflush(stdout);
+	if (fp)
+		fclose(fp);
+	if (tempbuf)
+		free(tempbuf);
+	return ret;
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+wlu_ciswrite(void *wl, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return (-1);
+#elif	defined(DONGLEBUILD)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return 0;
+#else
+	char *arg, *bufp;
+	FILE *fp = NULL;
+	int ret = 0;
+	uint32 len;
+
+	cis_rw_t cish;
+	char *cisp, *cisdata;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg check -- error if no arg */
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	memset((char*)&cish, 0, sizeof(cish));
+	/* Grab and move past optional output file argument */
+	if ((strcmp(*argv, "--pciecis") == 0) || (strcmp(*argv, "-p") == 0)) {
+		printf("Writing in PCIe CIS format\n");
+
+		cish.flags |= CISH_FLAG_PCIECIS;	/* write CIS format bit */
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+	}
+
+	/* initialize buffer with iovar */
+	bufp = buf;
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(bufp, "ciswrite");
+	bufp += strlen("ciswrite") + 1;
+	cisp = bufp;
+	cisdata = cisp + sizeof(cish);
+
+	/* grab the filename arg */
+	arg = *argv;
+	if (!(fp = fopen(arg, "rb"))) {
+		fprintf(stderr, "%s: No such file or directory\n", arg);
+		return BCME_BADARG;
+	}
+
+	len = fread(cisdata, 1, SROM_MAX + 1, fp);
+	if ((ret = ferror(fp))) {
+		printf("\nerror %d reading %s\n", ret, arg);
+		ret = BCME_ERROR;
+		goto out;
+	}
+
+	if (!feof(fp)) {
+		printf("\nFile %s is too large\n", arg);
+		ret = BCME_ERROR;
+		goto out;
+	}
+
+	/* Convert the endianess for non-zero fields */
+	cish.flags = htod16(cish.flags);
+	cish.nbytes = htod32(len); /* fill in length (offset is 0) */
+	memcpy(cisp, (char*)&cish, sizeof(cish));
+
+	printf("len %d sizeof(cish) %d total %d\n", len, (int)sizeof(cish),
+	       (int)(len + sizeof(cish)));
+	ret = wl_set(wl, WLC_SET_VAR, buf, (cisp - buf) + sizeof(cish) + len);
+	if (ret < 0) {
+		fprintf(stderr, "ciswrite failed: %d\n", ret);
+	}
+
+out:
+	if (fp)
+		fclose(fp);
+
+	return ret;
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+wlu_cisupdate(void *wl, cmd_t *cmd, char **argv)
+{
+#if	defined(DONGLEBUILD)
+	return 0;
+#else
+	char *bufp, *endptr;
+	int ret = 0;
+	int preview = 0;
+	uint32 off;
+	uint32 len;
+	uint32 updatelen;
+	uint32 i;
+	char hexstr[3];
+	char bytes[SROM_MAX];
+
+	cis_rw_t cish;
+	char *cisp;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* validate arg count */
+	if (!*++argv || !argv[1])
+		return BCME_USAGE_ERROR;
+
+	if (argv[2] && !strcmp(argv[2], "--preview"))
+		preview = 1;
+
+	/* grab byte offset */
+	off = (uint32)strtol(argv[0], &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+
+	bufp = argv[1];
+	updatelen = strlen(bufp);
+	if (updatelen % 2) {
+		fprintf(stderr, "cisupdate hex string must contain an even number of digits\n");
+		goto done;
+	}
+	updatelen /= 2;
+
+	/* convert and store hex byte values */
+	for (i = 0; i < updatelen; i++) {
+		hexstr[0] = *bufp;
+		hexstr[1] = *(bufp + 1);
+		if (!isxdigit((int)hexstr[0]) || !isxdigit((int)hexstr[1])) {
+			fprintf(stderr, "cisupdate invalid hex digit(s) in %s\n", argv[1]);
+			goto done;
+		}
+		hexstr[2] = '\0';
+		bytes[i] = (char) strtol(hexstr, NULL, 16);
+		bufp += 2;
+	}
+
+	/* Prepare the read info */
+	memset((char*)&cish, 0, sizeof(cish));
+
+	/* set up the buffer and do the get (+9 allows space for "ciswrite" string later) */
+	memset(buf + 9, 0, (WLC_IOCTL_MAXLEN - 9));
+	strcpy(buf + 9, "cisdump");
+	bufp = buf + strlen("cisdump") + 1 + 9;
+	memcpy(bufp, (char*)&cish, sizeof(cish));
+	bufp += sizeof(cish);
+	ret = wl_get(wl, WLC_GET_VAR, buf + 9, (bufp - (buf + 9)) + SROM_MAX);
+	if (ret < 0) {
+		fprintf(stderr, "cisupdate failed to read cis: %d\n", ret);
+		goto done;
+	}
+
+	/* pull off the cis_rw_t */
+	bufp = buf + 9;
+	memcpy((char*)&cish, bufp, sizeof(cish));
+	len = dtoh32(cish.nbytes);
+
+	if ((off + updatelen) > len) {
+		fprintf(stderr, "cisupdate offset %d plus update len %d exceeds CIS len %d\n",
+		        off, updatelen, len);
+		goto done;
+	}
+
+	/* move past to the data */
+	bufp += sizeof(cish);
+
+	/* update the bytes */
+	if (dtoh16(cish.source) == WLC_CIS_SROM) {
+		for (i = 0; i < updatelen; ++i)
+			bufp[off + i] = bytes[i] & 0xff;
+	} else {
+		for (i = 0; i < updatelen; ++i) {
+			if (~bytes[i] & bufp[off + i]) {
+				fprintf(stderr, "cisupdate: OTP update incompatible:"
+				        " update[%d](0x%02x)->cis[%d](0x%02x)\n",
+				        i,  bytes[i], off + i, bufp[off + i]);
+				goto done;
+			}
+			bufp[off + i] |= bytes[i];
+		}
+	}
+
+	/* initialize buffer with iovar */
+	bufp = buf;
+	strcpy(bufp, "ciswrite");
+	bufp += strlen("ciswrite") + 1;
+	cisp = bufp;
+
+	/* fill in cis_rw_t fields */
+	memset((char*)&cish, 0, sizeof(cish));
+	cish.nbytes = htod32(len);
+	memcpy(cisp, (char*)&cish, sizeof(cish));
+
+	/* write the data back to the device */
+	printf("offset %d data %s cislen %d\n", off, argv[1], len);
+	if (preview) {
+		bufp += sizeof(cish);
+		for (i = 0; i < len; i++) {
+			if ((i % 8) == 0)
+				printf("\nByte %3d: ", i);
+			printf("0x%02x ", (uint8)bufp[i]);
+		}
+		printf("\n");
+	} else {
+		ret = wl_set(wl, WLC_SET_VAR, buf, (cisp - buf) + sizeof(cish) + len);
+		if (ret < 0) {
+			fprintf(stderr, "cisupdate cis write failed: %d\n", ret);
+		}
+	}
+
+done:
+	return ret;
+#endif 
+}
+
+static int
+wlu_cisdump(void *wl, cmd_t *cmd, char **argv)
+{
+	char *bufp;
+	int i, ret = 0;
+	cis_rw_t cish;
+	uint nbytes = 0;
+	char *fname = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* Grab and move past optional output file argument */
+	if ((argv[1] != NULL) && (strcmp(argv[1], "-b") == 0)) {
+		fname = argv[2];
+		argv += 2;
+	}
+
+	/* check for a length argument */
+	if (*++argv != NULL) {
+		nbytes = (int)strtol(*argv, NULL, 0);
+		if (nbytes & 1) {
+			printf("Invalid byte count %d, must be even\n", nbytes);
+			ret = BCME_BADARG;
+			goto done;
+		}
+		if (nbytes > SROM_MAX) {
+			printf("Count %d too large\n", nbytes);
+			ret = BCME_BUFTOOLONG;
+			goto done;
+		}
+	}
+
+	/* Prepare the read info */
+	memset((char*)&cish, 0, sizeof(cish));
+	cish.nbytes = htod32(nbytes);
+
+	/* set up the buffer and do the get */
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "cisdump");
+	bufp = buf + strlen("cisdump") + 1;
+	memcpy(bufp, (char*)&cish, sizeof(cish));
+	bufp += sizeof(cish);
+	ret = wl_get(wl, WLC_GET_VAR, buf, (bufp - buf) + (nbytes ? nbytes : SROM_MAX));
+	if (ret < 0) {
+		fprintf(stderr, "Failed cisdump request: %d\n", ret);
+		goto done;
+	}
+
+	/* pull off the cis_rw_t */
+	bufp = buf;
+	memcpy((char*)&cish, bufp, sizeof(cish));
+	cish.source = dtoh16(cish.source);
+	cish.flags = dtoh16(cish.flags);
+	cish.byteoff = dtoh32(cish.byteoff);
+	cish.nbytes = dtoh32(cish.nbytes);
+
+	/* move past to the data */
+	bufp += sizeof(cish);
+
+	printf("Source: %d (%s)", cish.source,
+	       (cish.source == WLC_CIS_DEFAULT) ? "Built-in default" :
+	       (cish.source == WLC_CIS_SROM) ? "External SPROM" :
+	       (cish.source == WLC_CIS_OTP) ? "Internal OTP" : "Unknown?");
+	if (!nbytes)
+		printf("\nMaximum length: %d bytes", cish.nbytes);
+	for (i = 0; i < (int)cish.nbytes; i++) {
+		if ((i % 8) == 0)
+			printf("\nByte %3d: ", i);
+		printf("0x%02x ", (uint8)bufp[i]);
+	}
+	printf("\n");
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+#if !defined(DONGLEBUILD)
+	if (fname != NULL) {
+		FILE *fp;
+
+		if (!nbytes)
+			nbytes = cish.nbytes;
+
+		fp = fopen(fname, "wb");
+		if (fp != NULL) {
+			ret = fwrite(bufp, 1, nbytes, fp);
+			if (ret != (int)nbytes) {
+				fprintf(stderr, "Error writing %d bytes to file, rc %d!\n",
+				        (int)nbytes, ret);
+				ret = BCME_ERROR;
+			} else {
+				printf("Wrote %d bytes to %s\n", ret, fname);
+				ret = 0;
+			}
+			fclose(fp);
+		} else {
+			fprintf(stderr, "Problem opening file %s\n", fname);
+			ret = BCME_BADARG;
+		}
+	}
+#endif /* !(CFE|DONGLEBUILD|IOPOS) -- has stdio filesystem */
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+
+done:
+	return ret;
+}
+
+#if	defined(linux) || defined(DONGLEBUILD) || defined(__FreeBSD__) || \
+	defined(BWL_NO_INTERNAL_STDLIB_SUPPORT)
+/* linux, MacOS, NetBSD: ffs is in the standard C library */
+/* CFE, DONGLEBUILD & IOPOS: Not needed, the code below is ifdef out */
+#else
+static int
+ffs(int i)
+{
+	int j;
+
+	if (i != 0)
+		for (j = 0; j < 32; j++)
+			if (i & (1 << j))
+				return j + 1;
+	return 0;
+}
+#endif	
+
+#if	!defined(DONGLEBUILD)
+
+/* VX wants prototypes even for static functions. */
+static int newtuple(char *b, int *cnt, uint8 tag, const cis_tuple_t *srv);
+static int parsecis(char *b, char **argv, int sromrev);
+static const sromvar_t *srvlookup(const sromvar_t *tab, char *name, int nlen, int sromrev);
+
+/* Find an entry in argv[][] in this form
+ *	name=value, could be pattern=(0x)1234 or pattern=ABC
+ *
+ * If *val is NULL, return the pointer to value.
+ * If *val is not NULL, fill the value into val, return the pointer to name if found,
+ * return NULL if no match found.
+ */
+char*
+find_pattern(char **argv, const char *pattern, uint *val)
+{
+	char *ret = NULL, *name = NULL, **pargv = argv;
+
+	/* clear val first */
+	if (val)	*val = 0;
+
+	while ((name = *pargv++)) {
+		if ((ret = strstr(name, pattern))) {
+			char *p = ret, *q = NULL;
+
+			/* Extracting the content */
+			p += strlen(pattern);
+
+			/* var name could have same prefix */
+			if (*p++ != '=') {
+				ret = NULL;
+				continue;
+			}
+			if (!val)
+				return (ret+strlen(pattern)+1);
+
+			*val = strtoul(p, &q, 0);
+			if (p == q) {
+				printf("Bad value: %s\n", ret);
+				return NULL;
+			}
+
+			break;
+		}
+	}
+	return ret;
+}
+
+/* Find an entry in argv[][] in this form
+ *	name=value1,value2,...,value(n)
+ *		n is indicated by vnum
+ * 		could be pattern=(0x)1234,... or pattern=ABC,...
+ *
+ * If *val is NULL, return the pointer to value.
+ * If *val is not NULL, fill the value into val, return the pointer to name if found,
+ * return NULL if no match found.
+ */
+char*
+find_pattern2(char **argv, const char *pattern, uint *val, int vnum)
+{
+	char *ret = NULL, *name = NULL, **pargv = argv;
+	int i;
+
+	while ((name = *pargv++)) {
+		if ((ret = strstr(name, pattern))) {
+			char *p = ret, *q = NULL;
+
+			/* Extracting the content */
+			p += strlen(pattern);
+
+			/* var name could have same prefix */
+			if (*p++ != '=') {
+				ret = NULL;
+				continue;
+			}
+			if (!val)
+				return (ret+strlen(pattern)+1);
+
+			for (i = 0; i < vnum; i ++)
+			{
+				val[i] = strtoul(p, &q, 0);
+
+				if (p == q) {
+					printf("Bad value: %s\n", ret);
+					return NULL;
+				}
+				p = q + 1;	/* skip ',' */
+			}
+			break;
+		}
+	}
+	return ret;
+}
+
+static int
+newtuple(char *b, int *cnt, uint8 tag, const cis_tuple_t *srv)
+{
+	memset(b, 0, srv->len + 2);
+
+	b[0] = tag;
+	b[1] = (char)srv->len;
+	b[2] = (char)srv->tag;
+
+	if (cnt)
+		*cnt += 3;
+	return 0;
+}
+
+/**
+ * When programming OTP or SROM, driver expects to receive a CIS from the wl utility.
+ * This function converts a caller supplied string (in **argv) containing nvram variables pairs into
+ * a CIS (in *b). Caller can dictate the binary CIS contents  by using nvram string 'RAW=...' or
+ * 'RAW1=...'. Function will only create tuples for values in caller supplied nvram string.
+ */
+static int
+parsecis(char *b, char **argv, int sromrev)
+{
+	/* built-in list of known tuples and nvram var(s) associated with a specific tuple */
+	const cis_tuple_t *srv = cis_hnbuvars;
+	char	*cpar = NULL, *p = NULL;
+	char	*par;
+	char	delimit[2] = " \0";
+	int	cnt = 0, i = 0;
+	uint 	sromrev_mask = 0xffffffff;
+
+	if (sromrev > 0 && sromrev <= 31) {
+		sromrev_mask = 1 << sromrev;
+	} else {
+		printf("Invalid sromrev %d.\n", sromrev);
+		return BCME_BADARG;
+	}
+
+	/* Walk through built-in list of tuples, create append buffer */
+	while (srv->tag != 0xFF) {
+		uint val = 0;
+
+		/* Skip srv if not supported in sromrev */
+		if (!(sromrev_mask & srv->revmask)) {
+			srv++;
+			continue;
+		}
+
+		/* Special cases (Raw Data / macaddr / ccode / fem) */
+		if (srv->tag == OTP_RAW) {
+			if ((p = find_pattern(argv, "RAW", &val))) {
+				p += (strlen("RAW") + 1);	/* RAW= */
+				for (;;) {
+					b[cnt++] = (unsigned char) strtoul(p, &p, 16);
+					if (!*p++)
+						break;
+				}
+			}
+		} else if (srv->tag == OTP_RAW1) {
+			if ((p = find_pattern(argv, "RAW1", NULL))) {
+				for (;;) {
+					b[cnt++] = (unsigned char) strtoul(p, &p, 16);
+					if (!*p++)
+						break;
+				}
+			}
+		} else if (srv->tag == OTP_VERS_1) {
+			uint l1 = 1, l2 = 1;
+			char *p2 = NULL;
+
+			if ((p = find_pattern(argv, "manf", NULL)))
+				l1 += strlen(p);
+
+			if ((p2 = find_pattern(argv, "productname", NULL)))
+				l2 += strlen(p2);
+
+			if ((p != NULL) | (p2 != NULL)) {
+				b[cnt++] = CISTPL_VERS_1;
+				b[cnt++] = 2 + l1 + l2;
+				b[cnt++] = 8;
+				b[cnt++] = 0;
+				if (p) {
+					char *q = p;
+					/* Replace '_' by space */
+					while ((q = strchr(q, '_')))
+						*q = ' ';
+					memcpy(&b[cnt], p, l1);
+				} else
+					b[cnt] = '\0';
+				cnt += l1;
+
+				if (p2) {
+					char *q = p2;
+					/* Replace '_' by space */
+					while ((q = strchr(q, '_')))
+						*q = ' ';
+					memcpy(&b[cnt], p2, l2);
+				} else
+					b[cnt] = '\0';
+				cnt += l2;
+			}
+		} else if (srv->tag == OTP_MANFID) {
+			bool found = FALSE;
+			uint manfid = 0, prodid = 0;
+
+			if ((p = find_pattern(argv, "manfid", &manfid)))
+				found = TRUE;
+
+			if ((p = find_pattern(argv, "prodid", &prodid)))
+				found = TRUE;
+
+			if (found) {
+				b[cnt++] = CISTPL_MANFID;
+				b[cnt++] = srv->len;
+				b[cnt++] = (uint8)(manfid & 0xff);
+				b[cnt++] = (uint8)((manfid >> 8) & 0xff);
+				b[cnt++] = (uint8)(prodid & 0xff);
+				b[cnt++] = (uint8)((prodid >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_MACADDR) {
+			if ((p = find_pattern(argv, "macaddr", NULL))) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				if (!wl_ether_atoe(p, (struct ether_addr*)&b[cnt]))
+					printf("Argument does not look like a MAC "
+					"address: %s\n", p);
+				cnt += sizeof(struct ether_addr);
+			}
+		} else if (srv->tag == HNBU_MACADDR2) {
+			if ((p = find_pattern(argv, "macaddr2", NULL))) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				if (!wl_ether_atoe(p, (struct ether_addr*)&b[cnt]))
+					printf("Argument does not look like a MAC "
+						"address: %s\n", p);
+					cnt += sizeof(struct ether_addr);
+			}
+		} else if (srv->tag == HNBU_CCODE) {
+			bool found = FALSE;
+			char tmp[3] = "\0\0\0";
+
+			if ((p = find_pattern(argv, "ccode", NULL))) {
+				found = TRUE;
+				tmp[0] = *p++;
+				tmp[1] = *p++;
+			}
+			if ((p = find_pattern(argv, "cctl", &val))) {
+				found = TRUE;
+				tmp[2] = (uint8)val;
+			}
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				memcpy(&b[cnt], tmp, 3);
+				cnt += 3;	/* contents filled already */
+			}
+		} else if (srv->tag == HNBU_RSSISMBXA2G) {
+			bool found = FALSE;
+			char tmp[2] = "\0\0";
+
+			if ((p = find_pattern(argv, "rssismf2g", &val))) {
+				found = TRUE;
+				tmp[0] |= val & 0xf;
+			}
+			if ((p = find_pattern(argv, "rssismc2g", &val))) {
+				found = TRUE;
+				tmp[0] |= (val & 0xf) << 4;
+			}
+			if ((p = find_pattern(argv, "rssisav2g", &val))) {
+				found = TRUE;
+				tmp[1] |= val & 0x7;
+			}
+			if ((p = find_pattern(argv, "bxa2g", &val))) {
+				found = TRUE;
+				tmp[1] |= (val & 0x3) << 3;
+			}
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				memcpy(&b[cnt], tmp, 2);
+				cnt += 2;	/* contents filled already */
+			}
+		} else if (srv->tag == HNBU_RSSISMBXA5G) {
+			bool found = FALSE;
+			char tmp[2] = "\0\0";
+
+			if ((p = find_pattern(argv, "rssismf5g", &val))) {
+				found = TRUE;
+				tmp[0] |= val & 0xf;
+			}
+			if ((p = find_pattern(argv, "rssismc5g", &val))) {
+				found = TRUE;
+				tmp[0] |= (val & 0xf) << 4;
+			}
+			if ((p = find_pattern(argv, "rssisav5g", &val))) {
+				found = TRUE;
+				tmp[1] |= val & 0x7;
+			}
+			if ((p = find_pattern(argv, "bxa5g", &val))) {
+				found = TRUE;
+				tmp[1] |= (val & 0x3) << 3;
+			}
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				memcpy(&b[cnt], tmp, 2);
+				cnt += 2;	/* contents filled already */
+			}
+		} else if (srv->tag == HNBU_FEM) {
+			bool	found = FALSE;
+			uint16	tmp2g = 0, tmp5g = 0;
+
+			if ((p = find_pattern(argv, "antswctl2g", &val))) {
+				found = TRUE;
+				tmp2g |= ((val << SROM8_FEM_ANTSWLUT_SHIFT) &
+					SROM8_FEM_ANTSWLUT_MASK);
+			}
+			if ((p = find_pattern(argv, "triso2g", &val))) {
+				found = TRUE;
+				tmp2g |= ((val << SROM8_FEM_TR_ISO_SHIFT) &
+					SROM8_FEM_TR_ISO_MASK);
+			}
+			if ((p = find_pattern(argv, "pdetrange2g", &val))) {
+				found = TRUE;
+				tmp2g |= ((val << SROM8_FEM_PDET_RANGE_SHIFT) &
+					SROM8_FEM_PDET_RANGE_MASK);
+			}
+			if ((p = find_pattern(argv, "extpagain2g", &val))) {
+				found = TRUE;
+				tmp2g |= ((val << SROM8_FEM_EXTPA_GAIN_SHIFT) &
+					SROM8_FEM_EXTPA_GAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "tssipos2g", &val))) {
+				found = TRUE;
+				tmp2g |= ((val << SROM8_FEM_TSSIPOS_SHIFT) &
+					SROM8_FEM_TSSIPOS_MASK);
+			}
+			if ((p = find_pattern(argv, "antswctl5g", &val))) {
+				found = TRUE;
+				tmp5g |= ((val << SROM8_FEM_ANTSWLUT_SHIFT) &
+					SROM8_FEM_ANTSWLUT_MASK);
+			}
+			if ((p = find_pattern(argv, "triso5g", &val))) {
+				found = TRUE;
+				tmp5g |= ((val << SROM8_FEM_TR_ISO_SHIFT) &
+					SROM8_FEM_TR_ISO_MASK);
+			}
+			if ((p = find_pattern(argv, "pdetrange5g", &val))) {
+				found = TRUE;
+				tmp5g |= ((val << SROM8_FEM_PDET_RANGE_SHIFT) &
+					SROM8_FEM_PDET_RANGE_MASK);
+			}
+			if ((p = find_pattern(argv, "extpagain5g", &val))) {
+				found = TRUE;
+				tmp5g |= ((val << SROM8_FEM_EXTPA_GAIN_SHIFT) &
+					SROM8_FEM_EXTPA_GAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "tssipos5g", &val))) {
+				found = TRUE;
+				tmp5g |= ((val << SROM8_FEM_TSSIPOS_SHIFT) &
+					SROM8_FEM_TSSIPOS_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(tmp2g & 0xff);
+				b[cnt++] = (uint8)((tmp2g >> 8) & 0xff);
+				b[cnt++] = (uint8)(tmp5g & 0xff);
+				b[cnt++] = (uint8)((tmp5g >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_UUID) {
+
+			char *uuidstr = NULL;
+			char nibble[3] = {0, 0, 0};
+
+			if ((uuidstr = find_pattern(argv, "uuid", NULL)) != NULL) {
+
+				/* uuid format 12345678-1234-5678-1234-567812345678 */
+
+				if (strlen(uuidstr) == 36) {
+					newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+					while (*uuidstr != '\0') {
+						if (*uuidstr == '-') {
+							uuidstr++;
+							continue;
+						}
+						nibble[0] = *uuidstr++;
+						nibble[1] = *uuidstr++;
+						b[cnt ++] = (char)strtoul(nibble, NULL, 16);
+					}
+				}
+			}
+
+		} else if (srv->tag == HNBU_TEMPTHRESH) {
+			bool found = FALSE;
+			char tmp[6] = "\0\0\0\0\0\0";
+
+			if ((p = find_pattern(argv, "tempthresh", &val))) {
+				found = TRUE;
+				tmp[0] = val;
+			}
+			if ((p = find_pattern(argv, "temps_period", &val))) {
+				found = TRUE;
+				tmp[1] |= ((val << SROM11_TEMPS_PERIOD_SHIFT) &
+					SROM11_TEMPS_PERIOD_MASK);
+			}
+			if ((p = find_pattern(argv, "temps_hysteresis", &val))) {
+				found = TRUE;
+				tmp[1] |= ((val << SROM11_TEMPS_HYSTERESIS_SHIFT) &
+					SROM11_TEMPS_HYSTERESIS_MASK);
+			}
+			if ((p = find_pattern(argv, "tempoffset", &val))) {
+				found = TRUE;
+				tmp[2] = val;
+			}
+			if ((p = find_pattern(argv, "tempsense_slope", &val))) {
+				found = TRUE;
+				tmp[3] = val;
+			}
+			if ((p = find_pattern(argv, "tempcorrx", &val))) {
+				found = TRUE;
+				tmp[4] |= ((val << SROM11_TEMPCORRX_SHIFT) &
+					SROM11_TEMPCORRX_MASK);
+			}
+			if ((p = find_pattern(argv, "tempsense_option", &val))) {
+				found = TRUE;
+				tmp[4] |= ((val << SROM11_TEMPSENSE_OPTION_SHIFT) &
+					SROM11_TEMPSENSE_OPTION_MASK);
+			}
+			if ((p = find_pattern(argv, "phycal_tempdelta", &val))) {
+				found = TRUE;
+				tmp[5] = val;
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				memcpy(&b[cnt], tmp, 6);
+				cnt += 6;	/* contents filled already */
+			}
+		} else if (srv->tag == HNBU_FEM_CFG) {
+			bool found = FALSE;
+			uint16	fem_cfg1 = 0, fem_cfg2 = 0;
+
+			if ((p = find_pattern(argv, "femctrl", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_FEMCTRL_SHIFT) &
+					SROM11_FEMCTRL_MASK);
+			}
+			if ((p = find_pattern(argv, "papdcap2g", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_PAPDCAP_SHIFT) &
+					SROM11_PAPDCAP_MASK);
+			}
+			if ((p = find_pattern(argv, "tworangetssi2g", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_TWORANGETSSI_SHIFT) &
+					SROM11_TWORANGETSSI_MASK);
+			}
+			if ((p = find_pattern(argv, "pdgain2g", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_PDGAIN_SHIFT) &
+					SROM11_PDGAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "epagain2g", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_EPAGAIN_SHIFT) &
+					SROM11_EPAGAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "tssiposslope2g", &val))) {
+				found = TRUE;
+				fem_cfg1 |= ((val << SROM11_TSSIPOSSLOPE_SHIFT) &
+					SROM11_TSSIPOSSLOPE_MASK);
+			}
+			if ((p = find_pattern(argv, "gainctrlsph", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_GAINCTRLSPH_SHIFT) &
+					SROM11_GAINCTRLSPH_MASK);
+			}
+			if ((p = find_pattern(argv, "papdcap5g", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_PAPDCAP_SHIFT) &
+					SROM11_PAPDCAP_MASK);
+			}
+			if ((p = find_pattern(argv, "tworangetssi5g", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_TWORANGETSSI_SHIFT) &
+					SROM11_TWORANGETSSI_MASK);
+			}
+			if ((p = find_pattern(argv, "pdgain5g", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_PDGAIN_SHIFT) &
+					SROM11_PDGAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "epagain5g", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_EPAGAIN_SHIFT) &
+					SROM11_EPAGAIN_MASK);
+			}
+			if ((p = find_pattern(argv, "tssiposslope5g", &val))) {
+				found = TRUE;
+				fem_cfg2 |= ((val << SROM11_TSSIPOSSLOPE_SHIFT) &
+					SROM11_TSSIPOSSLOPE_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(fem_cfg1 & 0xff);
+				b[cnt++] = (uint8)((fem_cfg1 >> 8) & 0xff);
+				b[cnt++] = (uint8)(fem_cfg2 & 0xff);
+				b[cnt++] = (uint8)((fem_cfg2 >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_ACRXGAINS_C0) {
+			bool found = FALSE;
+			uint16	rxgains = 0, rxgains1 = 0;
+
+			if ((p = find_pattern(argv, "rxgains5gtrelnabypa0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gtrisoa0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRISOA_SHIFT) &
+					SROM11_RXGAINS5GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gelnagaina0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrelnabypa0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS2GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrisoa0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRISOA_SHIFT) &
+					SROM11_RXGAINS2GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gelnagaina0", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS2GELNAGAINA_MASK);
+			}
+
+			if ((p = find_pattern(argv, "rxgains5ghtrelnabypa0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GHTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghtrisoa0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRISOA_SHIFT) &
+					SROM11_RXGAINS5GHTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghelnagaina0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GHELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrelnabypa0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GMTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrisoa0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRISOA_SHIFT) &
+					SROM11_RXGAINS5GMTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmelnagaina0", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GMELNAGAINA_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(rxgains & 0xff);
+				b[cnt++] = (uint8)((rxgains >> 8) & 0xff);
+				b[cnt++] = (uint8)(rxgains1 & 0xff);
+				b[cnt++] = (uint8)((rxgains1 >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_ACRXGAINS_C1) {
+			bool found = FALSE;
+			uint16	rxgains = 0, rxgains1 = 0;
+
+			if ((p = find_pattern(argv, "rxgains5gtrelnabypa1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gtrisoa1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRISOA_SHIFT) &
+					SROM11_RXGAINS5GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gelnagaina1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrelnabypa1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS2GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrisoa1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRISOA_SHIFT) &
+					SROM11_RXGAINS2GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gelnagaina1", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS2GELNAGAINA_MASK);
+			}
+
+			if ((p = find_pattern(argv, "rxgains5ghtrelnabypa1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GHTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghtrisoa1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRISOA_SHIFT) &
+					SROM11_RXGAINS5GHTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghelnagaina1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GHELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrelnabypa1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GMTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrisoa1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRISOA_SHIFT) &
+					SROM11_RXGAINS5GMTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmelnagaina1", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GMELNAGAINA_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(rxgains & 0xff);
+				b[cnt++] = (uint8)((rxgains >> 8) & 0xff);
+				b[cnt++] = (uint8)(rxgains1 & 0xff);
+				b[cnt++] = (uint8)((rxgains1 >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_ACRXGAINS_C2) {
+			bool found = FALSE;
+			uint16	rxgains = 0, rxgains1 = 0;
+
+			if ((p = find_pattern(argv, "rxgains5gtrelnabypa2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gtrisoa2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GTRISOA_SHIFT) &
+					SROM11_RXGAINS5GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gelnagaina2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS5GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrelnabypa2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS2GTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gtrisoa2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GTRISOA_SHIFT) &
+					SROM11_RXGAINS2GTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains2gelnagaina2", &val))) {
+				found = TRUE;
+				rxgains |= ((val << SROM11_RXGAINS2GELNAGAINA_SHIFT) &
+					SROM11_RXGAINS2GELNAGAINA_MASK);
+			}
+
+			if ((p = find_pattern(argv, "rxgains5ghtrelnabypa2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GHTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghtrisoa2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHTRISOA_SHIFT) &
+					SROM11_RXGAINS5GHTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5ghelnagaina2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GHELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GHELNAGAINA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrelnabypa2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRELNABYPA_SHIFT) &
+					SROM11_RXGAINS5GMTRELNABYPA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmtrisoa2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMTRISOA_SHIFT) &
+					SROM11_RXGAINS5GMTRISOA_MASK);
+			}
+			if ((p = find_pattern(argv, "rxgains5gmelnagaina2", &val))) {
+				found = TRUE;
+				rxgains1 |= ((val << SROM11_RXGAINS5GMELNAGAINA_SHIFT) &
+					SROM11_RXGAINS5GMELNAGAINA_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(rxgains & 0xff);
+				b[cnt++] = (uint8)((rxgains >> 8) & 0xff);
+				b[cnt++] = (uint8)(rxgains1 & 0xff);
+				b[cnt++] = (uint8)((rxgains1 >> 8) & 0xff);
+			}
+		} else if (srv->tag == HNBU_PDOFF_2G) {
+			bool	found = FALSE;
+			uint16	tmppdoff2g = 0;
+
+			if ((p = find_pattern(argv, "pdoffset2g40ma0", &val))) {
+				found = TRUE;
+				tmppdoff2g |= ((val << SROM11_PDOFF_2G_40M_A0_SHIFT) &
+					SROM11_PDOFF_2G_40M_A0_MASK);
+			}
+
+			if ((p = find_pattern(argv, "pdoffset2g40ma1", &val))) {
+				found = TRUE;
+				tmppdoff2g |= ((val << SROM11_PDOFF_2G_40M_A1_SHIFT) &
+					SROM11_PDOFF_2G_40M_A1_MASK);
+			}
+
+			if ((p = find_pattern(argv, "pdoffset2g40ma2", &val))) {
+				found = TRUE;
+				tmppdoff2g |= ((val << SROM11_PDOFF_2G_40M_A2_SHIFT) &
+					SROM11_PDOFF_2G_40M_A2_MASK);
+			}
+
+			if ((p = find_pattern(argv, "pdoffset2g40mvalid", &val))) {
+				found = TRUE;
+				tmppdoff2g |= ((val << SROM11_PDOFF_2G_40M_VALID_SHIFT) &
+					SROM11_PDOFF_2G_40M_VALID_MASK);
+			}
+
+			if (found) {
+				newtuple(&b[cnt], &cnt, CISTPL_BRCM_HNBU, srv);
+				b[cnt++] = (uint8)(tmppdoff2g & 0xff);
+				b[cnt++] = (uint8)((tmppdoff2g >> 8) & 0xff);
+			}
+		} else {	/* All other tuples */
+			int	found = FALSE, varlen = 0;
+			char	*cur = &b[cnt];
+			uint	newtp = TRUE;
+
+			/* example srv->params contents: "1aa2g 1aa5g" */
+			par = malloc(strlen(srv->params)+1);
+			if (!par)
+				return BCME_NOMEM;
+
+			/* Walk through each parameters in one tuple */
+			strcpy(par, srv->params);
+
+			cpar = strtok (par, delimit);	/* current param */
+			while (cpar) {
+				int	array_sz = 1;
+				val = 0;
+
+				/* Fill the CIS tuple to b but don't commit cnt yet */
+				if (newtp) {
+					newtuple(cur, NULL, CISTPL_BRCM_HNBU, srv);
+					cur += 3;
+					newtp = FALSE;
+				}
+
+				/* the first byte of each parameter indicates its length */
+				varlen = (*cpar++) - '0';
+
+				/* parse array size if any */
+				if (*cpar == '*') {
+					array_sz = 0;
+					while (((*++cpar) >= '0') && (*cpar <= '9'))
+						array_sz = (array_sz * 10) + *cpar - '0';
+				}
+
+				/* Find the parameter in the input argument list */
+				if ((p = find_pattern(argv, cpar, &val)))
+					found = TRUE;
+				else
+					val = 0;
+
+				while (found && array_sz--) {
+					*cur++ = (uint8)(val & 0xff);
+					if (varlen >= 2)
+						*cur++ = (uint8)((val >> 8) & 0xff);
+					if (varlen >= 4) {
+						*cur++ = (uint8)((val >> 16) & 0xff);
+						*cur++ = (uint8)((val >> 24) & 0xff);
+					}
+
+					/* skip the "," if more array elements */
+					if (p && array_sz) {
+						char *q = NULL;
+
+						p = strstr (p, ",");	/* current param */
+						if (p) {
+							p++;
+							val = strtoul(p, &q, strncmp(p, "0x", 2) ?
+								10 : 16);
+						} else {
+							printf("Input array size error!");
+							free(par);
+							return BCME_BADARG;
+						}
+					}
+				}
+
+				/* move to the next parameter string */
+				cpar = strtok(NULL, delimit);
+			}
+			free(par);
+
+			/* commit the tuple if its valid */
+			if (found)
+				cnt += (cur - &b[cnt]);
+		}
+
+		srv++;
+	}
+
+	printf("sromrev %d buffer size %d bytes:\n", sromrev, cnt);
+	for (i = 0; i < cnt; i++) {
+		printf("0x%.02x ", b[i] & 0xff);
+		if (i%8 == 7)	printf("\n");
+	}
+	printf("\n");
+
+	return cnt;
+}
+
+static const sromvar_t *
+srvlookup(const sromvar_t *tab, char *name, int nlen, int sromrev)
+{
+	uint32 srrmask;
+	const sromvar_t *srv = tab;
+
+	srrmask = 1 << sromrev;
+
+	while (srv->name) {
+		if ((strncmp(name, srv->name, nlen) == 0) &&
+		    ((srrmask & srv->revmask) != 0))
+		    break;
+		while (srv->flags & SRFL_MORE)
+			srv++;
+		srv++;
+	}
+
+	return srv;
+}
+#endif	
+
+/** read/write caller supplied NVRAM variables in OTP or SROM */
+static int
+wlu_srvar(void *wl, cmd_t *cmd, char **argv)
+{
+#if	defined(DONGLEBUILD)
+	return 0;
+#else
+	int ret, nw, nlen, ro, co, wr, sromrev, shift = 0;
+	bool otp = FALSE;
+	uint32 val32 = 0;
+	char *name, *p, *newval;
+	const sromvar_t *srv;
+	uint16 w, *words = (uint16 *)&buf[8];
+	srom_rw_t   *srt;
+	struct ether_addr ea;
+
+	ro = !strcmp(*argv, "rdvar");
+	wr = !strcmp(*argv, "wrvar");
+	co = !strcmp(*argv, "cisconvert");
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	/* Query the driver on where the cis comes from: OTP or SROM */
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "cis_source");
+	ret = wl_get(wl, WLC_GET_VAR, buf, strlen(buf)+1);
+	if (ret < 0) {
+		; /* printf("Error %x: cannot get cis_source\n", ret); */
+	}
+
+	if (buf[0] == WLC_CIS_OTP)
+		otp = TRUE;
+	if (otp && ro) {
+		/* read caller supplied nvram variable from driver */
+		wl_nvget(wl, cmd, --argv);
+		return ret;
+	}
+
+	/*
+	 * Before OTP can be written, the caller supplied nvram string has to be converted into a
+	 * list of CIS tuples. This CIS format is SROM rev dependent.
+	 */
+	if ((otp && wr) || co) {
+		int cnt = 0, err = 0;
+		uint sromrev = 8;
+		void *p = NULL;
+
+		/* Read all nvram variables from driver and retrieve srom revision from that */
+		if ((err = wlu_var_getbuf(wl, "nvram_dump", NULL, 0, &p)) < 0) {
+			err = wlu_get(wl, WLC_NVRAM_DUMP, &buf[0], WLC_IOCTL_MAXLEN);
+		}
+
+		if (err) {
+			printf("Fail to get sromrev from nvram file!\n");
+			return err;
+		}
+
+		if ((p = strstr(p, "sromrev"))) {
+			char *q = NULL;
+
+			p = (void*)((char*)p + 8);
+			/* for OTP, its either srom rev 10 or 16 */
+			sromrev = strtoul(p, &q, strncmp(p, "0x", 2) ? 10 : 16);
+		} else {
+			printf("sromrev not defined in nvram file!\n");
+			return BCME_ERROR;
+		}
+
+		/* convert caller supplied nvram string (in argv) into a list of tuples (in buf) */
+		if ((cnt = parsecis(buf, argv, sromrev)) <= 0) {
+			printf("CIS parse failure!\n");
+			return BCME_ERROR;
+		}
+
+		/* leave an empty srom_rw_t at the front for backward
+		 * compatibility
+		 */
+		if (!co) {
+			/*
+			 * Pass the CIS containing caller supplied nvram vars to driver so driver
+			 * can write OTP. Driver decides which OTP region (hardware,software) will
+			 * be written, depending on chip type and bus type.
+			 */
+			ret = wlu_iovar_set(wl, "cisvar", buf, cnt); /* IOV_BMAC_CISVAR */
+		}
+		return ret;
+	}
+
+	/* First read the srom and find out the sromrev */
+	srt = (srom_rw_t *)buf;
+	srt->byteoff = htod32(0);
+	srt->nbytes = htod32(2 * SROM4_WORDS);
+
+	if (cmd->get < 0)
+		return -1;
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	if (words[SROM11_SIGN] == SROM11_SIGNATURE) {
+		sromrev = 11;
+
+		srt->byteoff = htod32(0);
+		srt->nbytes = htod32(2 * SROM11_WORDS);
+
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+
+	} else if (words[SROM11_SIGN] == SROM12_SIGNATURE) {
+		sromrev = 12;
+
+		srt->byteoff = htod32(0);
+		srt->nbytes = htod32(2 * SROM12_WORDS);
+
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+	} else if (words[SROM11_SIGN] == SROM13_SIGNATURE) {
+		sromrev = 13;
+
+		srt->byteoff = htod32(0);
+		srt->nbytes = htod32(2 * SROM13_WORDS);
+
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+	} else if (words[SROM11_SIGN] == SROM15_SIGNATURE) {
+		sromrev = 15;
+		srt->byteoff = htod32(0);
+		srt->nbytes = htod32(2 * SROM15_WORDS);
+
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+	} else {
+		if ((words[SROM4_SIGN] != SROM4_SIGNATURE) &&
+		    (words[SROM8_SIGN] != SROM4_SIGNATURE))
+			nw = SROM_CRCREV;
+		else
+			nw = SROM4_CRCREV;
+		sromrev = words[nw] & 0xff;
+	}
+
+	if ((sromrev < 2) || (sromrev > SROM_MAXREV)) {
+		return BCME_ERROR;
+	}
+
+	nw = 0;
+	while ((name = *argv++) != NULL) {
+		int off, off_base;
+
+		newval = strchr(name, '=');
+		if (newval)
+			*newval++ = '\0';
+		nlen = strlen(name);
+		if ((nlen == 0) || (nlen > 32)) {
+			printf("Bad variable name: %s\n", name);
+			continue;
+		}
+		off = 0;
+		if (sromrev == 15)
+			 srv = srvlookup(pci_srom15vars, name, nlen + 1, sromrev);
+		else
+			srv = srvlookup(pci_sromvars, name, nlen + 1, sromrev);
+
+		if (srv->name == NULL) {
+			int path;
+			if (sromrev == 15) {
+				printf("Variable %s does not exist in sromrev %d\n", name, sromrev);
+				return BCME_ERROR;
+			 }
+			srv = srvlookup(perpath_pci_sromvars, name, nlen - 1, sromrev);
+			path = name[nlen - 1] - '0';
+			if ((srv->name == NULL) || (path < 0) || (path >= MAX_PATH_SROM)) {
+				printf("Variable %s does not exist in sromrev %d\n",
+				       name, sromrev);
+				continue;
+			}
+			if (sromrev == 13) {
+				if (path == 0) {
+					off = SROM13_PATH0;
+				} else if (path == 1) {
+					off = SROM13_PATH1;
+				} else if (path == 2) {
+					off = SROM13_PATH2;
+				} else if (path == 3) {
+					off = SROM13_PATH3;
+				}
+			} else if (sromrev == 12) {
+				if (path == 0) {
+					off = SROM12_PATH0;
+				} else if (path == 1) {
+					off = SROM12_PATH1;
+				} else if (path == 2) {
+					off = SROM12_PATH2;
+				}
+			} else if (sromrev == 11) {
+				if (path == 0) {
+					off = SROM11_PATH0;
+				} else if (path == 1) {
+					off = SROM11_PATH1;
+				} else if (path == 2) {
+					off = SROM11_PATH2;
+				}
+			} else if (sromrev >= 8) {
+				if (path == 0) {
+					off = SROM8_PATH0;
+				} else if (path == 1) {
+					off = SROM8_PATH1;
+				} else if (path == 2) {
+					off = SROM8_PATH2;
+				} else if (path == 3) {
+					off = SROM8_PATH3;
+				}
+			} else
+				off = (path == 0) ? SROM4_PATH0 : SROM4_PATH1;
+		}
+		off_base = off;
+		off += srv->off;
+
+		if (ro) {
+			/* This code is cheating a bit: it knows that SRFL_ETHADDR means three
+			 * whole words, and SRFL_MORE means 2 whole words (i.e. the masks for
+			 * them are all 0xffff).
+			 */
+			if (srv->flags & SRFL_ETHADDR) {
+				w = words[off];
+				ea.octet[0] = w >> 8;
+				ea.octet[1] = w & 0xff;
+				w = words[off + 1];
+				ea.octet[2] = w >> 8;
+				ea.octet[3] = w & 0xff;
+				w = words[off + 2];
+				ea.octet[4] = w >> 8;
+				ea.octet[5] = w & 0xff;
+			} else if (srv->flags & SRFL_MORE) {
+				val32 = words[off];
+				val32 |= words[srv[1].off] << 16;
+			} else {
+				shift = ffs(srv->mask) - 1;
+				val32 = (words[off] & srv->mask) >> shift;
+			}
+
+			/* OK, print it */
+			if (srv->flags & SRFL_ETHADDR)
+				printf("%s=%s", name, wl_ether_etoa(&ea));
+			else if (srv->flags & SRFL_PRHEX)
+				printf("%s=0x%x", name, val32);
+			else if (srv->flags & SRFL_PRSIGN)
+				printf("%s=%d", name, val32);
+			else
+				printf("%s=%u", name, val32);
+
+			if (srv->flags & SRFL_ARRAY) {
+				do {
+					srv ++;
+					off = off_base + srv->off;
+
+					if (srv->name == NULL)
+						break;
+
+					shift = ffs(srv->mask) - 1;
+					val32 = (words[off] & srv->mask) >> shift;
+
+					if (srv->flags & SRFL_PRHEX)
+						printf(",0x%x", val32);
+					else if (srv->flags & SRFL_PRSIGN)
+						printf(",%d", val32);
+					else
+						printf(",%u", val32);
+				} while (srv->flags & SRFL_ARRAY);
+			}
+			printf("\n");
+
+		} else {	/* wr */
+
+			/* Make the change in the image we read */
+			if (!newval) {
+				printf("wrvar missing value to write for variable %s\n", name);
+				ro = 1;
+				break;
+			}
+
+			/* Cheating again as above */
+			if (srv->flags & SRFL_ETHADDR) {
+				if (!wl_ether_atoe(newval, &ea)) {
+					printf("Argument does not look like a MAC address: %s\n",
+						newval);
+					ret = BCME_USAGE_ERROR;
+					ro = 1;
+					break;
+				}
+				words[off] = (ea.octet[0] << 8) | ea.octet[1];
+				words[off + 1] = (ea.octet[2] << 8) | ea.octet[3];
+				words[off + 2] = (ea.octet[4] << 8) | ea.octet[5];
+				off += 2;
+			} else {
+				val32 = strtoul(newval, &p, 0);
+				if (p == newval) {
+					printf("Bad value: %s for variable %s\n", newval, name);
+					ro = 1;
+					break;
+				}
+
+				if (srv->flags & SRFL_MORE) {
+					words[off] = val32 & 0xffff;
+					words[off + 1] = val32 >> 16;
+					off++;
+				} else {
+					shift = ffs(srv->mask) - 1;
+					words[off] = (((val32 << shift) & srv->mask) |
+						(words[off] & ~srv->mask));
+
+					if (srv->flags & SRFL_ARRAY) {
+						do {
+							srv ++;
+							off = off_base + srv->off;
+
+							if (srv->name == NULL)
+								break;
+
+							newval = p + 1;
+							val32 = strtoul(newval, &p, 0);
+							if (p == newval) {
+								printf(
+								 "Bad value: %s for variable %s\n",
+								 newval, name);
+								ro = 1;
+								break;
+							}
+
+							shift = ffs(srv->mask) - 1;
+							words[off] =
+							 (((val32 << shift) & srv->mask) |
+							 (words[off] & ~srv->mask));
+						} while (srv->flags & SRFL_ARRAY);
+					}
+				}
+			}
+
+			if (off > nw)
+				nw = off;
+		}
+	}
+
+	if (!ro) {
+		/* Now write all the changes */
+		nw++;
+		srt->byteoff = 0;
+		srt->nbytes = htod32(2 * nw);
+		ret = wlu_set(wl, cmd->set, buf, (2 * nw) + 8);
+		if (ret < 0)
+			printf("Error %d writing the srom\n", ret);
+	}
+
+	return ret;
+#endif 
+}
+
+/* All 32bits are used. Please populate wl_msgs2[] with further entries */
+static dbg_msg_t wl_msgs[] = {
+	{WL_ERROR_VAL, 	"error"},
+	{WL_ERROR_VAL, 	"err"},
+	{WL_TRACE_VAL, 	"trace"},
+	{WL_PRHDRS_VAL,	"prhdrs"},
+	{WL_PRPKT_VAL,	"prpkt"},
+	{WL_INFORM_VAL,	"inform"},
+	{WL_INFORM_VAL,	"info"},
+	{WL_INFORM_VAL,	"inf"},
+	{WL_TMP_VAL,	"tmp"},
+	{WL_OID_VAL,	"oid"},
+	{WL_RATE_VAL,	"rate"},
+	{WL_ASSOC_VAL,	"assoc"},
+	{WL_ASSOC_VAL,	"as"},
+	{WL_PRUSR_VAL,	"prusr"},
+	{WL_PS_VAL,	"ps"},
+	{WL_MODE_SWITCH_VAL,	"modesw"},
+	{WL_PORT_VAL,	"port"},
+	{WL_DUAL_VAL,	"dual"},
+	{WL_WSEC_VAL,	"wsec"},
+	{WL_WSEC_DUMP_VAL,	"wsec_dump"},
+	{WL_LOG_VAL,	"log"},
+	{WL_BCNTRIM_VAL,	"bcntrim"},
+	{WL_PFN_VAL,	"pfn"},
+	{WL_REGULATORY_VAL,	"regulatory"},
+	{WL_MPC_VAL,	"mpc"},
+	{WL_APSTA_VAL,	"apsta"},
+	{WL_DFS_VAL,	"dfs"},
+	{WL_MUMIMO_VAL, "mumimo"},
+	{WL_MUMIMO_VAL, "mu"},
+	{WL_MBSS_VAL,	"mbss"},
+	{WL_CAC_VAL,	"cac"},
+	{WL_AMSDU_VAL,	"amsdu"},
+	{WL_AMPDU_VAL,	"ampdu"},
+	{WL_FFPLD_VAL,  "ffpld"},
+	{0,		NULL}
+};
+
+/* msglevels which use wl_msg_level2 should go here */
+static dbg_msg_t wl_msgs2[] = {
+	{WL_SCAN_VAL,	"scan"},
+	{WL_WOWL_VAL,	"wowl"},
+	{WL_COEX_VAL,	"coex"},
+	{WL_RTDC_VAL,	"rtdc"},
+	{WL_PROTO_VAL,	"proto"},
+	{WL_CHANINT_VAL,	"chanim"},
+	{WL_WMF_VAL, "wmf"},
+#ifdef WLP2P
+	{WL_P2P_VAL,	"p2p"},
+#endif
+	{WL_ITFR_VAL,	"itfr"},
+#ifdef WLMCHAN
+	{WL_MCHAN_VAL,	"mchan"},
+#endif
+#ifdef WLTDLS
+	{WL_TDLS_VAL, "tdls"},
+#endif
+	{WL_PSTA_VAL,	"psta"},
+	{WL_MCNX_VAL,	"mcnx"},
+	{WL_PROT_VAL,	"prot"},
+	{WL_TBTT_VAL,	"tbtt"},
+	{WL_TIMESTAMP_VAL, "time"},
+	{WL_PWRSEL_VAL, "lpc"},
+	{WL_TSO_VAL,	"tso"},
+	{WL_MQ_VAL,	"mq"},
+	{WL_TIMESTAMP_VAL, "chanlog"},
+#ifdef WLP2PO
+	{WL_P2PO_VAL, "p2po"},
+#endif
+	{WL_WNM_VAL, "wnm"},
+	{WL_TXBF_VAL, "txbf"},
+	{WL_PCIE_VAL, "pcie"},
+	{WL_MESH_VAL,	"mesh"},
+	{WL_NATOE_VAL,	"natoe"},
+	{0,		NULL}
+};
+
+static int
+wl_msglevel(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint hval = 0, len, val = 0, found, last_val = 0, msglevel = 0, msglevel2_add = 0;
+	uint msglevel2_del = 0, msglevel_add = 0, msglevel_del = 0, supported = 1;
+	char *endptr = NULL;
+	dbg_msg_t *dbg_msg = wl_msgs, *dbg_msg2 = wl_msgs2;
+	void *ptr = NULL;
+	struct wl_msglevel2 msglevel64, *reply;
+	const char *cmdname = "msglevel";
+	char c[32] = "0x";
+
+	UNUSED_PARAMETER(cmd);
+
+	/* but preseve older IOCTL call for older drivers */
+	if ((ret = wlu_var_getbuf_sm(wl, cmdname, &msglevel64, sizeof(msglevel64), &ptr) < 0)) {
+		if ((ret = wlu_get(wl, WLC_GET_MSGLEVEL, &msglevel, sizeof(int))) < 0)
+			return (ret);
+		supported = 0;
+		msglevel = dtoh32(msglevel);
+		if (!*++argv) {
+			printf("0x%x ", msglevel);
+			for (i = 0; (val = dbg_msg[i].value); i++) {
+			if ((msglevel & val) && (val != last_val))
+				printf(" %s", dbg_msg[i].string);
+			last_val = val;
+			}
+		printf("\n");
+		return (0);
+		}
+		while (*argv) {
+			char *s = *argv;
+			if (*s == '+' || *s == '-')
+				s++;
+			else
+				msglevel_del = ~0; /* make the whole list absolute */
+			val = strtoul(s, &endptr, 0);
+			if (val == 0xFFFFFFFF) {
+				fprintf(stderr,
+					"Bits >32 are not supported on this driver version\n");
+				val = 1;
+			}
+			/* not an integer if not all the string was parsed by strtoul */
+			if (*endptr != '\0') {
+				for (i = 0; (val = dbg_msg[i].value); i++)
+					if (stricmp(dbg_msg[i].string, s) == 0)
+						break;
+					if (!val)
+						goto usage;
+			}
+			if (**argv == '-')
+				msglevel_del |= val;
+			else
+				msglevel_add |= val;
+			++argv;
+		}
+		msglevel &= ~msglevel_del;
+		msglevel |= msglevel_add;
+		msglevel = htod32(msglevel);
+		return (wlu_set(wl, WLC_SET_MSGLEVEL, &msglevel, sizeof(int)));
+	} else { /* 64bit message level */
+		reply = (struct wl_msglevel2 *)ptr;
+		reply->low = dtoh32(reply->low);
+		reply->high = dtoh32(reply->high);
+		if (!*++argv) {
+			if (reply->high != 0)
+				printf("0x%x%08x", reply->high, reply->low);
+			else
+				printf("0x%x ", reply->low);
+			for (i = 0; (val = dbg_msg2[i].value); i++) {
+				if (((reply->high & val)) && (val != last_val))
+					printf(" %s", dbg_msg2[i].string);
+				last_val = val;
+				}
+			last_val = 0;
+			for (i = 0; (val = dbg_msg[i].value); i++) {
+				if (((reply->low & val)) && (val != last_val))
+					printf(" %s", dbg_msg[i].string);
+				last_val = val;
+			}
+			printf("\n");
+			return (0);
+		}
+		while (*argv) {
+			char* s = *argv;
+			char t[32];
+			found = 0;
+			if (*s == '+' || *s == '-')
+				s++;
+			else {
+				msglevel_del = ~0;	/* make the whole list absolute */
+				msglevel2_del = ~0;
+			}
+			val = strtoul(s, &endptr, 0);
+			if (val == 0xFFFFFFFF){ /* Assume >32 bit hex passed in */
+				if (!(*s == '0' && *(s+1) == 'x')) {
+					fprintf(stderr,
+					"Msg bits >32 take only numerical input in hex\n");
+					val = 0;
+				} else {
+					len = strlen(s);
+					hval = strtoul(strncpy(t, s, len-8), &endptr, 0);
+					*endptr = 0;
+					s = s+strlen(t);
+					s = strcat(c, s);
+					val = strtoul(s, &endptr, 0);
+					if (hval == 0xFFFFFFFF) {
+						fprintf(stderr, "Invalid entry for msglevel\n");
+						hval = 0;
+						val = 0;
+					}
+				}
+			}
+			if (*endptr != '\0') {
+				for (i = 0; (val = dbg_msg[i].value); i++) {
+					if (stricmp(dbg_msg[i].string, s) == 0) {
+						found = 1;
+						break;
+					}
+				}
+				if (!found) {
+				for (i = 0; (hval = dbg_msg2[i].value); i++)
+					if (stricmp(dbg_msg2[i].string, s) == 0)
+						break;
+				}
+				if (!val && !hval)
+				      goto usage;
+		      }
+		      if (**argv == '-') {
+				msglevel_del |= val;
+				if (!found)
+					msglevel2_del |= hval;
+		      }
+		      else {
+				msglevel_add |= val;
+				if (!found)
+					msglevel2_add |= hval;
+		      }
+		      ++argv;
+		}
+		reply->low &= ~msglevel_del;
+		reply->high &= ~msglevel2_del;
+		reply->low |= msglevel_add;
+		reply->high |= msglevel2_add;
+		reply->low = htod32(reply->low);
+		reply->high = htod32(reply->high);
+		msglevel64.low = reply->low;
+		msglevel64.high = reply->high;
+		return (wlu_var_setbuf(wl, cmdname, &msglevel64, sizeof(msglevel64)));
+	}
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+
+	for (i = 0; (val = dbg_msg[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, dbg_msg[i].string);
+		else
+			fprintf(stderr, ", %s", dbg_msg[i].string);
+		last_val = val;
+	}
+	if (supported) {
+		for (i = 0; (val = dbg_msg2[i].value); i++) {
+			if (val != last_val)
+				fprintf(stderr, "\n0x%x00000000 %s", val, dbg_msg2[i].string);
+			else
+				fprintf(stderr, ", %s", dbg_msg2[i].string);
+			last_val = val;
+		}
+	}
+	fprintf(stderr, "\n");
+	return 0;
+}
+
+struct d11_mcs_rate_info {
+	uint8 constellation_bits;
+	uint8 coding_q;
+	uint8 coding_d;
+};
+
+static const struct d11_mcs_rate_info wlu_mcs_info[] = {
+	{ 1, 1, 2 }, /* MCS  0: MOD: BPSK,   CR 1/2 */
+	{ 2, 1, 2 }, /* MCS  1: MOD: QPSK,   CR 1/2 */
+	{ 2, 3, 4 }, /* MCS  2: MOD: QPSK,   CR 3/4 */
+	{ 4, 1, 2 }, /* MCS  3: MOD: 16QAM,  CR 1/2 */
+	{ 4, 3, 4 }, /* MCS  4: MOD: 16QAM,  CR 3/4 */
+	{ 6, 2, 3 }, /* MCS  5: MOD: 64QAM,  CR 2/3 */
+	{ 6, 3, 4 }, /* MCS  6: MOD: 64QAM,  CR 3/4 */
+	{ 6, 5, 6 }, /* MCS  7: MOD: 64QAM,  CR 5/6 */
+	{ 8, 3, 4 }, /* MCS  8: MOD: 256QAM, CR 3/4 */
+	{ 8, 5, 6 }  /* MCS  9: MOD: 256QAM, CR 5/6 */
+};
+
+static uint
+wl_mcs2rate(uint mcs, uint nss, uint bw, int sgi)
+{
+	const int ksps = 250; /* kilo symbols per sec, 4 us sym */
+	const int Nsd_20MHz = 52;
+	const int Nsd_40MHz = 108;
+	const int Nsd_80MHz = 234;
+	const int Nsd_160MHz = 468;
+	uint rate;
+
+	if (mcs == 32) {
+		/* just return fixed values for mcs32 instead of trying to parametrize */
+		rate = (sgi == 0) ? 6000 : 6700;
+	} else if (mcs <= 9) {
+		/* This calculation works for 11n HT and 11ac VHT if the HT mcs values
+		 * are decomposed into a base MCS = MCS % 8, and Nss = 1 + MCS / 8.
+		 * That is, HT MCS 23 is a base MCS = 7, Nss = 3
+		 */
+
+		/* find the number of complex numbers per symbol */
+		if (bw == 20) {
+			rate = Nsd_20MHz;
+		} else if (bw == 40) {
+			rate = Nsd_40MHz;
+		} else if (bw == 80) {
+			rate = Nsd_80MHz;
+		} else if (bw == 160) {
+			rate = Nsd_160MHz;
+		} else {
+			rate = 1;
+		}
+
+		/* multiply by bits per number from the constellation in use */
+		rate = rate * wlu_mcs_info[mcs].constellation_bits;
+
+		/* adjust for the number of spatial streams */
+		rate = rate * nss;
+
+		/* adjust for the coding rate given as a quotient and divisor */
+		rate = (rate * wlu_mcs_info[mcs].coding_q) / wlu_mcs_info[mcs].coding_d;
+
+		/* multiply by Kilo symbols per sec to get Kbps */
+		rate = rate * ksps;
+
+		/* adjust the symbols per sec for SGI
+		 * symbol duration is 4 us without SGI, and 3.6 us with SGI,
+		 * so ratio is 10 / 9
+		 */
+		if (sgi) {
+			/* add 4 for rounding of division by 9 */
+			rate = ((rate * 10) + 4) / 9;
+		}
+	} else {
+		rate = 0;
+	}
+
+	return rate;
+}
+
+/* take a wl_ratespec arg and return phy rate in 500Kbps units */
+static int
+wl_ratespec2rate(uint32 rspec)
+{
+	const char* fn_name = "wl_ratespec2rate";
+	int rate = -1;
+	int sgi = ((rspec & WL_RSPEC_SGI) != 0);
+
+	if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_RATE) {
+		rate = (rspec & WL_RSPEC_RATE_MASK);
+	} else if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_HT) {
+		uint mcs = (rspec & WL_RSPEC_RATE_MASK);
+
+		if (mcs > 32) {
+			fprintf(stderr, "%s: MCS %u out of range (>32) in ratespec 0x%X\n",
+				fn_name, mcs, rspec);
+		} else if (mcs == 32) {
+			rate = wl_mcs2rate(mcs, 1, 40, sgi) / 500;
+		} else {
+			uint nss = 1 + (mcs / 8);
+			mcs = mcs % 8;
+
+			rate = wl_mcs2rate(mcs, nss, 20, sgi) / 500;
+		}
+	} else if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_VHT) {
+		uint mcs = (rspec & WL_RSPEC_VHT_MCS_MASK);
+		uint nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
+
+		rate = wl_mcs2rate(mcs, nss, 20, sgi) / 500;
+	} else {
+		fprintf(stderr, "%s: expected rate encoding in ratespec 0x%X\n",
+			fn_name, (uint)rspec);
+	}
+
+	return rate;
+}
+
+/* take rate arg in units of 500Kbits/s and print it in units of Mbit/s */
+static void
+wl_printrate(int val)
+{
+	char rate_buf[32];
+
+	printf("%s\n", rate_int2string(rate_buf, val));
+}
+
+/* convert rate string in Mbit/s format, like "11", "5.5", to internal 500 Kbit/s units */
+int
+rate_string2int(char *s)
+{
+	if (!stricmp(s, "-1"))
+		return (0);
+	if (!stricmp(s, "5.5"))
+		return (11);
+	return (atoi(s) * 2);
+}
+
+/* convert rate internal 500 Kbits/s units to string in Mbits/s format, like "11", "5.5" */
+char*
+rate_int2string(char *rate_buf, int val)
+{
+	if ((val == -1) || (val == 0))
+		sprintf(rate_buf, "auto");
+	else
+		sprintf(rate_buf, "%d%s Mbps", (val / 2), (val & 1) ? ".5" : "");
+	return (rate_buf);
+}
+
+/*
+ * Format a ratespec for output of any of the wl_rate() iovars
+ */
+char*
+wl_rate_print(char *rate_buf, uint32 rspec)
+{
+	uint encode, rate, txexp, bw_val;
+	const char* stbc;
+	const char* ldpc;
+	const char* sgi;
+	const char* bw;
+
+	encode = (rspec & WL_RSPEC_ENCODING_MASK);
+	rate = (rspec & WL_RSPEC_RATE_MASK);
+	txexp = (rspec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT;
+	bw_val = (rspec & WL_RSPEC_BW_MASK);
+	stbc  = ((rspec & WL_RSPEC_STBC) != 0) ? " stbc" : "";
+	ldpc  = ((rspec & WL_RSPEC_LDPC) != 0) ? " ldpc" : "";
+	sgi   = ((rspec & WL_RSPEC_SGI)  != 0) ? " sgi"  : "";
+
+	if (bw_val == WL_RSPEC_BW_UNSPECIFIED) {
+		bw = "auto";
+	} else if (bw_val == WL_RSPEC_BW_20MHZ) {
+		bw = "20";
+	} else if (bw_val == WL_RSPEC_BW_40MHZ) {
+		bw = "40";
+	} else if (bw_val == WL_RSPEC_BW_80MHZ) {
+		bw = "80";
+	} else if (bw_val == WL_RSPEC_BW_160MHZ) {
+		bw = "160";
+	} else if (bw_val == WL_RSPEC_BW_10MHZ) {
+		bw = "10";
+	} else if (bw_val == WL_RSPEC_BW_5MHZ) {
+		bw = "5";
+	} else if (bw_val == WL_RSPEC_BW_2P5MHZ) {
+		bw = "2.5";
+	} else {
+		bw = "???";
+	}
+
+	if ((rspec & ~WL_RSPEC_TXEXP_MASK) == 0) { /* Ignore TxExpansion for NULL rspec check */
+		sprintf(rate_buf, "auto");
+	} else if (encode == WL_RSPEC_ENCODE_RATE) {
+		sprintf(rate_buf, "rate %d%s Mbps Tx Exp %d",
+			rate/2, (rate % 2)?".5":"", txexp);
+	} else if (encode == WL_RSPEC_ENCODE_HT) {
+		sprintf(rate_buf, "ht mcs %d Tx Exp %d BW %s%s%s%s",
+		        rate, txexp, bw, stbc, ldpc, sgi);
+	} else if (encode == WL_RSPEC_ENCODE_VHT) {
+		uint mcs = (rspec & WL_RSPEC_VHT_MCS_MASK);
+		uint Nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
+		sprintf(rate_buf, "vht mcs %d Nss %d Tx Exp %d BW %s%s%s%s",
+		        mcs, Nss, txexp, bw, stbc, ldpc, sgi);
+	} else {
+		sprintf(rate_buf, "<unknown encoding for ratespec 0x%08X>", rspec);
+	}
+
+	return rate_buf;
+}
+
+/* handles both "rate" and "mrate", which makes the flow a bit complex */
+static int
+wl_rate_mrate(void *wl, cmd_t *cmd, char **argv)
+{
+	const char* fn_name = "wl_rate_mrate";
+	int error;
+	int val;
+	int band;
+	int list[3];
+	char aname[sizeof("5g_mrate") + 1];
+	char bgname[sizeof("2g_mrate") + 1];
+	char *name;
+
+	sprintf(aname, "5g_%s", cmd->name);
+	sprintf(bgname, "2g_%s", cmd->name);
+
+	if ((error = wlu_get(wl, WLC_GET_BAND, &band, sizeof(uint))) < 0)
+		return error;
+	band = dtoh32(band);
+
+	if ((error = wlu_get(wl, WLC_GET_BANDLIST, list, sizeof(list))) < 0)
+		return error;
+	list[0] = dtoh32(list[0]);
+	list[1] = dtoh32(list[1]);
+	list[2] = dtoh32(list[2]);
+
+	if (!list[0])
+		return BCME_ERROR;
+	else if (list[0] > 2)
+		list[0] = 2;
+
+	/* toss the command name from the args */
+	argv++;
+
+	if ((!strcmp(cmd->name, "rate"))) {
+		/* it is "rate" */
+		if (!*argv) {
+			/* it is "rate" get. handle it here */
+			/* WLC_GET_RATE processing */
+			if ((error = wlu_get(wl, cmd->get, &val, sizeof(int))) < 0)
+				return error;
+
+			val = dtoh32(val);
+			wl_printrate(val);
+			return 0;
+		}
+	}
+
+	switch (band) {
+	case WLC_BAND_AUTO :
+		if (list[0] > 1) {
+			fprintf(stderr,
+			        "%s: driver band must be locked to %s %s, use %s/%s instead\n",
+			        fn_name, (*argv ? "set" : "get"), cmd->name,
+			        bgname, aname);
+			return BCME_BADARG;
+		} else if (list[1] == WLC_BAND_5G)
+			name = (char *)aname;
+		else if (list[1] == WLC_BAND_2G)
+			name = (char *)bgname;
+		else
+			return BCME_ERROR;
+
+		break;
+
+	case WLC_BAND_5G :
+		name = (char *)aname;
+		break;
+
+	case WLC_BAND_2G :
+		name = (char *)bgname;
+		break;
+
+	default :
+		return BCME_ERROR;
+	}
+
+	if (!*argv) {
+		/* it is "mrate" get */
+		if ((error = wlu_iovar_getint(wl, name, &val) < 0))
+			return error;
+
+		val = dtoh32(val);
+
+		if (ioctl_version == 1) {
+			wl_printrate(val);
+		} else {
+			wl_printrate(wl_ratespec2rate((uint32)val));
+		}
+	} else {
+		/* create the ioctl value based on the major ioctl version */
+		if (ioctl_version == 1) {
+			/* for ver=1 ioctl interfaces, override values for 2g_(m)rate/5g_(m)rate
+			 * are just given as 500 Kbps units
+			 */
+			val = rate_string2int(*argv);
+		} else {
+			/* for ver>1 ioctl interfaces, override values for 2g_(m)rate/5g_(m)rate
+			 * are a wl_ratespec of a legacy rate.
+			 */
+			val = WL_RSPEC_ENCODE_RATE | rate_string2int(*argv);
+		}
+
+		val = htod32(val);
+
+		error = wlu_iovar_setint(wl, name, val);
+	}
+
+	return error;
+}
+
+/* parse the -v/--vht or -c argument for the wl_rate() command.
+ * return FALSE if the arg does not look like MxS or cMsS, where M and S are single digits
+ * return TRUE if the arg does look like MxS or cMsS, setting mcsp to M, and nssp to S
+ */
+static int
+wl_parse_vht_spec(const char* cp, int* mcsp, int* nssp)
+{
+	char *startp, *endp;
+	char c;
+	int mcs, nss;
+	char sx;
+
+	if (cp == NULL || cp[0] == '\0') {
+		return FALSE;
+	}
+
+	if (cp[0] == 'c') {
+		startp = (char*)cp + 1;
+		sx = 's';
+	}
+	else {
+		startp = (char*)cp;
+		sx = 'x';
+	}
+
+	mcs = (int)strtol(startp, &endp, 10);
+	/* verify MCS 0-11, and next char is 's' or 'x' */
+	/* std MCS 0-9 and prop MCS 10-11 */
+	if (mcs < 0 || mcs > 11 || endp[0] != sx) {
+		return FALSE;
+	}
+
+	/* grab the char after the 'x'/'s' and convert to value */
+	c = endp[1];
+	nss = 0;
+	if (isdigit((int)c)) {
+		nss = c - '0';
+	}
+
+	/* consume trailing space after digit */
+	cp = &endp[2];
+	while (isspace((int)(*cp))) {
+		cp++;
+	}
+
+	/* check for trailing garbage after digit */
+	if (cp[0] != '\0') {
+		return FALSE;
+	}
+
+	if (nss < 1 || nss > 8) {
+		return FALSE;
+	}
+
+	*mcsp = mcs;
+	*nssp = nss;
+
+	return TRUE;
+}
+
+static int
+wl_rate(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t mo;
+	char *option_name = NULL;
+	char* endp;
+	const int option_name_len = 64;
+	const char* iov_name;
+	const char* fn_name = "wl_rate";
+	bool options = FALSE;
+	bool auto_set = FALSE;
+	bool legacy_set = FALSE, ht_set = FALSE, vht_set = FALSE;
+	int rate, mcs, Nss, tx_exp, bw;
+	bool stbc, ldpc, sgi;
+	int err, opt_err;
+	uint32 rspec = 0;
+
+	/* set default values */
+	rate = 0;
+	mcs = 0;
+	Nss = 0;
+	tx_exp = 0;
+	stbc = FALSE;
+	ldpc = FALSE;
+	sgi = FALSE;
+	bw = 0;
+
+	/* save the command name */
+	iov_name = *argv++;
+
+	if (ioctl_version == 1) {
+		fprintf(stderr,
+			"cmd %s not supported in this version of the driver, ioctl version 1.\n",
+			iov_name);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* process a GET */
+	if (!*argv) {
+		uint32 val = 0;
+		char * rate_str;
+		const int rate_str_len = 64;
+
+		if (cmd->get < 0)
+			return -1;
+		if ((err = wlu_iovar_getint(wl, iov_name, (int*)&val)) < 0)
+			return err;
+
+		rate_str = malloc(rate_str_len);
+		if (rate_str == NULL) {
+			fprintf(stderr, "%s: malloc failure for rate string buffer.\n", fn_name);
+			return BCME_NOMEM;
+		}
+		memset(rate_str, 0, rate_str_len);
+
+		wl_rate_print(rate_str, val);
+
+		printf("%s\n", rate_str);
+
+		free(rate_str);
+
+		return 0;
+	}
+
+	/* process a SET */
+
+	/* initialze to common error for the miniopt processing */
+	err = BCME_USAGE_ERROR;
+
+	/* alloc option name for error messages */
+	option_name = malloc(option_name_len);
+	if (option_name == NULL) {
+		fprintf(stderr, "%s: malloc failure for option_name buffer.\n", fn_name);
+		return BCME_NOMEM;
+	}
+	memset(option_name, 0, option_name_len);
+
+	miniopt_init(&mo, fn_name, "lg", TRUE);
+	while ((opt_err = miniopt(&mo, argv)) != -1) {
+		if (opt_err == 1) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv += mo.consumed;
+
+		/* track whether or not the command line is just a single positional
+		 * parameter of "auto" or a legacy rate, or is using options
+		 */
+		if (!mo.positional) {
+			options = TRUE;	/* command line is using options */
+		}
+		if (mo.positional) {
+			/* command line is using a positional parameter,
+			 * complain if options are also being used
+			 */
+			if (options) {
+				fprintf(stderr,
+				        "%s: cannot mix positional args and options. "
+				        "Got positional arg \"%s\" after options.\n",
+				        fn_name, mo.valstr);
+				goto exit;
+			}
+			/* complain if there are any more parameters since there should only
+			 * be one positional param, "auto" or a legacy rate.
+			 */
+			if (*argv != NULL) {
+				fprintf(stderr,
+				        "%s: unexpected parameter \"%s\" after rate value.\n",
+				        fn_name, *argv);
+				goto exit;
+			}
+			/* test for "auto" to clear the rate override */
+			if (!strcmp(mo.valstr, "auto")) {
+				auto_set = TRUE;
+			} else {
+				/* pretend there was a '-r' option */
+				mo.opt = 'r';
+			}
+		}
+
+		/* format the option name for error messages */
+		if (mo.key[0] != '\0') {
+			/* would like to do the following, but snprintf() is not availble in
+			 * all target builds. Fails in win_mfgtest_wl build.
+			 *
+			 * snprintf(option_name, option_name_len, "--%s", mo.key);
+			 * option_name[option_name_len - 1] = '\0';
+			 */
+			size_t key_len;
+
+			key_len = strlen(mo.key);
+			/* limit key_len to space in str buffer minus the '--' and null */
+			key_len = MIN((uint)(option_name_len - 3), key_len);
+
+			memcpy(option_name, "--", 2);
+			memcpy(option_name + 2, mo.key, key_len);
+			option_name[2 + key_len] = '\0';
+		} else {
+			sprintf(option_name, "-%c", mo.opt);
+		}
+
+		/* Option: -r or --rate */
+		if (mo.opt == 'r' ||
+		    !strcmp(mo.key, "rate")) {
+			if (mo.valstr == NULL) {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			/* special case check for "-r 5.5" */
+			if (!strcmp(mo.valstr, "5.5")) {
+				rate = 11;
+			} else if (!mo.good_int) {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			} else {
+				rate = mo.val*2;
+			}
+
+			legacy_set = TRUE;
+		}
+		/* Option: -h or --ht */
+		if (mo.opt == 'h' ||
+		    !strcmp(mo.key, "ht")) {
+			if (mo.valstr == NULL) {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			if (!mo.good_int) {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+
+			mcs = mo.val;
+			ht_set = TRUE;
+		}
+		/* Option: -v or --vht */
+		if (mo.opt == 'v' ||
+		    !strcmp(mo.key, "vht")) {
+			if (mo.valstr == NULL || mo.valstr[0] == 'c') {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			mcs = (int)strtol(mo.valstr, &endp, 10);
+			if (*endp == '\0') {
+				mcs = mo.val;
+				vht_set = TRUE;
+			} else if (wl_parse_vht_spec(mo.valstr, &mcs, &Nss)) {
+				vht_set = TRUE;
+			} else {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+		}
+		/* Option: -c (system team's c notiation: c<MCS>s<Nss>) */
+		if (mo.opt == 'c') {
+			if (mo.valstr == NULL || mo.valstr[0] != 'c') {
+				fprintf(stderr,
+				        "%s: expected a value start with c for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			mcs = (int)strtol(mo.valstr + 1, &endp, 10);
+			if (*endp == '\0') {
+				vht_set = TRUE;
+			} else if (wl_parse_vht_spec(mo.valstr, &mcs, &Nss)) {
+				vht_set = TRUE;
+			} else {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+		}
+		/* Option: -s or --ss */
+		if (mo.opt == 's' ||
+		    !strcmp(mo.key, "ss")) {
+			if (mo.valstr == NULL) {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			if (!mo.good_int) {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+			Nss = mo.val;
+		}
+		/* Option: -x or --exp */
+		if (mo.opt == 'x' ||
+		    !strcmp(mo.key, "exp")) {
+			if (mo.valstr == NULL) {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			if (!mo.good_int) {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+			tx_exp = mo.val;
+			if (tx_exp < 0 || tx_exp > 3) {
+				fprintf(stderr,
+				        "%s: tx expansion %d out of range [0-3]\n",
+				        fn_name, tx_exp);
+				err = BCME_RANGE;
+				goto exit;
+			}
+		}
+		/* Option: --stbc */
+		if (!strcmp(mo.key, "stbc")) {
+			if (mo.valstr != NULL) {
+				fprintf(stderr,
+				        "%s: unexpected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+			stbc = TRUE;
+		}
+		/* Option: -l or --ldpc */
+		if (mo.opt == 'l' ||
+		    !strcmp(mo.key, "ldpc")) {
+			if (mo.valstr != NULL) {
+				fprintf(stderr,
+				        "%s: unexpected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+			ldpc = TRUE;
+		}
+		/* Option: -g or --sgi */
+		if (mo.opt == 'g' ||
+		    !strcmp(mo.key, "sgi")) {
+			if (mo.valstr != NULL) {
+				fprintf(stderr,
+				        "%s: unexpected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+			sgi = TRUE;
+		}
+		/* Option: -b or --bandwidth */
+		if (mo.opt == 'b' ||
+		    !strcmp(mo.key, "bandwidth")) {
+			if (mo.valstr == NULL) {
+				fprintf(stderr,
+				        "%s: expected a value for %s option\n",
+				        fn_name, option_name);
+				goto exit;
+			}
+
+			if (!mo.good_int && strcmp(mo.valstr, "2.5")) {
+				fprintf(stderr,
+				        "%s: could not parse \"%s\" as a value for %s option\n",
+				        fn_name, mo.valstr, option_name);
+				goto exit;
+			}
+
+			if (mo.val == 2) {
+				if (strcmp(mo.valstr, "2.5")) {
+					fprintf(stderr,
+						"%s: unexpected bandwidth specified \"%s\", "
+						"expected 2.5, 5, 10, 20, 40, 80, or 160\n",
+						fn_name, mo.valstr);
+					goto exit;
+				}
+				bw = WL_RSPEC_BW_2P5MHZ;
+			} else if (mo.val == 5) {
+				bw = WL_RSPEC_BW_5MHZ;
+			} else if (mo.val == 10) {
+				bw = WL_RSPEC_BW_10MHZ;
+			} else if (mo.val == 20) {
+				bw = WL_RSPEC_BW_20MHZ;
+			} else if (mo.val == 40) {
+				bw = WL_RSPEC_BW_40MHZ;
+			} else if (mo.val == 80) {
+				bw = WL_RSPEC_BW_80MHZ;
+			} else if (mo.val == 160) {
+				bw = WL_RSPEC_BW_160MHZ;
+			} else {
+				fprintf(stderr,
+				        "%s: unexpected bandwidth specified \"%s\", "
+				        "expected 2.5, 5, 10, 20, 40, 80, or 160\n",
+				        fn_name, mo.valstr);
+				goto exit;
+			}
+		}
+	}
+
+	/*
+	 * check for necessary use of one of -r/-h/-v or auto
+	 */
+
+	if (!auto_set && !legacy_set && !ht_set && !vht_set) {
+		fprintf(stderr, "%s: must specify one of \"auto\", legacy rate -r/--rate, "
+		        "HT (11n) rate -h/--ht, or VHT (11ac) rate -v/--vht\n",
+		        fn_name);
+		goto exit;
+	}
+
+	/*
+	 * check for incompatible use of -r/-h/-v
+	 */
+
+	if (legacy_set && ht_set) {
+		fprintf(stderr, "%s: cannot use legacy rate -r/--rate and "
+		        "HT rate -h/--ht at the same time\n",
+		        fn_name);
+		goto exit;
+	}
+
+	if (legacy_set && vht_set) {
+		fprintf(stderr, "%s: cannot use legacy rate -r/--rate and "
+		        "HT rate -v/--vht at the same time\n",
+		        fn_name);
+		goto exit;
+	}
+
+	if (ht_set && vht_set) {
+		fprintf(stderr, "%s: cannot use HT rate -h/--ht and "
+		        "HT rate -v/--vht at the same time\n",
+		        fn_name);
+		goto exit;
+	}
+
+	/* Nss can only be used with VHT */
+	if (!vht_set && Nss != 0) {
+		fprintf(stderr, "%s: cannot use -s/--ss option with non VHT rate\n",
+		        fn_name);
+		goto exit;
+	}
+
+	/* STBC, LDPC, SGI can only be used with HT/VHT rates */
+	if ((stbc || ldpc || sgi) && !(ht_set || vht_set)) {
+		fprintf(stderr, "%s: cannot use STBC/LDPC/SGI options with non HT/VHT rates\n",
+		        fn_name);
+		goto exit;
+	}
+
+	/* set the ratespec encoding type and basic rate value */
+	if (auto_set) {
+		rspec = 0;
+	} else if (legacy_set) {
+		rspec = WL_RSPEC_ENCODE_RATE;	/* 11abg */
+		rspec |= rate;
+	} else if (ht_set) {
+		rspec = WL_RSPEC_ENCODE_HT;	/* 11n HT */
+		rspec |= mcs;
+	} else {
+		rspec = WL_RSPEC_ENCODE_VHT;	/* 11ac VHT */
+		if (Nss == 0) {
+			Nss = 1; /* default Nss = 1 if --ss option not given */
+		}
+		rspec |= (Nss << WL_RSPEC_VHT_NSS_SHIFT) | mcs;
+	}
+
+	/* set the other rspec fields */
+	rspec |= (tx_exp << WL_RSPEC_TXEXP_SHIFT);
+	rspec |= bw;
+	rspec |= (stbc ? WL_RSPEC_STBC : 0);
+	rspec |= (ldpc ? WL_RSPEC_LDPC : 0);
+	rspec |= (sgi  ? WL_RSPEC_SGI  : 0);
+
+	err = wlu_iovar_setint(wl, iov_name, (int)rspec);
+
+exit:
+	if (option_name != NULL) {
+		free(option_name);
+	}
+
+	return err;
+} /* wl_rate */
+
+static int
+wl_bss_max(void *wl, cmd_t *cmd, char **argv)
+{
+	int val = 1;
+	int error;
+
+	UNUSED_PARAMETER(argv);
+
+	/* Get the CAP variable; search for mbss4 or mbss16 */
+	strcpy(buf, "cap");
+	if ((error = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MEDLEN)) < 0)
+		return (error);
+
+	buf[WLC_IOCTL_MEDLEN] = '\0';
+	if (strstr(buf, "mbss16"))
+		val = 16;
+	else if (strstr(buf, "mbss4"))
+		val = 4;
+
+	printf("%d\n", val);
+	return (0);
+}
+
+int
+wl_phy_rate(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error;
+	const char *name = cmd->name;
+	static const struct {
+		const char* orig;
+		const char* new;
+	} aliases[] = {
+		{"bg_rate",  "2g_rate"},
+		{"bg_mrate", "2g_mrate"},
+		{"a_rate",   "5g_rate"},
+		{"a_mrate",  "5g_mrate"},
+	};
+
+	/* toss the command name from the args */
+	argv++;
+
+	/* if we are not using the legacy ioctl driver, translate the
+	 * bg_* prefix to 2g_* and a_* to 5g_* iovars
+	 */
+	if (ioctl_version > 1) {
+		int i;
+		for (i = 0; i < 4; i++) {
+			if (!strcmp(name, aliases[i].orig)) {
+				name = aliases[i].new;
+				break;
+			}
+		}
+	}
+
+	if (!*argv) {
+		error = wlu_iovar_getint(wl, name, &val);
+		if (error < 0)
+			return (error);
+
+		val = dtoh32(val);
+		if (ioctl_version > 1) {
+			wl_printrate(wl_ratespec2rate((uint32)val));
+		} else {
+			wl_printrate(val);
+		}
+	} else {
+		/* create the ioctl value based on the major ioctl version */
+		if (ioctl_version == 1) {
+			/* for ver=1 ioctl interfaces, override values for 2g_(m)rate/5g_(m)rate
+			 * are just given as 500 Kbps units
+			 */
+			val = rate_string2int(*argv);
+		} else {
+			/* for ver>1 ioctl interfaces, override values for 2g_(m)rate/5g_(m)rate
+			 * are a wl_ratespec of a legacy rate.
+			 */
+			val = WL_RSPEC_ENCODE_RATE | rate_string2int(*argv);
+		}
+
+
+		val = htod32(val);
+		error = wlu_iovar_setint(wl, name, val);
+	}
+
+	return error;
+}
+
+static int
+wl_assoc_info(void *wl, cmd_t *cmd, char **argv)
+{
+	uint i, req_ies_len = 0, resp_ies_len = 0;
+	wl_assoc_info_t assoc_info;
+	int ret;
+	uint8 *pbuf;
+
+	UNUSED_PARAMETER(argv);
+
+	/* get the generic association information */
+	strcpy(buf, cmd->name);
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_SMLEN)) < 0)
+		return ret;
+
+	memcpy(&assoc_info, buf, sizeof(wl_assoc_info_t));
+	assoc_info.req_len = htod32(assoc_info.req_len);
+	assoc_info.resp_len = htod32(assoc_info.resp_len);
+	assoc_info.flags = htod32(assoc_info.flags);
+
+	printf("Assoc req:\n");
+	printf("\tlen 0x%x\n", assoc_info.req_len);
+	if (assoc_info.req_len) {
+		printf("\tcapab  0x%x\n", ltoh16(assoc_info.req.capability));
+		printf("\tlisten 0x%x\n", ltoh16(assoc_info.req.listen));
+		req_ies_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
+		if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
+			printf("\treassoc bssid %s\n",
+				wl_ether_etoa(&assoc_info.reassoc_bssid));
+			req_ies_len -= ETHER_ADDR_LEN;
+		}
+	}
+
+	/* get the association req IE's if there are any */
+	if (req_ies_len) {
+		strcpy(buf, "assoc_req_ies");
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_SMLEN)) < 0)
+			return ret;
+
+		printf("assoc req IEs:\n\t");
+		for (i = 1, pbuf = (uint8*)buf; i <= req_ies_len; i++) {
+			printf("0x%02x ", *pbuf++);
+			if (!(i%8))
+				printf("\n\t");
+		}
+	}
+
+	printf("\nAssoc resp:\n");
+	printf("\tlen 0x%x\n", assoc_info.resp_len);
+	if (assoc_info.resp_len) {
+		printf("\tcapab  0x%x\n", ltoh16(assoc_info.resp.capability));
+		printf("\tstatus 0x%x\n", ltoh16(assoc_info.resp.status));
+		printf("\taid    0x%x\n", ltoh16(assoc_info.resp.aid));
+		resp_ies_len = assoc_info.resp_len - sizeof(struct dot11_assoc_resp);
+	}
+
+	/* get the association resp IE's if there are any */
+	if (resp_ies_len) {
+		strcpy(buf, "assoc_resp_ies");
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_SMLEN)) < 0)
+			return ret;
+
+		printf("assoc resp IEs:\n\t");
+		for (i = 1, pbuf = (uint8*)buf; i <= resp_ies_len; i++) {
+			printf(" 0x%02x ", *pbuf++);
+			if (!(i%8))
+				printf("\n\t");
+
+		}
+	}
+	printf("\n");
+
+	return 0;
+}
+
+static int
+wl_pmkid_info(void *wl, cmd_t *cmd, char**argv)
+{
+	int i, j, ret;
+	pmkid_list_t *pmkid_info;
+
+	if (!*++argv) {
+		strcpy(buf, cmd->name);
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_SMLEN)) < 0)
+			return ret;
+
+		pmkid_info = (pmkid_list_t *)buf;
+		pmkid_info->npmkid = dtoh32(pmkid_info->npmkid);
+		printf("\npmkid entries : %d\n", pmkid_info->npmkid);
+
+		for (i = 0; i < (int)pmkid_info->npmkid; i++) {
+			printf("\tPMKID[%d]: %s =",
+				i, wl_ether_etoa(&pmkid_info->pmkid[i].BSSID));
+			for (j = 0; j < WPA2_PMKID_LEN; j++)
+				printf("%02x ", pmkid_info->pmkid[i].PMKID[j]);
+			printf("\n");
+		}
+	}
+	else {
+#ifdef test_pmkid_info
+		char eaddr[6] = {0x0, 0x0, 0x1, 0x2, 0x3, 0x5};
+		char eaddr1[6] = {0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
+		char id[WPA2_PMKID_LEN], id1[WPA2_PMKID_LEN];
+		int i, len = (sizeof(uint32) + 2*(sizeof(pmkid_t)));
+
+		/* check that the set uses to "test" cmd */
+		if (strcmp(*argv, "test")) {
+			printf("\t wl pmkid_info only supports `test` a test specific set\n");
+			return BCME_USAGE_ERROR;
+		}
+		if ((pmkid_info = (pmkid_list_t *)malloc(len)) == NULL)	{
+			printf("\tfailed to allocate buffer\n");
+			return BCME_NOMEM;
+		}
+
+		printf("\toverwriting pmkid table with test pattern\n");
+		for (i = 0; i < (int)sizeof(id); i++) {
+			id[i] = i;
+			id1[i] = (i*2);
+		}
+
+		/* "test" - creates two PMKID entries and sets the table to that */
+		pmkid_info->npmkid = htod32(2);
+		memcpy(&pmkid_info->pmkid[0].BSSID.octet[0], &eaddr[0], ETHER_ADDR_LEN);
+		memcpy(&pmkid_info->pmkid[0].PMKID[0], &id[0], WPA2_PMKID_LEN);
+		memcpy(&pmkid_info->pmkid[1].BSSID.octet[0], &eaddr1[0], ETHER_ADDR_LEN);
+		memcpy(&pmkid_info->pmkid[1].PMKID[0], &id1[0], WPA2_PMKID_LEN);
+
+		ret = wlu_var_setbuf(wl, cmd->name, pmkid_info, len);
+
+		free(pmkid_info);
+
+		return ret;
+#else
+		printf("\tset cmd ignored\n");
+#endif /* test_pmkid_info */
+	}
+
+	return 0;
+}
+
+static int
+wl_rateset(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_rateset_args_t rs, defrs;
+	int error;
+	uint i;
+
+	UNUSED_PARAMETER(cmd);
+
+	error = 0;
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get current rateset */
+		if ((error = wlu_iovar_get(wl, "cur_rateset", &rs, sizeof(rs))) < 0)
+			return (error);
+
+		dump_rateset(rs.rates, dtoh32(rs.count));
+		printf("\n");
+		wl_print_mcsset((char *)rs.mcs);
+		wl_print_vhtmcsset((uint16 *)rs.vht_mcs);
+	} else {
+		/* get default rateset and mcsset */
+		if ((error = wlu_iovar_get(wl, "rateset", &defrs,
+		                           sizeof(wl_rateset_args_t))) < 0)
+			return (error);
+		defrs.count = dtoh32(defrs.count);
+
+		if (!stricmp(*argv, "all")) {
+			for (i = 0; i < defrs.count; i++)
+				defrs.rates[i] |= 0x80;
+			defrs.count = htod32(defrs.count);
+			error = wlu_iovar_set(wl, "rateset", &defrs,
+			                      sizeof(wl_rateset_args_t));
+		}
+		else if (!stricmp(*argv, "default")) {
+			defrs.count = htod32(defrs.count);
+			error = wlu_iovar_set(wl, "rateset", &defrs,
+			                      sizeof(wl_rateset_args_t));
+		}
+		else {	/* arbitrary list */
+			error = wl_parse_rateset(wl, &defrs, argv);
+			if (!error) {
+
+				/* check for common error of no basic rates */
+				for (i = 0; i < defrs.count; i++) {
+					if (defrs.rates[i] & 0x80)
+						break;
+				}
+				if (i < defrs.count) {
+					defrs.count = htod32(defrs.count);
+					error = wlu_iovar_set(wl, "rateset", &defrs,
+						sizeof(wl_rateset_args_t));
+				} else {
+					error = BCME_BADARG;
+					fprintf(stderr,
+					    "Bad Args: at least one rate must be marked Basic\n");
+				}
+			}
+		}
+
+	}
+	return (error);
+}
+
+static int
+wl_default_rateset(void *wl, cmd_t *cmd, char **argv)
+{
+	int error = 0;
+	wl_rates_info_t rates_info;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset((char*)&rates_info.rs_tgt, 0, sizeof(wl_rateset_t));
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse phy type\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* phy_type */
+	if (!stricmp(*argv, "a"))
+		rates_info.phy_type = 0;
+	else if (!stricmp(*argv, "b"))
+		rates_info.phy_type = 2;
+	else if (!stricmp(*argv, "g"))
+		rates_info.phy_type = 2;
+	else if (!stricmp(*argv, "n"))
+		rates_info.phy_type = 4;
+	else if (!stricmp(*argv, "lp"))
+		rates_info.phy_type = 5;
+	else if (!stricmp(*argv, "ssn"))
+		rates_info.phy_type = 6;
+	else if (!stricmp(*argv, "ht"))
+		rates_info.phy_type = 7;
+	else if (!stricmp(*argv, "lcn"))
+		rates_info.phy_type = 8;
+	else if (!stricmp(*argv, "lcn40"))
+		rates_info.phy_type = 10;
+	else if (!stricmp(*argv, "ac"))
+		rates_info.phy_type = 11;
+	else {
+		fprintf(stderr, "Wrong phy type: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse band type\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* band type */
+	if (!stricmp(*argv, "5"))
+		rates_info.bandtype = WLC_BAND_5G;
+	else if (!stricmp(*argv, "2"))
+		rates_info.bandtype = WLC_BAND_2G;
+	else {
+		fprintf(stderr, "Wrong band type: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse cck\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* cck only */
+	if (!stricmp(*argv, "0"))
+		rates_info.cck_only = FALSE;
+	else if (!stricmp(*argv, "1"))
+		rates_info.cck_only = TRUE;
+	else {
+		fprintf(stderr, "Wrong cck: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse basic rates\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* rate_mask */
+	if (!stricmp(*argv, "0"))
+		rates_info.rate_mask = 0x7f;
+	else if (!stricmp(*argv, "1"))
+		rates_info.rate_mask = 0xff;
+	else {
+		fprintf(stderr, "Wrong basic rates: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse mcs\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* mcs */
+	if (!stricmp(*argv, "0"))
+		rates_info.mcsallow = FALSE;
+	else if (!stricmp(*argv, "1"))
+		rates_info.mcsallow = TRUE;
+	else {
+		fprintf(stderr, "Wrong mcs: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse bandwidth\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* channel bandwidth */
+	if (!stricmp(*argv, "10"))
+		rates_info.bw = 10;
+	else if (!stricmp(*argv, "20"))
+		rates_info.bw = 20;
+	else if (!stricmp(*argv, "40"))
+		rates_info.bw = 40;
+	else if (!stricmp(*argv, "80"))
+		rates_info.bw = 80;
+	else if (!stricmp(*argv, "160"))
+		rates_info.bw = 160;
+	else {
+		fprintf(stderr, "Wrong bandwidth: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	/* not enough params */
+	if (*argv == NULL) {
+		fprintf(stderr, "Can't parse tx/rx streams\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* mcs */
+	if (!stricmp(*argv, "tx")) {
+		int txstreams;
+		if ((error = wlu_iovar_getint(wl, "txstreams", &txstreams)) < 0) {
+			fprintf(stderr, "Can't get tx streams\n");
+			return BCME_USAGE_ERROR;
+		}
+		rates_info.txstreams = txstreams;
+	}
+	else if (!stricmp(*argv, "rx")) {
+		int rxstreams;
+		if ((error = wlu_iovar_getint(wl, "rxstreams", &rxstreams)) < 0) {
+			fprintf(stderr, "Can't get rx streams\n");
+			return BCME_USAGE_ERROR;
+		}
+		rates_info.txstreams = rxstreams;
+	}
+	else {
+		fprintf(stderr, "Wrong tx/rx streams: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* get default rates */
+	if ((error = wlu_iovar_getbuf(wl, "default_rateset", NULL, 0, &rates_info,
+		sizeof(wl_rates_info_t)))) {
+		fprintf(stderr, "default_rateset failed\n");
+		return (error);
+	}
+
+	dump_rateset(rates_info.rs_tgt.rates, dtoh32(rates_info.rs_tgt.count));
+
+	return (error);
+}
+
+static int
+wl_txbf_rateset(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_txbf_rateset_t rs;
+	int error = 0;
+
+	argv++;
+
+	if ((error = wlu_iovar_get(wl, cmd->name, &rs, sizeof(rs))) < 0)
+		return (error);
+	/* Get txbf rateset */
+	if (*argv == NULL) {
+		printf("    OFDM: ");
+		dump_rateset(rs.txbf_rate_ofdm, dtoh32(rs.txbf_rate_ofdm_cnt));
+		printf("\n");
+		wl_print_txbf_mcsset((char *)rs.txbf_rate_mcs, "   ");
+		wl_print_txbf_vhtmcsset((uint16 *)rs.txbf_rate_vht, "   ");
+
+		printf("BCM OFDM: ");
+		dump_rateset(rs.txbf_rate_ofdm_bcm, dtoh32(rs.txbf_rate_ofdm_cnt_bcm));
+		printf("\n");
+		wl_print_txbf_mcsset((char *)rs.txbf_rate_mcs_bcm, "BCM");
+		wl_print_txbf_vhtmcsset((uint16 *)rs.txbf_rate_vht_bcm, "BCM");
+	} else {	/* Set txbf rateset */
+		error = wl_parse_txbf_rateset(&rs, argv);
+		if (!error) {
+			rs.txbf_rate_ofdm_cnt     = htod32(rs.txbf_rate_ofdm_cnt);
+			rs.txbf_rate_ofdm_cnt_bcm = htod32(rs.txbf_rate_ofdm_cnt_bcm);
+			error = wlu_iovar_set(wl, cmd->name, &rs, sizeof(rs));
+		}
+	}
+	return (error);
+}
+
+static int
+wl_sup_rateset(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_rateset_args_t rs;
+	bool got_basic;
+	int error;
+	uint i;
+
+	error = 0;
+	memset((char*)&rs, 0, sizeof(wl_rateset_args_t));
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get rateset */
+		if ((error = wlu_get(wl, cmd->get, &rs, sizeof(wl_rateset_t))) < 0)
+			return (error);
+
+		dump_rateset(rs.rates, dtoh32(rs.count));
+		printf("\n");
+	} else {
+		if (!stricmp(*argv, "-1") || !stricmp(*argv, "0")) {
+			/* set an empty rateset */
+			error = wlu_set(wl, cmd->set, &rs, sizeof(wl_rateset_t));
+		}
+		else {	/* set the specified rateset */
+			wl_parse_rateset(wl, &rs, argv);
+			/* check for common error of including a basic rate */
+			got_basic = FALSE;
+			for (i = 0; i < rs.count; i++) {
+				if (rs.rates[i] & 0x80) {
+					rs.rates[i] &= 0x7F;
+					got_basic = TRUE;
+				}
+			}
+			if (got_basic) {
+				fprintf(stderr,
+				"Warning: Basic rate attribute ignored for \"%s\" command\n",
+				cmd->name);
+			}
+			rs.count = htod32(rs.count);
+			error = wlu_set(wl, cmd->set, &rs, sizeof(wl_rateset_t));
+		}
+
+	}
+	return (error);
+}
+
+/*
+ * Parse the rateset command arguments into the passed wl_rateset_args_t structure.
+ *
+ * Returns 0 on success, or an appropriate error code (BCME_USAGE_ERROR, BCME_BADARG).
+ *
+ */
+static int
+wl_parse_rateset(void *wl, wl_rateset_args_t* rs, char **argv)
+{
+	char* endp = NULL;
+	char* arg;
+	int r;
+	int mcs_index = 0;
+	uint32 mcs_mask;
+	int error = 0;
+	wl_rateset_args_t cur_rs;
+	bool mcs_args, vht_args;
+
+	mcs_args = vht_args = FALSE;
+
+	memset(rs, 0, sizeof(*rs));
+
+	while ((arg = *argv++) != NULL) {
+		/* mcs rates */
+		if (!stricmp(arg, "-m")) {
+			mcs_args = TRUE;
+			break;
+		}
+
+		/* vht rates */
+		if (!stricmp(arg, "-v")) {
+			vht_args = TRUE;
+			break;
+		}
+
+		/* Parse legacy rates */
+
+		if (rs->count >= WL_MAXRATES_IN_SET) {
+			fprintf(stderr,
+			"parsing \"%s\", too many rates specified, max is %d rates\n",
+			arg, WL_MAXRATES_IN_SET);
+			error = BCME_USAGE_ERROR;
+			break;
+		}
+
+		/* convert the rate number to a 500kbps rate by multiplying by 2 */
+		r = (int)(strtoul(arg, &endp, 0) * 2);
+		if (endp == arg) {
+			fprintf(stderr, "unable to convert the rate parameter \"%s\"\n", arg);
+			error = BCME_USAGE_ERROR;
+			break;
+		}
+
+		/* parse a .5 specially */
+		if (!strncmp(endp, ".5", 2)) {
+			r += 1;
+			endp += 2;
+		}
+
+		/* strip trailing space */
+		while (isspace((int)endp[0]))
+			endp++;
+
+		/* check for a basic rate specifier */
+		if (!stricmp(endp, "b") || !stricmp(endp, "(b)")) {
+			r |= 0x80;
+		} else if (endp[0] != '\0') {
+			fprintf(stderr,
+				"unable to convert trailing characters"
+				" \"%s\" in the rate parameter \"%s\"\n",
+				endp, arg);
+			error = BCME_USAGE_ERROR;
+			break;
+		}
+
+		/* no legacy rates specified */
+		if ((rs->count == 0) && (r == 0)) {
+			fprintf(stderr, "empty legacy rateset not supported\n");
+			error = BCME_USAGE_ERROR;
+			break;
+		}
+
+		rs->rates[rs->count++] = r;
+	}
+
+	if (error)
+		return error;
+
+	if (!mcs_args && !vht_args && !rs->count)
+		return BCME_USAGE_ERROR; /* Cannot happen, really */
+
+	/*
+	 * If one of the rate sets was not specified, keep its current setting.
+	 */
+
+	error = wlu_iovar_get(wl, "cur_rateset", &cur_rs, sizeof(cur_rs));
+	if (error)
+		return error;
+
+	if (!rs->count) { /* No legacy rates specified -- keep what we have */
+		rs->count = cur_rs.count;
+		memcpy(&rs->rates, &cur_rs.rates, rs->count);
+	}
+
+	if (!mcs_args) { /* No MCS rates specified */
+		memcpy(rs->mcs, cur_rs.mcs, MCSSET_LEN);
+	}
+
+	if (!vht_args) { /* No VHT rates specified, keep current values */
+		memcpy(rs->vht_mcs, cur_rs.vht_mcs,
+		       VHT_CAP_MCS_MAP_NSS_MAX * sizeof(rs->vht_mcs[0]));
+	}
+
+	/* If no more args, return. */
+
+	if (!arg) {
+		return error;
+	}
+
+	/* Parse mcs or VHT rateset values */
+
+	while ((arg = *argv++) != NULL) {
+
+	    if (mcs_args) {
+
+		    if (mcs_index >= MCSSET_LEN) {
+			fprintf(stderr, "parsing \"%s\", too many mcs rates "
+			        "specified, max is %d rates\n", arg, MCSSET_LEN);
+			error = BCME_USAGE_ERROR;
+			break;
+		}
+
+		mcs_mask = strtoul(arg, &endp, 16);
+
+		if (endp == arg) {
+			fprintf(stderr, "unable to convert the mcs parameter \"%s\"\n", arg);
+			error = BCME_BADARG;
+			break;
+		}
+
+		/* clear the mcs rates */
+		if (mcs_mask == 0) {
+			memset(rs->mcs, 0, MCSSET_LEN);
+			break;
+		}
+
+		/* copy the mcs rates bitmap octets */
+		rs->mcs[mcs_index++] = mcs_mask;
+
+	    } else { /* vht_args */
+
+		    /*
+		     * Specified as rate masks for Nss=0, Nss=1, etc.
+		     */
+		    if (mcs_index >= VHT_CAP_MCS_MAP_NSS_MAX) {
+			fprintf(stderr,
+				"Error: Too many VHT rate masks specified, max %d\n",
+				VHT_CAP_MCS_MAP_NSS_MAX);
+			error = BCME_USAGE_ERROR;
+			break;
+		    }
+
+		    mcs_mask = strtoul( arg, &endp, 16 ); /* Base 16 for consistency with -m */
+
+		    if ((*arg == '\0') || (*endp != '\0')) {
+			    fprintf(stderr, "Error converting VHT rate mask value '%s'\n", arg);
+			    error = BCME_USAGE_ERROR;
+			    break;
+		    }
+
+		    /*
+		     * Can only specify 0, 0xff, 0x1ff, 0x3ff because of the way the rates
+		     * are encoded in the driver (0-3).
+		     */
+		    if ((mcs_mask != 0x0000) &&   /* vht disabled */
+			(mcs_mask != VHT_CAP_MCS_0_7_RATEMAP) &&   /* vht mcs0-7 */
+			(mcs_mask != VHT_CAP_MCS_0_8_RATEMAP) &&   /* vht mcs0-8 */
+			(mcs_mask != VHT_CAP_MCS_0_9_RATEMAP) &&   /* vht mcs0-9 */
+			(mcs_mask != (VHT_CAP_MCS_0_9_RATEMAP |
+				      VHT_PROP_MCS_10_11_RATEMAP))) {   /* vht mcs0-11 */
+			    fprintf(stderr, "Error: VHT rate mask must be 0 (disabled),"
+				" 0xff (MCS0-7), 0x1ff (MCS0-8), 0x3ff (MCS0-9) or "
+				"0xfff (MCS0-11).\n");
+			    error = BCME_BADARG;
+			    break;
+		    }
+
+		    rs->vht_mcs[mcs_index++] = mcs_mask;
+	       }
+	}
+
+	return error;
+}
+
+static int
+wl_parse_txbf_rateset(wl_txbf_rateset_t *rs, char **argv)
+{
+#define TXBF_RATE_OFDM	0
+#define TXBF_RATE_MCS	1
+#define TXBF_RATE_VHT	2
+	char* endp = NULL;
+	char* arg;
+	int i;
+	int error = 0;
+	int rate_type = TXBF_RATE_OFDM;
+	uint8	txbf_rate_mcs[TXBF_RATE_MCS_ALL];
+	uint8	txbf_rate_mcs_cnt = 0;
+	uint8	mcs_mask;
+	uint16	txbf_rate_vht[TXBF_RATE_VHT_ALL];
+	uint8	txbf_rate_vht_cnt = 0;
+	uint16	vht_mask;
+	uint8	txbf_rate_ofdm[TXBF_RATE_OFDM_ALL];
+	uint8	txbf_rate_ofdm_cnt;
+	int r;
+	bool specified_ofdm = FALSE;
+	bool specified_mcs  = FALSE;
+	bool specified_vht  = FALSE;
+	bool specified_bcm  = FALSE;
+
+	/* First see if ofdm list */
+	arg = *argv;
+	if (stricmp(arg, "-m") != 0 && stricmp(arg, "-v") != 0) {
+		rate_type = TXBF_RATE_OFDM;
+		specified_ofdm = TRUE;
+		txbf_rate_ofdm_cnt = 0;
+	}
+
+	while ((arg = *argv++) != NULL) {
+		/* mcs rates */
+		if (!stricmp(arg, "-m")) {
+			rate_type = TXBF_RATE_MCS;
+			specified_mcs = TRUE;
+			txbf_rate_mcs_cnt = 0;
+			continue;
+		}
+		/* vht rates */
+		if (!stricmp(arg, "-v")) {
+			rate_type = TXBF_RATE_VHT;
+			specified_vht = TRUE;
+			txbf_rate_vht_cnt = 0;
+			continue;
+		}
+		/* Broadcom-to-Broadcom group */
+		if (!stricmp(arg, "-b")) {
+			specified_bcm = TRUE;
+			continue;
+		}
+
+		if (rate_type == TXBF_RATE_OFDM) {
+			/* Check if too many specified ofdm rates */
+			if (txbf_rate_ofdm_cnt >= TXBF_RATE_OFDM_ALL) {
+				fprintf(stderr, "ERR: more than max. of %d ofdm rates\n",
+					TXBF_RATE_OFDM_ALL);
+				return (BCME_USAGE_ERROR);
+			}
+			/* Convert user typed number to a 500kbps rate by multiplying by 2 */
+			r = (int)(strtoul(arg, &endp, 0) * 2);
+			if (endp == arg) {
+				fprintf(stderr, "ERR: failed to convert %s\n", arg);
+				return (BCME_USAGE_ERROR);
+			}
+			/* Check if valid ofdm rate */
+			for (i = 0; i < (int)sizeof(ofdm_rates); i++) {
+				/* match: it is a valid ofdm rate */
+				if (r == (ofdm_rates[i] & OFDM_RATE_MASK)) {
+					r = ofdm_rates[i]; /* will pick up basic rate bit too */
+					break;
+				}
+			}
+			if (i >= (int)sizeof(ofdm_rates)) {
+				fprintf(stderr, "ERR: %s is an invalid ofdm rate\n", arg);
+				return (BCME_USAGE_ERROR);
+			}
+
+			/* Strip trailing space */
+			while (isspace((int)endp[0]))
+				endp++;
+			/* No ofdm rate specified */
+			if ((rs->txbf_rate_ofdm_cnt == 0) && (r == 0)) {
+				fprintf(stderr, "ERR: no ofdm rate specified\n");
+				return (BCME_USAGE_ERROR);
+			}
+			txbf_rate_ofdm[txbf_rate_ofdm_cnt++] = r;
+		} else if (rate_type == TXBF_RATE_MCS) {
+			/* Check if exceeding max */
+			if (txbf_rate_mcs_cnt >= TXBF_RATE_MCS_ALL) {
+				fprintf(stderr, "ERR: exceed max. %d bitmask bytes; parsing %s\n",
+					TXBF_RATE_MCS_ALL, arg);
+				return (BCME_BADARG);
+			}
+			mcs_mask = (uint8)strtoul(arg, &endp, 16);
+			if (endp == arg) {
+				fprintf(stderr, "ERR: failed to convert %s\n", arg);
+				return (BCME_USAGE_ERROR);
+			}
+			txbf_rate_mcs[txbf_rate_mcs_cnt++] = mcs_mask;
+		} else if (rate_type == TXBF_RATE_VHT) {
+			/* Check if exceeding max */
+			if (txbf_rate_vht_cnt >= TXBF_RATE_VHT_ALL) {
+				fprintf(stderr, "ERR: exceed max. %d bitmasks; parsing %s\n",
+					TXBF_RATE_VHT_ALL, arg);
+				return (BCME_BADARG);
+			}
+			vht_mask = (uint16)strtoul(arg, &endp, 16);
+			if (endp == arg) {
+				fprintf(stderr, "ERR: failed to convert %s\n", arg);
+				return (BCME_USAGE_ERROR);
+			}
+
+			/* Validate bitmask value */
+			if (vht_mask > 0x0fff) {
+				fprintf(stderr, "ERR: vht bitmask must be 0 (disabled)"
+						" or up to a maximum of 0xfff (MCS0-11).\n");
+				return (BCME_BADARG);
+			}
+			txbf_rate_vht[txbf_rate_vht_cnt++] = vht_mask;
+		}
+
+	} /* while */
+
+	if (specified_mcs && !specified_bcm) {
+		for (i = 0; i < txbf_rate_mcs_cnt; i++)
+			rs->txbf_rate_mcs[i] = txbf_rate_mcs[i];
+		if (txbf_rate_mcs_cnt)
+			for (i = txbf_rate_mcs_cnt; i < TXBF_RATE_MCS_ALL; i++)	/* clear trailer */
+				rs->txbf_rate_mcs[i] = 0;
+	}
+
+	if (specified_vht && !specified_bcm) {
+		for (i = 0; i < txbf_rate_vht_cnt; i++)
+			rs->txbf_rate_vht[i] = txbf_rate_vht[i];
+		if (txbf_rate_vht_cnt)
+			for (i = txbf_rate_vht_cnt; i < TXBF_RATE_VHT_ALL; i++)	/* clear trailer */
+				rs->txbf_rate_vht[i] = 0;
+	}
+
+	if (specified_ofdm && !specified_bcm) {
+		for (i = 0; i < txbf_rate_ofdm_cnt; i++)
+			rs->txbf_rate_ofdm[i] = txbf_rate_ofdm[i];
+		rs->txbf_rate_ofdm_cnt = txbf_rate_ofdm_cnt;
+	}
+
+	if (specified_mcs && specified_bcm) {
+		for (i = 0; i < txbf_rate_mcs_cnt; i++)
+			rs->txbf_rate_mcs_bcm[i] = txbf_rate_mcs[i];
+		if (txbf_rate_mcs_cnt)
+			for (i = txbf_rate_mcs_cnt; i < TXBF_RATE_MCS_ALL; i++)	/* clear trailer */
+				rs->txbf_rate_mcs_bcm[i] = 0;
+	}
+
+	if (specified_vht && specified_bcm) {
+		for (i = 0; i < txbf_rate_vht_cnt; i++)
+			rs->txbf_rate_vht_bcm[i] = txbf_rate_vht[i];
+		if (txbf_rate_vht_cnt)
+			for (i = txbf_rate_vht_cnt; i < TXBF_RATE_VHT_ALL; i++)	/* clear trailer */
+				rs->txbf_rate_vht_bcm[i] = 0;
+	}
+
+	if (specified_ofdm && specified_bcm) {
+		for (i = 0; i < txbf_rate_ofdm_cnt; i++)
+			rs->txbf_rate_ofdm_bcm[i] = txbf_rate_ofdm[i];
+		rs->txbf_rate_ofdm_cnt_bcm = txbf_rate_ofdm_cnt;
+	}
+
+	return (error);
+}
+
+/*
+ * Get or Set LPC Params
+ *	wl lpc_params \
+ *		<rate_stab_thresh> <pwr_stab_thresh> <lpc_exp_time> <pwrup_slow_step>
+ *           <pwrup_fast_step> <pwrdn_slow_step>
+ */
+static int
+wl_power_sel_params(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, argc;
+	bool lpc_params_use_powersel_params;
+	lpc_params_t lpc_params;
+
+	UNUSED_PARAMETER(cmd);
+
+	lpc_params_use_powersel_params = (wlc_ver_major(wl) <= 5);
+
+	/* handle old powersel_params_t format support */
+	if (lpc_params_use_powersel_params) {
+		powersel_params_t pwrsel_params;
+
+		argv++;
+
+		if (*argv == NULL) {
+			/* get current powersel params */
+			if ((err = wlu_iovar_get(wl, cmd->name, (void *) &pwrsel_params,
+				(sizeof(powersel_params_t)))) < 0)
+				return (err);
+
+			printf("- Link Power Control parameters -\n");
+			printf("tp_ratio_thresh\t\t= %d\nrate_stab_thresh\t= %d\n",
+				pwrsel_params.tp_ratio_thresh, pwrsel_params.rate_stab_thresh);
+			printf("pwr_stab_thresh\t\t= %d\npwr_sel_exp_time\t= %d\n",
+				pwrsel_params.pwr_stab_thresh, pwrsel_params.pwr_sel_exp_time);
+		} else {
+			char *endptr;
+			/* Validate num of entries */
+			for (argc = 0; argv[argc]; argc++);
+			if (argc != 4)
+				return BCME_USAGE_ERROR;
+
+			argc = 0;
+			pwrsel_params.tp_ratio_thresh = strtol(argv[argc], &endptr, 0);
+			argc++;
+			pwrsel_params.rate_stab_thresh = strtol(argv[argc], &endptr, 0);
+			argc++;
+			pwrsel_params.pwr_stab_thresh = strtol(argv[argc], &endptr, 0);
+			argc++;
+			pwrsel_params.pwr_sel_exp_time = strtol(argv[argc], &endptr, 0);
+
+			/* Set powersel params */
+			err = wlu_iovar_set(wl, cmd->name, (void *) &pwrsel_params,
+				(sizeof(powersel_params_t)));
+		}
+		return err;
+	}
+
+	/* handle new lpc_params_t format support */
+	argv++;
+
+	if (*argv == NULL) {
+		/* get current powersel params */
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &lpc_params,
+			(sizeof(lpc_params_t)))) < 0)
+			return (err);
+
+		printf("- Link Power Control parameters (ver%d) -\n",
+			lpc_params.version);
+		printf("rate_stab_thresh\t= %d\npwr_stab_thresh\t\t= %d\n",
+			lpc_params.rate_stab_thresh, lpc_params.pwr_stab_thresh);
+		printf("lpc_exp_time\t\t= %d\npwrup_slow_step\t\t= %d\n",
+			lpc_params.lpc_exp_time, lpc_params.pwrup_slow_step);
+		printf("pwrup_fast_step\t\t= %d\npwrdn_slow_step\t\t= %d\n",
+			lpc_params.pwrup_fast_step, lpc_params.pwrdn_slow_step);
+	} else {
+		char *endptr;
+		/* Validate num of entries */
+		for (argc = 0; argv[argc]; argc++);
+		if (argc != 6)
+			return BCME_USAGE_ERROR;
+
+		lpc_params.version = WL_LPC_PARAMS_CURRENT_VERSION;
+		lpc_params.length = sizeof(lpc_params);
+
+		argc = 0;
+		lpc_params.rate_stab_thresh = strtol(argv[argc], &endptr, 0);
+		argc++;
+		lpc_params.pwr_stab_thresh = strtol(argv[argc], &endptr, 0);
+		argc++;
+		lpc_params.lpc_exp_time = strtol(argv[argc], &endptr, 0);
+		argc++;
+		lpc_params.pwrup_slow_step = strtol(argv[argc], &endptr, 0);
+		argc++;
+		lpc_params.pwrup_fast_step = strtol(argv[argc], &endptr, 0);
+		argc++;
+		lpc_params.pwrdn_slow_step = strtol(argv[argc], &endptr, 0);
+
+		/* Set powersel params */
+		err = wlu_iovar_set(wl, cmd->name, (void *) &lpc_params,
+			(sizeof(lpc_params_t)));
+	}
+
+	return err;
+}
+
+static int
+wl_channel(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	channel_info_t ci;
+
+	if (!*++argv) {
+		memset(&ci, 0, sizeof(ci));
+		if ((ret = wlu_get(wl, cmd->get, &ci, sizeof(channel_info_t))) < 0)
+			return ret;
+		ci.hw_channel = dtoh32(ci.hw_channel);
+		ci.scan_channel = dtoh32(ci.scan_channel);
+		ci.target_channel = dtoh32(ci.target_channel);
+		if (ci.scan_channel) {
+			printf("Scan in progress.\n");
+			printf("current scan channel\t%d\n", ci.scan_channel);
+		} else {
+			printf("No scan in progress.\n");
+		}
+		printf("current mac channel\t%d\n", ci.hw_channel);
+		printf("target channel\t%d\n", ci.target_channel);
+		return 0;
+	} else {
+		ci.target_channel = htod32(atoi(*argv));
+		ret =  wlu_set(wl, cmd->set, &ci.target_channel, sizeof(int));
+		return ret;
+	}
+}
+
+static int
+wl_chanspec(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_chanspec";
+	bool band_set = FALSE, ch_set = FALSE, bw_set = FALSE, ctl_sb_set = FALSE;
+	int err, opt_err;
+	uint32 val = 0;
+	chanspec_t chanspec = 0;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((err = wlu_iovar_getint(wl, cmd->name, (int*)&val)) < 0)
+			return err;
+
+		chanspec = wl_chspec32_from_driver(val);
+		wf_chspec_ntoa(chanspec, buf);
+		printf("%s (0x%x)\n", buf, chanspec);
+		return 0;
+	}
+
+
+	chanspec = wf_chspec_aton(*argv);
+	if (chanspec != 0) {
+		val = wl_chspec32_to_driver(chanspec);
+		if (val != INVCHANSPEC) {
+			err = wlu_iovar_setint(wl, cmd->name, val);
+		} else {
+			err = BCME_USAGE_ERROR;
+		}
+	} else {
+		miniopt_init(&to, fn_name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 'c') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" the channel\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val > 224) {
+					fprintf(stderr, "%s: invalid channel %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				chanspec |= to.val;
+				ch_set = TRUE;
+			}
+			if (to.opt == 'b') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for band\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 5) && (to.val != 2)) {
+					fprintf(stderr,
+						"%s: invalid band %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 5)
+					chanspec |= WL_CHANSPEC_BAND_5G;
+				else
+					chanspec |= WL_CHANSPEC_BAND_2G;
+				band_set = TRUE;
+			}
+			if (to.opt == 'w') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" bandwidth\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 20) && (to.val != 40) && (to.val != 80) &&
+					(to.val != 160)) {
+					fprintf(stderr,
+						"%s: invalid bandwidth %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 20)
+					chanspec |= WL_CHANSPEC_BW_20;
+				else if (to.val == 40)
+					chanspec |= WL_CHANSPEC_BW_40;
+				else if (to.val == 80)
+					chanspec |= WL_CHANSPEC_BW_80;
+				else
+					chanspec |= WL_CHANSPEC_BW_160;
+				bw_set = TRUE;
+			}
+			if (to.opt == 's') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" ctl sideband\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 1) && (to.val != 0) && (to.val != -1)) {
+					fprintf(stderr,
+						"%s: invalid ctl sideband %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == -1)
+					chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
+				else if (to.val == 1)
+					chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
+				ctl_sb_set = TRUE;
+			}
+		}
+
+		/* set ctl sb to 20 if not set and 20mhz is selected */
+		if (!ctl_sb_set && CHSPEC_IS20(chanspec)) {
+			ctl_sb_set = TRUE;
+		}
+
+		if (ch_set && band_set && bw_set && ctl_sb_set) {
+			val = wl_chspec32_to_driver(chanspec);
+			if (val != INVCHANSPEC) {
+				err = wlu_iovar_setint(wl, cmd->name, val);
+			} else {
+				err = BCME_USAGE_ERROR;
+			}
+		} else {
+			if (!ch_set)
+				fprintf(stderr, "%s: you need to set a channel,"
+					" '-c <ch>'\n", fn_name);
+			if (!band_set)
+				fprintf(stderr, "%s: you need to set a band,"
+					" '-b <5|2>'\n", fn_name);
+			if (!bw_set)
+				fprintf(stderr, "%s: you need to set a bandwidth,"
+					" '-w <20|40>'\n", fn_name);
+			if (!ctl_sb_set)
+				fprintf(stderr, "%s: you need to set a ctl sideband,"
+					  " '-s <-1|0|1>'\n", fn_name);
+			err = BCME_USAGE_ERROR;
+		}
+	}
+
+	if (!err)
+		printf("Chanspec set to 0x%x\n", chanspec);
+
+exit:
+	return err;
+}
+
+static int
+wl_sc_chan(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_sc_chan";
+	bool band_set = FALSE, ch_set = FALSE, bw_set = FALSE, ctl_sb_set = FALSE;
+	int err, opt_err;
+	uint32 val = 0;
+	chanspec_t chanspec = 0;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((err = wlu_iovar_getint(wl, cmd->name, (int*)&val)) < 0)
+			return err;
+
+		chanspec = wl_chspec32_from_driver(val);
+		wf_chspec_ntoa(chanspec, buf);
+		printf("%s (0x%x)\n", buf, chanspec);
+		return 0;
+	}
+
+	chanspec = wf_chspec_aton(*argv);
+	if (chanspec != 0) {
+		val = wl_chspec32_to_driver(chanspec);
+		if (val != INVCHANSPEC) {
+			err = wlu_iovar_setint(wl, cmd->name, val);
+		} else {
+			err = BCME_USAGE_ERROR;
+		}
+	} else {
+		miniopt_init(&to, fn_name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 'c') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" the channel\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val > 224) {
+					fprintf(stderr, "%s: invalid channel %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				chanspec |= to.val;
+				ch_set = TRUE;
+			}
+			if (to.opt == 'b') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for band\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 5) && (to.val != 2)) {
+					fprintf(stderr,
+						"%s: invalid band %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 5)
+					chanspec |= WL_CHANSPEC_BAND_5G;
+				else
+					chanspec |= WL_CHANSPEC_BAND_2G;
+				band_set = TRUE;
+			}
+			if (to.opt == 'w') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" bandwidth\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 20) && (to.val != 40) && (to.val != 80)) {
+					fprintf(stderr,
+						"%s: invalid bandwidth %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 20)
+					chanspec |= WL_CHANSPEC_BW_20;
+				else if (to.val == 40)
+					chanspec |= WL_CHANSPEC_BW_40;
+				else
+					chanspec |= WL_CHANSPEC_BW_80;
+				bw_set = TRUE;
+			}
+			if (to.opt == 's') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" ctl sideband\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 1) && (to.val != 0) && (to.val != -1)) {
+					fprintf(stderr,
+						"%s: invalid ctl sideband %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == -1)
+					chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
+				else if (to.val == 1)
+					chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
+				ctl_sb_set = TRUE;
+			}
+		}
+
+		/* set ctl sb to 20 if not set and 20mhz is selected */
+		if (!ctl_sb_set && CHSPEC_IS20(chanspec)) {
+			ctl_sb_set = TRUE;
+		}
+
+		if (ch_set && band_set && bw_set && ctl_sb_set) {
+			val = wl_chspec32_to_driver(chanspec);
+			if (val != INVCHANSPEC) {
+				err = wlu_iovar_setint(wl, cmd->name, val);
+			} else {
+				err = BCME_USAGE_ERROR;
+			}
+		} else {
+			if (!ch_set)
+				fprintf(stderr, "%s: you need to set a channel,"
+					" '-c <ch>'\n", fn_name);
+			if (!band_set)
+				fprintf(stderr, "%s: you need to set a band,"
+					" '-b <5|2>'\n", fn_name);
+			if (!bw_set)
+				fprintf(stderr, "%s: you need to set a bandwidth,"
+					" '-w <20|40>'\n", fn_name);
+			if (!ctl_sb_set)
+				fprintf(stderr, "%s: you need to set a ctl sideband,"
+					  " '-s <-1|0|1>'\n", fn_name);
+			err = BCME_USAGE_ERROR;
+		}
+	}
+
+	if (!err)
+		printf("SC Chanspec set to 0x%x\n", chanspec);
+
+exit:
+	return err;
+}
+
+static int
+wl_phy_vcore(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint32 val = 0;
+	uint8 bw80p80_cap  = 0;
+	uint8 ncore = 0;
+	uint8 hw_swmask_txchain = 0;
+	uint8 hw_swmask_rxchain = 0;
+	bool tx_80p80_valid = FALSE;
+	bool rx_80p80_valid = FALSE;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((err = wlu_iovar_getint(wl, cmd->name, (int*)&val)) < 0)
+			return err;
+		bw80p80_cap = (val >> 12) & 0x1;
+		/*
+		*	assume maximum core number is 4
+		*	bit extension is needed for future > 4-core design
+		*/
+		ncore = (val >> 8) & 0xf;
+		hw_swmask_txchain  = (val >> 4) & 0xf;
+		hw_swmask_rxchain  = val & 0xf;
+		printf("REAL160:NO\n");
+
+		if (bw80p80_cap == 1) {
+			if (ncore == 4) {
+				/* 80p80 for 4-core, 4365 */
+				tx_80p80_valid |= hw_swmask_txchain == 0xf;
+				tx_80p80_valid |= hw_swmask_txchain == 0xa;
+				tx_80p80_valid |= hw_swmask_txchain == 0x5;
+				rx_80p80_valid |= hw_swmask_rxchain == 0xf;
+				rx_80p80_valid |= hw_swmask_rxchain == 0xa;
+				rx_80p80_valid |= hw_swmask_rxchain == 0x5;
+				if (!(tx_80p80_valid) || !(rx_80p80_valid)) {
+					printf("80p80:NO\n");
+				} else {
+					printf("80p80:YES\n");
+					if (hw_swmask_txchain == 0xf) {
+						printf("tx_vcore=%d txchain= %d\n", 1, 5);
+						printf("tx_vcore=%d txchain=%d\n", 2, 10);
+						printf("tx_vcore=%d txchain=%d\n", 3, 15);
+					} else if (hw_swmask_txchain == 0xa) {
+						printf("tx_vcore=%d txchain=%d\n", 2, 10);
+					} else {
+						printf("tx_vcore=%d txchain= %d\n", 1, 5);
+					}
+					if (hw_swmask_rxchain == 0xf) {
+						printf("rx_vcore=%d rxchain= %d\n", 1, 5);
+						printf("rx_vcore=%d rxchain=%d\n", 2, 10);
+						printf("rx_vcore=%d rxchain=%d\n", 3, 15);
+					} else if (hw_swmask_rxchain == 0xa) {
+						printf("rx_vcore=%d rxchain=%d\n", 2, 10);
+					} else {
+						printf("rx_vcore=%d rxchain= %d\n", 1, 5);
+					}
+				}
+			} else if (ncore == 2) {
+				/* 80p80 for 2-core, 4349 */
+				tx_80p80_valid |= hw_swmask_txchain == 0x3;
+				rx_80p80_valid |= hw_swmask_rxchain == 0x3;
+
+				if (!(tx_80p80_valid) || !(rx_80p80_valid)) {
+					printf("80p80:NO\n");
+				} else {
+					printf("80p80:YES\n");
+					printf("tx_vcore=%d txchain= %d\n", 1, 3);
+					printf("rx_vcore=%d rxchain= %d\n", 1, 3);
+				}
+			} else {
+				printf("!!!Number of cores should be 2 or 4!!!\n");
+			}
+		} else {
+			printf("80p80:NO\n");
+		}
+		return 0;
+	} else {
+		return BCME_UNSUPPORTED;
+	}
+}
+
+
+static int
+wl_dfs_ap_move(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	void *ptr;
+	const char* fn_name = "wl_dfs_ap_move";
+	bool band_set = FALSE, ch_set = FALSE, bw_set = FALSE, ctl_sb_set = FALSE;
+	int err, opt_err;
+	uint32 val = 0;
+	chanspec_t chanspec = 0;
+	int arg1;
+	struct wl_dfs_ap_move_status_v1 *status_v1;
+	struct wl_dfs_ap_move_status_v2 *status_v2;
+
+	char chanbuf[CHANSPEC_STR_LEN];
+	const char *dfs_state_str[DFS_SCAN_S_MAX] = {
+		"Radar Free On Channel",
+		"Radar Found On Channel",
+		"Radar Scan In Progress",
+		"Radar Scan Aborted",
+		"RSDB Mode switch in Progress For Scan"
+	};
+
+	/* toss the command name */
+	argv++;
+
+	/* GET */
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+
+		if ((err = wlu_var_getbuf_sm(wl, cmd->name, NULL, 0, &ptr))) {
+			printf("err=%d \n", err);
+			return err;
+		}
+
+		/* Check for firmware version */
+		if (wlc_ver_major(wl) <= 5) {
+
+			status_v1 = (struct wl_dfs_ap_move_status_v1*)ptr;
+
+			if (status_v1->dfs_status != DFS_SCAN_S_IDLE) {
+				chanspec = wl_chspec32_from_driver(status_v1->chanspec);
+				if (chanspec != 0 && chanspec != INVCHANSPEC) {
+					wf_chspec_ntoa(chanspec, chanbuf);
+					printf("AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
+				}
+				printf("%s\n", dfs_state_str[status_v1->dfs_status]);
+				err = wl_print_dfs_status(&status_v1->cac_status);
+
+			} else
+				printf("dfs AP move in IDLE state\n");
+
+			return err;
+		} else {
+			status_v2 = (struct wl_dfs_ap_move_status_v2*)ptr;
+
+			if (status_v2->version != WL_DFS_AP_MOVE_VERSION) {
+				err = BCME_UNSUPPORTED;
+				printf("err=%d version=%d\n", err, status_v2->version);
+				return err;
+			}
+
+			printf("version=%d, move status=%d\n", status_v2->version,
+				status_v2->move_status);
+
+			if (status_v2->move_status != (int8) DFS_SCAN_S_IDLE) {
+				chanspec = wl_chspec32_from_driver(status_v2->chanspec);
+				if (chanspec != 0 && chanspec != INVCHANSPEC) {
+					wf_chspec_ntoa(chanspec, chanbuf);
+					printf("AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
+				}
+				printf("%s\n", dfs_state_str[status_v2->move_status]);
+				err = wl_print_dfs_status_all(&status_v2->scan_status);
+
+			} else {
+				printf("dfs AP move in IDLE state\n");
+				err = wl_print_dfs_status_all(&status_v2->scan_status);
+			}
+
+			return err;
+		}
+	}
+
+
+	/* SET */
+	arg1 = atoi(*argv);
+	chanspec = wf_chspec_aton(*argv);
+
+	if (arg1 == WL_DFS_AP_MOVE_ABORT || arg1 == WL_DFS_AP_MOVE_STUNT) {
+		err = wlu_iovar_setint(wl, cmd->name, arg1);
+	} else if (chanspec != 0) {
+		val = wl_chspec32_to_driver(chanspec);
+		if (val != INVCHANSPEC) {
+			err = wlu_iovar_setint(wl, cmd->name, val);
+		} else {
+			err = BCME_USAGE_ERROR;
+		}
+	} else {
+		miniopt_init(&to, fn_name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 'c') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" the channel\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val > 224) {
+					fprintf(stderr, "%s: invalid channel %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				chanspec |= to.val;
+				ch_set = TRUE;
+			}
+			if (to.opt == 'b') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for band\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val != 5) {
+					fprintf(stderr,
+						"%s: invalid band %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				chanspec |= WL_CHANSPEC_BAND_5G;
+				band_set = TRUE;
+			}
+			if (to.opt == 'w') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" bandwidth\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 20) && (to.val != 40) && (to.val != 80)) {
+					fprintf(stderr,
+						"%s: invalid bandwidth %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 20)
+					chanspec |= WL_CHANSPEC_BW_20;
+				else if (to.val == 40)
+					chanspec |= WL_CHANSPEC_BW_40;
+				else
+					chanspec |= WL_CHANSPEC_BW_80;
+				bw_set = TRUE;
+			}
+			if (to.opt == 's') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for"
+						" ctl sideband\n", fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 1) && (to.val != 0) && (to.val != -1)) {
+					fprintf(stderr,
+						"%s: invalid ctl sideband %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == -1)
+					chanspec |= WL_CHANSPEC_CTL_SB_LOWER;
+				else if (to.val == 1)
+					chanspec |= WL_CHANSPEC_CTL_SB_UPPER;
+				ctl_sb_set = TRUE;
+			}
+		}
+
+		/* set ctl sb to 20 if not set and 20mhz is selected */
+		if (!ctl_sb_set && CHSPEC_IS20(chanspec)) {
+			ctl_sb_set = TRUE;
+		}
+
+		if (ch_set && band_set && bw_set && ctl_sb_set) {
+			val = wl_chspec32_to_driver(chanspec);
+			if (val != INVCHANSPEC) {
+				err = wlu_iovar_setint(wl, cmd->name, val);
+			} else {
+				err = BCME_USAGE_ERROR;
+			}
+		} else {
+			if (!ch_set)
+				fprintf(stderr, "%s: you need to set a channel,"
+					" '-c <ch>'\n", fn_name);
+			if (!band_set)
+				fprintf(stderr, "%s: you need to set a band,"
+					" '-b <5|2>'\n", fn_name);
+			if (!bw_set)
+				fprintf(stderr, "%s: you need to set a bandwidth,"
+					" '-w <20|40>'\n", fn_name);
+			if (!ctl_sb_set)
+				fprintf(stderr, "%s: you need to set a ctl sideband,"
+					  " '-s <-1|0|1>'\n", fn_name);
+			err = BCME_USAGE_ERROR;
+		}
+	}
+
+exit:
+	return err;
+}
+
+static int
+wl_dfs_max_safe_tx(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint argc, num_vals = 0;
+	uint32 *pvals, vals[3];
+	char *endptr = NULL;
+
+	/* pop command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argc < 4 && argv[argc]; argc++); /* empty loop */
+
+	/* get case */
+	if (argc < 1) {
+		if (cmd->get < 0) {
+			return -1;
+		}
+
+		if ((err = wlu_var_getbuf_sm(wl, cmd->name, NULL, 0, (void**)&pvals)) || !pvals) {
+			printf("err=%d \n", err);
+			return err;
+		}
+
+		pvals[0] = dtoh32(pvals[0]);
+		pvals[1] = dtoh32(pvals[1]);
+		pvals[2] = dtoh32(pvals[2]);
+		printf("non-adjacent=%u%%, adjacent=%u%%, eu-weather=%u%%\n",
+				pvals[0], pvals[1], pvals[2]);
+
+		return err;
+	}
+
+	/* set case */
+	if (cmd->get < 0) {
+		return -1;
+	}
+	vals[num_vals++] = htod32(strtol(argv[0], &endptr, 0));
+	if (argc > 1) {
+		vals[num_vals++] = htod32(strtol(argv[1], &endptr, 0));
+	}
+	if (argc > 2) {
+		vals[num_vals++] = htod32(strtol(argv[2], &endptr, 0));
+	}
+
+	if ((err = wlu_var_setbuf_sm(wl, cmd->name, vals, sizeof(*vals)*(num_vals))) != BCME_OK) {
+		printf("err=%d\n", err);
+		return err;
+	}
+
+	return err;
+}
+
+static int
+wl_rclass(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_USAGE_ERROR;
+	chanspec_t chanspec = 0;
+	void *ptr;
+
+	/* toss the command name */
+	argv++;
+
+	if (*argv) {
+		chanspec = wf_chspec_aton(*argv);
+		if (chanspec != 0) {
+			err = wlu_var_getbuf(wl, cmd->name, &chanspec, sizeof(chanspec_t), &ptr);
+
+			if (err)
+				printf("Read rclass fails: chanspec:0x%x\n", chanspec);
+			else
+				printf("rclass=0x%x\n", *((int *)ptr));
+		}
+	}
+
+	return err;
+}
+
+int
+wl_ether_atoe(const char *a, struct ether_addr *n)
+{
+	char *c = NULL;
+	int i = 0;
+
+	memset(n, 0, ETHER_ADDR_LEN);
+	for (;;) {
+		n->octet[i++] = (uint8)strtoul(a, &c, 16);
+		if (!*c++ || i == ETHER_ADDR_LEN)
+			break;
+		a = c;
+	}
+	return (i == ETHER_ADDR_LEN);
+}
+char *
+wl_ether_etoa(const struct ether_addr *n)
+{
+	static char etoa_buf[ETHER_ADDR_LEN * 3];
+	char *c = etoa_buf;
+	int i;
+
+	for (i = 0; i < ETHER_ADDR_LEN; i++) {
+		if (i)
+			*c++ = ':';
+		c += sprintf(c, "%02X", n->octet[i] & 0xff);
+	}
+	return etoa_buf;
+}
+
+int
+wl_atoip(const char *a, struct ipv4_addr *n)
+{
+	char *c = NULL;
+	int i = 0;
+
+	for (;;) {
+		n->addr[i++] = (uint8)strtoul(a, &c, 0);
+		if (*c++ != '.' || i == IPV4_ADDR_LEN)
+			break;
+		a = c;
+	}
+	return (i == IPV4_ADDR_LEN);
+}
+
+
+int wl_ipv6_colon(const char *a, char *x)
+{
+	int     i;
+	const char	*t;
+	int     colons = 0;
+	int     double_colons = 0;
+	int     zero_req = 0;
+
+	if (*a == ':' && *(a+1) != ':')
+		return 1;		/* Illegal */
+	t = a;
+	while ((t = strstr(t, "::")) != NULL) {
+		++t;
+	++double_colons;
+	}
+
+	if (double_colons == 0) {
+	strcpy(x, a);			/* No double colon in the address */
+	return 0;
+	}
+
+	if (double_colons > 1) {
+	return 1;			/* Illegal */
+	}
+	t = a;
+	while ((t = strchr(t, ':')) != NULL) {
+		++t;
+		++colons;
+	}
+	zero_req = 8 - colons;
+	if (zero_req) {
+	t = a;
+		while (*t) {
+			if (*t == ':' && *(t+1) == ':') {
+				if (t == a) {
+					*x++ = '0';
+				}
+				*x++ = *t++;
+				for (i = 0; i < zero_req; i++) {
+					*x++ = '0';
+					*x++ = ':';
+				}
+				t++;
+				} else {
+				*x++ = *t++;
+			}
+		}
+	} else {
+		strcpy(x, a);
+	}
+		return 0;
+}
+
+int
+wl_atoipv6(const char *a, struct ipv6_addr *n)
+{
+	char *c = NULL;
+	int i = 0;
+	uint16 *addr16;
+	char x[64];
+	char *t = x;
+
+	memset(x, 0, 64);
+
+	if (wl_ipv6_colon(a, x) == 1) {
+		return 0;
+	}
+
+	for (;;) {
+		addr16 = (uint16 *)&n->addr[i];
+		*addr16 = hton16((uint16)strtoul((char *)t, &c, 16));
+		i += 2;
+		if (*c++ != ':' || i == IPV6_ADDR_LEN)
+			break;
+		t = c;
+	}
+
+	return (i == IPV6_ADDR_LEN);
+}
+
+char *
+wl_ipv6toa(const void *ipv6)
+{
+	/* Implementing RFC 5952 Sections 4 + 5 */
+	/* Not thoroughly tested */
+	uint16 *a = (uint16 *)ipv6;
+
+	/* Returned buffer is from a static circular pool to permit several calls in a printf */
+#define IPV6_BUFFER_CNT	4
+	static char buffer[IPV6_BUFFER_CNT][IPV6_ADDR_LEN * 4];
+	static int idx = 0;
+
+	char *p = buffer[idx++ % IPV6_BUFFER_CNT];
+	int i, i_max = -1, cnt = 0, cnt_max = 1;
+	uint8 *a4 = NULL;
+
+	for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
+		if (a[i]) {
+			if (cnt > cnt_max) {
+				cnt_max = cnt;
+				i_max = i - cnt;
+			}
+			cnt = 0;
+		} else
+			cnt++;
+	}
+	if (cnt > cnt_max) {
+		cnt_max = cnt;
+		i_max = i - cnt;
+	}
+	if (i_max == 0 &&
+		/* IPv4-translated: ::ffff:0:a.b.c.d */
+		((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) ||
+		/* IPv4-mapped: ::ffff:a.b.c.d */
+		(cnt_max == 5 && a[5] == 0xffff)))
+		a4 = (uint8*) (a + 6);
+
+	for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
+		if ((uint8*) (a + i) == a4) {
+			sprintf(p, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]);
+			break;
+		} else if (i == i_max) {
+			*p++ = ':';
+			i += cnt_max - 1;
+			p[0] = ':';
+			p[1] = '\0';
+		} else {
+			if (i)
+				*p++ = ':';
+			p += sprintf(p, "%x", ntoh16(a[i]));
+		}
+	}
+
+	/* Sub-buffer start is found back by rounding p with the sub-buffer size */
+	return buffer[(p - buffer[0]) / sizeof(buffer[0])];
+}
+
+char *
+wl_iptoa(const struct ipv4_addr *n)
+{
+	static char iptoa_buf[IPV4_ADDR_LEN * 4];
+
+	sprintf(iptoa_buf, "%u.%u.%u.%u",
+	        n->addr[0], n->addr[1], n->addr[2], n->addr[3]);
+
+	return iptoa_buf;
+}
+
+int
+wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
+{
+	int i, c;
+	char *p = ssid_buf;
+
+	if (ssid_len > 32)
+		ssid_len = 32;
+
+	for (i = 0; i < ssid_len; i++) {
+		c = (int)ssid[i];
+		if (c == '\\') {
+			*p++ = '\\';
+			*p++ = '\\';
+		} else if (isprint((uchar)c)) {
+			*p++ = (char)c;
+		} else {
+			p += sprintf(p, "\\x%02X", c);
+		}
+	}
+	*p = '\0';
+
+	return p - ssid_buf;
+}
+
+/* pretty hex print a contiguous buffer */
+void
+wl_hexdump(uchar *dump_buf, uint nbytes)
+{
+	char line[256];
+	char* p;
+	uint i;
+
+	if (nbytes == 0) {
+		printf("\n");
+		return;
+	}
+
+	p = line;
+	for (i = 0; i < nbytes; i++) {
+		if (i % 16 == 0 && nbytes > 16) {
+			p += sprintf(p, "%04d: ", i);	/* line prefix */
+		}
+		p += sprintf(p, "%02x ", dump_buf[i]);
+		if (i % 16 == 15) {
+			printf("%s\n", line);		/* flush line */
+			p = line;
+		}
+	}
+
+	/* flush last partial line */
+	if (p != line)
+		printf("%s\n", line);
+}
+
+static int
+wl_plcphdr(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+
+	if (!*++argv) {
+		if ((ret = wlu_get(wl, cmd->get, &val, sizeof(int))) < 0)
+			return ret;
+		val = dtoh32(val);
+		if (val == WLC_PLCP_AUTO)
+			printf("long");
+		else if (val == WLC_PLCP_SHORT)
+			printf("auto");
+		else if (val == WLC_PLCP_LONG)
+			printf("debug");
+		else
+			printf("unknown");
+		printf("\n");
+		return 0;
+	} else {
+		if (!stricmp(*argv, "long"))
+			val = WLC_PLCP_AUTO;
+		else if (!stricmp(*argv, "auto"))
+			val = WLC_PLCP_SHORT;
+		else if (!stricmp(*argv, "debug"))
+			val = WLC_PLCP_LONG;
+		else
+			return BCME_USAGE_ERROR;
+		val = htod32(val);
+		return wlu_set(wl, cmd->set, &val, sizeof(int));
+	}
+}
+
+/* WLC_GET_RADIO and WLC_SET_RADIO in driver operate on radio_disabled which
+ * is opposite of "wl radio [1|0]".  So invert for user.
+ * In addition, display WL_RADIO_SW_DISABLE and WL_RADIO_HW_DISABLE bits.
+ */
+static int
+wl_radio(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	uint val;
+	char *endptr = NULL;
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((ret = wlu_get(wl, cmd->get, &val, sizeof(int))) < 0)
+			return ret;
+		val = dtoh32(val);
+		printf("0x%04x\n", val);
+		return 0;
+	} else {
+		if (cmd->set < 0)
+			return -1;
+		if (!stricmp(*argv, "on"))
+			val = WL_RADIO_SW_DISABLE << 16;
+		else if (!stricmp(*argv, "off"))
+			val = WL_RADIO_SW_DISABLE << 16 | WL_RADIO_SW_DISABLE;
+		else {
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+
+			/* raw bits setting, add the mask if not provided */
+			if ((val >> 16) == 0) {
+				val |= val << 16;
+			}
+		}
+		val = htod32(val);
+		return wlu_set(wl, cmd->set, &val, sizeof(int));
+	}
+}
+
+char *
+ver2str(unsigned int vms, unsigned int vls)
+{
+	static char verstr[100];
+	unsigned int maj, year, month, day, build;
+
+	maj = (vms >> 16) & 0xFFFF;
+	if (maj > 1000) {
+		/* it is probably a date... */
+		year = (vms >> 16) & 0xFFFF;
+		month = vms & 0xFFFF;
+		day = (vls >> 16) & 0xFFFF;
+		build = vls & 0xFFFF;
+		sprintf(verstr, "%d/%d/%d build %d",
+			month, day, year, build);
+	} else {
+		/* it is a tagged release. */
+		sprintf(verstr, "%d.%d RC%d.%d",
+			(vms>>16)&0xFFFF, vms&0xFFFF,
+			(vls>>16)&0xFFFF, vls&0xFFFF);
+	}
+	return verstr;
+}
+
+
+static int
+wl_version(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int bcmerr = 0;
+	char *p = NULL;
+	char *dump_buf;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	printf("%s\n",
+		ver2str(((EPI_MAJOR_VERSION) << 16) | EPI_MINOR_VERSION,
+		(EPI_RC_NUMBER << 16) | EPI_INCREMENTAL_NUMBER));
+	dump_buf = malloc(WLC_IOCTL_SMLEN);
+	if (dump_buf == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n", WLC_IOCTL_SMLEN);
+		return BCME_NOMEM;
+	}
+	memset(dump_buf, 0, WLC_IOCTL_SMLEN);
+
+	/* query for 'ver' to get version info */
+	ret = wlu_iovar_get(wl, "ver", dump_buf, WLC_IOCTL_SMLEN);
+
+	/* if the query is successful, continue on and print the result. */
+
+	/* if the query fails, check for a legacy driver that does not support
+	 * the "dump" iovar, and instead issue a WLC_DUMP ioctl.
+	 */
+	if (ret) {
+		err = wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+		if (!err && (bcmerr == BCME_UNSUPPORTED)) {
+			ret = wlu_get(wl, WLC_DUMP, dump_buf, WLC_IOCTL_SMLEN);
+		}
+	}
+
+	if (ret) {
+		fprintf(stderr, "Error %d on query of driver dump\n", (int)ret);
+		free(dump_buf);
+		return ret;
+	}
+
+	/* keep only the first line from the dump buf output */
+	p = strchr(dump_buf, '\n');
+	if (p)
+		*p = '\0';
+	printf("%s\n", dump_buf);
+
+	free(dump_buf);
+
+	return 0;
+}
+
+static int
+wl_rateparam(void *wl, cmd_t *cmd, char **argv)
+{
+	int val[2];
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	val[0] = htod32(atoi(*argv));
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	val[1] = htod32(atoi(*argv));
+	return wlu_set(wl, cmd->set, val, sizeof(val));
+}
+
+/* wl scan
+ * -s --ssid=ssid_list
+ * -t T --scan_type=T : [active|passive]
+ * --bss_type=T : [infra|bss|adhoc|ibss]
+ * -b --bssid=
+ * -n --nprobes=
+ * -a --active=
+ * -p --passive=
+ * -h --home=
+ * -c --channels=
+ * ssid_list
+ */
+
+/* Parse a comma-separated list from list_str into ssid array, starting
+ * at index idx.  Max specifies size of the ssid array.  Parses ssids
+ * and returns updated idx; if idx >= max not all fit, the excess have
+ * not been copied.  Returns -1 on empty string, or on ssid too long.
+ */
+int
+wl_parse_ssid_list(char* list_str, wlc_ssid_t* ssid, int idx, int max)
+{
+	char *str, *ptr;
+
+	if (list_str == NULL)
+		return -1;
+
+	for (str = list_str; str != NULL; str = ptr) {
+		if ((ptr = strchr(str, ',')) != NULL)
+			*ptr++ = '\0';
+
+		if (strlen(str) > DOT11_MAX_SSID_LEN) {
+			fprintf(stderr, "ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN);
+			return -1;
+		}
+		if (strlen(str) == 0)
+			ssid[idx].SSID_len = 0;
+
+		if (idx < max) {
+			strcpy((char*)ssid[idx].SSID, str);
+			ssid[idx].SSID_len = strlen(str);
+		}
+		idx++;
+	}
+
+	return idx;
+}
+
+int
+wl_scan_prep(void *wl, cmd_t *cmd, char **argv, wl_scan_params_t *params, int *params_size)
+{
+	int val = 0;
+	char key[64];
+	int keylen;
+	char *p, *eq, *valstr, *endptr = NULL;
+	char opt;
+	bool positional_param;
+	bool good_int;
+	bool opt_end;
+	int err = 0;
+	int i;
+
+	int nchan = 0;
+	int nssid = 0;
+	wlc_ssid_t ssids[WL_SCAN_PARAMS_SSID_MAX];
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
+	params->bss_type = DOT11_BSSTYPE_ANY;
+	params->scan_type = 0;
+	params->nprobes = -1;
+	params->active_time = -1;
+	params->passive_time = -1;
+	params->home_time = -1;
+	params->channel_num = 0;
+	memset(ssids, 0, WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t));
+
+	/* skip the command name */
+	argv++;
+
+	opt_end = FALSE;
+	while ((p = *argv) != NULL) {
+		argv++;
+		positional_param = FALSE;
+		memset(key, 0, sizeof(key));
+		opt = '\0';
+		valstr = NULL;
+		good_int = FALSE;
+
+		if (opt_end) {
+			positional_param = TRUE;
+			valstr = p;
+		}
+		else if (!strcmp(p, "--")) {
+			opt_end = TRUE;
+			continue;
+		}
+		else if (!strncmp(p, "--", 2)) {
+			eq = strchr(p, '=');
+			if (eq == NULL) {
+				fprintf(stderr,
+				"wl_scan: missing \" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			keylen = eq - (p + 2);
+			if (keylen > 63)
+				keylen = 63;
+			memcpy(key, p + 2, keylen);
+
+			valstr = eq + 1;
+			if (*valstr == '\0') {
+				fprintf(stderr,
+				"wl_scan: missing value after \" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		else if (!strncmp(p, "-", 1)) {
+			opt = p[1];
+			if (strlen(p) > 2) {
+				fprintf(stderr,
+				"wl_scan: only single char options, error on param \"%s\"\n", p);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (*argv == NULL) {
+				fprintf(stderr,
+				"wl_scan: missing value parameter after \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			valstr = *argv;
+			argv++;
+		} else {
+			positional_param = TRUE;
+			valstr = p;
+		}
+
+		/* parse valstr as int just in case */
+		val = (int)strtol(valstr, &endptr, 0);
+		if (*endptr == '\0') {
+			/* not all the value string was parsed by strtol */
+			good_int = TRUE;
+		}
+
+		if (opt == 's' || !strcmp(key, "ssid") || positional_param) {
+			nssid = wl_parse_ssid_list(valstr, ssids, nssid, WL_SCAN_PARAMS_SSID_MAX);
+			if (nssid < 0) {
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+
+		/* scan_type is a bitmap value and can have multiple options */
+		if (opt == 't' || !strcmp(key, "scan_type")) {
+			if (!strcmp(valstr, "active")) {
+				/* do nothing - scan_type is initialized outside of while loop */
+			} else if (!strcmp(valstr, "passive")) {
+				params->scan_type |= WL_SCANFLAGS_PASSIVE;
+			} else if (!strcmp(valstr, "prohibit")) {
+				params->scan_type |= WL_SCANFLAGS_PROHIBITED;
+			} else if (!strcmp(valstr, "offchan")) {
+				params->scan_type |= WL_SCANFLAGS_OFFCHAN;
+			} else if (!strcmp(valstr, "hotspot")) {
+				params->scan_type |= WL_SCANFLAGS_HOTSPOT;
+			} else {
+				fprintf(stderr,
+				"scan_type value should be \"active\", "
+				"\"passive\", \"prohibit\", \"offchan\" "
+				"or \"hotspot\", but got \"%s\"\n", valstr);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		if (!strcmp(key, "bss_type")) {
+			if (!strcmp(valstr, "bss") || !strcmp(valstr, "infra")) {
+				params->bss_type = DOT11_BSSTYPE_INFRASTRUCTURE;
+			} else if (!strcmp(valstr, "ibss") || !strcmp(valstr, "adhoc")) {
+				params->bss_type = DOT11_BSSTYPE_INDEPENDENT;
+			} else if (!strcmp(valstr, "any")) {
+				params->bss_type = DOT11_BSSTYPE_ANY;
+			} else {
+				fprintf(stderr,
+				"bss_type value should be "
+				"\"bss\", \"ibss\", or \"any\", but got \"%s\"\n", valstr);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		if (opt == 'b' || !strcmp(key, "bssid")) {
+			if (!wl_ether_atoe(valstr, &params->bssid)) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an ethernet MAC address\n", valstr);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		if (opt == 'n' || !strcmp(key, "nprobes")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an int for value nprobes\n", valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->nprobes = val;
+		}
+		if (opt == 'a' || !strcmp(key, "active")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an int for active dwell time\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->active_time = val;
+		}
+		if (opt == 'p' || !strcmp(key, "passive")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an int for passive dwell time\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->passive_time = val;
+		}
+		if (opt == 'h' || !strcmp(key, "home")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an int for home channel dwell time\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->home_time = val;
+		}
+		if (opt == 'c' || !strcmp(key, "chanspecs")) {
+			nchan = wl_parse_chanspec_list(valstr, params->channel_list,
+			                              WL_NUMCHANNELS);
+			if (nchan == -1) {
+				fprintf(stderr, "error parsing chanspec list arg\n");
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+	}
+
+	if (nssid > WL_SCAN_PARAMS_SSID_MAX) {
+		fprintf(stderr, "ssid count %d exceeds max of %d\n",
+		        nssid, WL_SCAN_PARAMS_SSID_MAX);
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	params->nprobes = htod32(params->nprobes);
+	params->active_time = htod32(params->active_time);
+	params->passive_time = htod32(params->passive_time);
+	params->home_time = htod32(params->home_time);
+
+	for (i = 0; i < nchan; i++) {
+		params->channel_list[i] = htodchanspec(params->channel_list[i]);
+	}
+
+	for (i = 0; i < nssid; i++) {
+		ssids[i].SSID_len = htod32(ssids[i].SSID_len);
+	}
+
+	/* For a single ssid, use the single fixed field */
+	if (nssid == 1) {
+		nssid = 0;
+		memcpy(&params->ssid, &ssids[0], sizeof(ssids[0]));
+	}
+
+	/* Copy ssid array if applicable */
+	if (nssid > 0) {
+		i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16);
+		i = ROUNDUP(i, sizeof(uint32));
+		if (i + nssid * sizeof(wlc_ssid_t) > (uint)*params_size) {
+			fprintf(stderr, "additional ssids exceed params_size\n");
+			err = BCME_BADARG;
+			goto exit;
+		}
+
+		p = (char*)params + i;
+		memcpy(p, ssids, nssid * sizeof(wlc_ssid_t));
+		p += nssid * sizeof(wlc_ssid_t);
+	} else {
+		p = (char*)params->channel_list + nchan * sizeof(uint16);
+	}
+
+	params->channel_num = htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) |
+	                             (nchan & WL_SCAN_PARAMS_COUNT_MASK));
+	*params_size = p - (char*)params + nssid * sizeof(wlc_ssid_t);
+exit:
+	return err;
+}
+
+
+static int
+wl_roamparms(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size;
+	wl_scan_params_t *params;
+	int err = 0;
+
+	params_size = WL_MAX_ROAMSCAN_DATSZ;
+	params = (wl_scan_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	if (!(argv[1])) {
+#ifdef BCMDBG
+		printf("GET roam scan params\n");
+#endif
+	/* no data to copy here for a get */
+	err = wlu_iovar_getbuf(wl, "roamscan_parms", params, 0,
+		buf, WLC_IOCTL_MEDLEN);
+	if (err) {
+		fprintf(stderr, "Error retrieving roamscan params: %d\n", err);
+		goto done;
+	}
+
+#ifdef BCMDBG
+		prhex(NULL, (void *)buf, 64);
+#endif
+		memset(params, 0, params_size);
+		memcpy(params, buf, params_size);
+
+		printf("Roam Scan Parameters:\n");
+		printf("scan_type: %d\n", dtoh32(params->scan_type));
+		printf("nprobes: %d\n", dtoh32(params->nprobes));
+		printf("active_time: %d\n", dtoh32(params->active_time));
+		printf("passive_time: %d\n", dtoh32(params->passive_time));
+		printf("home_time: %d\n", dtoh32(params->home_time));
+
+		/* print out the channels, if any */
+		if (params->channel_num) {
+			uint32 i;
+			uint32 chcount = dtoh32(params->channel_num);
+			printf("Channels:\n");
+			for (i = 0; i < chcount; i++)
+				printf("Channel number 0x%x\n", dtoh16(params->channel_list[i]));
+		}
+		/* No ssids to print out, ever */
+
+		goto done;
+	}
+
+
+	printf("Setting Roam Scan parameters \n");
+
+
+	err = wl_scan_prep(wl, cmd, argv, params, &params_size);
+
+	if (err)
+		goto done;
+
+	printf("params_size %d\n", params_size);
+	err = wlu_iovar_setbuf(wl, "roamscan_parms", params, params_size, buf, WLC_IOCTL_MEDLEN);
+
+done:
+	free(params);
+	return err;
+}
+
+#ifdef WLRCC
+static int
+wl_roamchannels(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size;
+	wl_roam_channel_list_t *params;
+	int i, chcount, chspec;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	params_size = sizeof(*params);
+	params = (wl_roam_channel_list_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan channels\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	if (!(argv[1])) {
+		/* no data to copy here for a get */
+		err = wlu_iovar_getbuf(wl, "roamscan_channels", params, 0,
+			buf, WLC_IOCTL_MEDLEN);
+		if (err) {
+			fprintf(stderr, "Error retrieving roamscan channels: %d\n", err);
+			goto done;
+		}
+
+		memcpy(params, buf, params_size);
+
+		chcount = dtoh32(params->n);
+		printf("Roam Scan Channels: %d\n", chcount);
+		for (i = 0; i < chcount; i++) {
+			chspec = dtoh16(params->channels[i]);
+			wf_chspec_ntoa(chspec, buf);
+			printf("Channel: %s (0x%x)\n", buf, chspec);
+		}
+		goto done;
+	}
+
+	printf("Setting Roam Scan channels not supported!!!\n");
+
+done:
+	free(params);
+	return err;
+}
+#endif /* WLRCC */
+
+static int
+wl_roam_prof(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	uint i;
+	void *ptr = NULL;
+	uint16	wl_rp_ver = WL_ROAM_PROF_VER_0;
+	uint wl_roam_prof_size = sizeof(wl_roam_prof_band_v1_t);
+	union {
+		wl_roam_prof_band_v1_t v1;
+		wl_roam_prof_band_v2_t v2;
+	} rp;
+
+	/* try to check wlc_ver first
+	 * for older FW (WLC interface revision <= 5), wl_roam_prof ver 0 is used;
+	 * for newer FW (WLC interface revision > 5), wl_roam_prof ver 1 is used;
+	 */
+	if (wlc_ver_major(wl) > 5) {
+		wl_rp_ver = WL_ROAM_PROF_VER_1;
+		wl_roam_prof_size = sizeof(wl_roam_prof_band_v2_t);
+	}
+
+	/* fill in some common fields among all roam_prof verisions */
+	++argv;
+	rp.v1.ver = wl_rp_ver;
+	if (*argv && (!strcmp(*argv, "b") || !strcmp(*argv, "2g"))) {
+		rp.v1.band = WLC_BAND_2G;
+	} else if (*argv && (!strcmp(*argv, "a") || !strcmp(*argv, "5g"))) {
+		rp.v1.band = WLC_BAND_5G;
+	} else
+		return -1;	/* Missing band */
+
+	/* roam_prof version get */
+	rp.v1.len = 0;
+	if ((ret = wlu_var_getbuf(wl, cmd->name, &rp, 8, &ptr)) < 0)
+		return ret;
+
+	memcpy(&rp, ptr, sizeof(rp));
+
+	if (dtoh16(rp.v1.ver) > WL_ROAM_PROF_VER_1) {
+		printf("\tIncorrect version: expected up to %d; got %d\n",
+				WL_ROAM_PROF_VER_1, dtoh16(rp.v1.ver));
+		return BCME_VERSION;
+	}
+
+	if (!*++argv) {
+		/* roam_prof get is done above. */
+		if ((rp.v1.len % wl_roam_prof_size) != 0)
+			printf("bad length (=%d) in return data\n", rp.v1.len);
+
+		for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
+			if ((i * wl_roam_prof_size) > rp.v1.len) break;
+
+			if (rp.v1.ver > WL_ROAM_PROF_VER_0) {
+				/* The full scan period must be non-zero for valid roam profile */
+				if (rp.v2.roam_prof[i].fullscan_period == 0) break;
+
+				printf("flag:%02x RSSI[%d,%d] delta:%d(%s) boost:%d.by.%d "
+				       "nfscan:%d period(full:%ds partial:%ds.x%d.%ds) "
+				       "CU(trigger:%d%% duration:%ds)\n",
+				       rp.v2.roam_prof[i].roam_flags,
+				       rp.v2.roam_prof[i].roam_trigger,
+				       rp.v2.roam_prof[i].rssi_lower,
+				       rp.v2.roam_prof[i].roam_delta,
+				       rp.v2.roam_prof[i].channel_usage ? "%" : "dBm",
+				       rp.v2.roam_prof[i].rssi_boost_thresh,
+				       rp.v2.roam_prof[i].rssi_boost_delta,
+				       rp.v2.roam_prof[i].nfscan,
+				       rp.v2.roam_prof[i].fullscan_period,
+				       rp.v2.roam_prof[i].init_scan_period,
+				       rp.v2.roam_prof[i].backoff_multiplier,
+				       rp.v2.roam_prof[i].max_scan_period,
+				       rp.v2.roam_prof[i].channel_usage,
+				       rp.v2.roam_prof[i].cu_avg_calc_dur);
+			} else {
+				/* The full scan period must be non-zero for valid roam profile */
+				if (rp.v1.roam_prof[i].fullscan_period == 0) break;
+
+				printf("flag:%02x RSSI[%d,%d] delta:%d(dBm) boost:%d.by.%d "
+				       "nfscan:%d period(full:%ds partial:%ds.x%d.%ds)\n",
+				       rp.v1.roam_prof[i].roam_flags,
+				       rp.v1.roam_prof[i].roam_trigger,
+				       rp.v1.roam_prof[i].rssi_lower,
+				       rp.v1.roam_prof[i].roam_delta,
+				       rp.v1.roam_prof[i].rssi_boost_thresh,
+				       rp.v1.roam_prof[i].rssi_boost_delta,
+				       rp.v1.roam_prof[i].nfscan,
+				       rp.v1.roam_prof[i].fullscan_period,
+				       rp.v1.roam_prof[i].init_scan_period,
+				       rp.v1.roam_prof[i].backoff_multiplier,
+				       rp.v1.roam_prof[i].max_scan_period);
+			}
+		}
+	} else {
+		/* set */
+		memset(&rp.v1.roam_prof[0], 0, wl_roam_prof_size * WL_MAX_ROAM_PROF_BRACKETS);
+		for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
+			if (rp.v1.ver > WL_ROAM_PROF_VER_0) {
+				if (!*argv) break;
+				rp.v2.roam_prof[i].roam_flags = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].roam_trigger = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].rssi_lower = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].roam_delta = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].rssi_boost_thresh = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].rssi_boost_delta = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].nfscan = htod16(atoi(*argv++));
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].fullscan_period = htod16(atoi(*argv++));
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].init_scan_period = htod16(atoi(*argv++));
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].backoff_multiplier = htod16(atoi(*argv++));
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].max_scan_period = htod16(atoi(*argv++));
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].channel_usage = htod16(atoi(*argv++));
+
+				if (!*argv) return -1;
+				rp.v2.roam_prof[i].cu_avg_calc_dur = htod16(atoi(*argv++));
+			} else {
+				if (!*argv) break;
+				rp.v1.roam_prof[i].roam_flags = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v1.roam_prof[i].roam_trigger = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v1.roam_prof[i].rssi_lower = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v1.roam_prof[i].roam_delta = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v1.roam_prof[i].rssi_boost_thresh = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v1.roam_prof[i].rssi_boost_delta = atoi(*argv++);
+
+				if (!*argv) return -1;
+				rp.v1.roam_prof[i].nfscan = htod16(atoi(*argv++));
+
+				if (!*argv) return -1;
+				rp.v1.roam_prof[i].fullscan_period = htod16(atoi(*argv++));
+
+				if (!*argv) return -1;
+				rp.v1.roam_prof[i].init_scan_period = htod16(atoi(*argv++));
+
+				if (!*argv) return -1;
+				rp.v1.roam_prof[i].backoff_multiplier = htod16(atoi(*argv++));
+
+				if (!*argv) return -1;
+				rp.v1.roam_prof[i].max_scan_period = htod16(atoi(*argv++));
+			}
+		}
+
+		if (i == 0) {
+			return -1;
+		}
+
+		if (*argv) {
+			/* too many parameters */
+			return -1;
+		}
+
+		rp.v1.len = wl_roam_prof_size * i;
+		ret = wlu_var_setbuf(wl, cmd->name, &rp, 8 + rp.v1.len);
+	}
+	return ret;
+}
+
+static int
+wl_scan(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+	wl_scan_params_t *params;
+	int err = 0;
+
+	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_scan_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	err = wl_scan_prep(wl, cmd, argv, params, &params_size);
+
+	if (!err) {
+		err = wlu_set(wl, cmd->set, params, params_size);
+	}
+
+	free(params);
+	return err;
+}
+
+static int
+wl_escan(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params)) +
+	    (WL_NUMCHANNELS * sizeof(uint16));
+	wl_escan_params_t *params;
+	int err = 0;
+	uint16 action = WL_SCAN_ACTION_START;
+
+	if (!stricmp(*argv, "escan"))
+		/* start an escan */
+		action = WL_SCAN_ACTION_START;
+	else if (!stricmp(*argv, "escanabort"))
+		/* abort an escan */
+		action = WL_SCAN_ACTION_ABORT;
+	else {
+		printf("unknown escan command: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_escan_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	err = wl_scan_prep(wl, cmd, argv, &params->params, &params_size);
+
+	if (!err) {
+		params->version = htod32(ESCAN_REQ_VERSION);
+		params->action = htod16(action);
+
+#if defined(linux)
+		srand((unsigned)time(NULL));
+		params->sync_id = htod16(rand() & 0xffff);
+#else
+		params->sync_id = htod16(4321);
+#endif /* #if defined(linux) */
+
+		params_size += OFFSETOF(wl_escan_params_t, params);
+		err = wlu_iovar_setbuf(wl, "escan", params, params_size, buf, WLC_IOCTL_MAXLEN);
+	}
+
+	free(params);
+	return err;
+}
+
+static int
+wl_iscan(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) +
+	    (WL_NUMCHANNELS * sizeof(uint16));
+	wl_iscan_params_t *params;
+	int err = 0;
+	uint16 action = WL_SCAN_ACTION_START;
+	char **p;
+	uint16 iscan_duration = 0;
+
+	if (!stricmp(*argv, "iscan_s"))
+		action = WL_SCAN_ACTION_START;
+	else if (!stricmp(*argv, "iscan_c"))
+		action = WL_SCAN_ACTION_CONTINUE;
+	else {
+		printf("unknown iscan command: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* look for iscan_duration parameter */
+	p = argv;
+	while (*p != NULL) {
+		if (!strcmp(*p, "-d") || !strncmp(*p, "--duration=", 11)) {
+			char *valptr;
+			int val;
+			char *endptr;
+			if (!strcmp(*p, "-d"))
+				valptr = *(++p);
+			else
+				valptr = *p + 11;
+			val = (int)strtol(valptr, &endptr, 0);
+			if (*endptr != '\0') {
+				fprintf(stderr,
+					"could not parse \"%s\" as an int for duration\n",
+					valptr);
+				err = -1;
+				goto exit;
+			}
+			iscan_duration = (uint16) val;
+			break;
+		}
+		++p;
+	}
+
+	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_iscan_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	err = wl_scan_prep(wl, cmd, argv, &params->params, &params_size);
+
+	if (!err) {
+		params->version = htod32(ISCAN_REQ_VERSION);
+		params->action = htod16(action);
+		params->scan_duration = htod16(iscan_duration);
+		params_size += OFFSETOF(wl_iscan_params_t, params);
+		err = wlu_iovar_setbuf(wl, "iscan", params, params_size, buf, WLC_IOCTL_MAXLEN);
+	}
+
+	free(params);
+exit:
+	return err;
+}
+
+static int
+wl_parse_assoc_params(char **argv, wl_assoc_params_t *params, bool *prescanned)
+{
+	int err = BCME_OK;
+	char *p, *eq, *valstr;
+	char opt;
+	bool opt_end;
+	int keylen;
+	char key[64];
+	int i;
+	bool bssid_set = FALSE;
+	bool ch_set = FALSE;
+
+	opt_end = FALSE;
+
+	while ((p = *argv) != NULL) {
+		argv++;
+		memset(key, 0, sizeof(key));
+		opt = '\0';
+		valstr = NULL;
+
+		if (opt_end) {
+			valstr = p;
+		}
+		else if (!strcmp(p, "--")) {
+			opt_end = TRUE;
+			continue;
+		}
+		else if (!strcmp(p, "prescanned")) {
+			if (prescanned)
+				*prescanned = TRUE;
+			continue;
+		}
+		else if (!strncmp(p, "--", 2)) {
+			eq = strchr(p, '=');
+			if (eq == NULL) {
+				fprintf(stderr, "wl_parse_assoc_params: missing \" = \" in "
+				        "long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			keylen = eq - (p + 2);
+			if (keylen > 63)
+				keylen = 63;
+			memcpy(key, p + 2, keylen);
+
+			valstr = eq + 1;
+			if (*valstr == '\0') {
+				fprintf(stderr, "wl_parse_assoc_params: missing value after "
+				        "\" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		else if (!strncmp(p, "-", 1)) {
+			opt = p[1];
+			if (strlen(p) > 2) {
+				fprintf(stderr, "wl_parse_assoc_params: only single char options, "
+				        "error on param \"%s\"\n", p);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (*argv == NULL) {
+				fprintf(stderr, "wl_parse_assoc_params: missing value parameter "
+				        "after \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			valstr = *argv++;
+		} else {
+			valstr = p;
+		}
+
+		/* handle -o v or --option=val */
+		if (opt == 'b' || !stricmp(key, "bssid")) {
+			if (!wl_ether_atoe(valstr, &params->bssid)) {
+				fprintf(stderr, "could not parse as an ethernet MAC address\n");
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			bssid_set = TRUE;
+		}
+		else if (opt == 'c' || !strcmp(key, "chanspecs")) {
+			params->chanspec_num =
+			     wl_parse_chanspec_list(valstr, params->chanspec_list, WL_NUMCHANNELS);
+			if (params->chanspec_num == -1) {
+				fprintf(stderr, "error parsing chanspec list arg\n");
+				err = BCME_BADARG;
+				goto exit;
+			}
+			ch_set = TRUE;
+		}
+	}
+
+	if (prescanned && *prescanned && (ch_set || bssid_set)) {
+		fprintf(stderr, "cannot use bssid/channel options with prescan option\n");
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	/* prepare the chanspec using the channel number and the user provided options */
+	for (i = 0; i < params->chanspec_num; i++) {
+		chanspec_t chanspec = wl_chspec_to_driver(params->chanspec_list[i]);
+		if (chanspec == INVCHANSPEC) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		params->chanspec_list[i] = chanspec;
+	}
+	params->chanspec_num = htod32(params->chanspec_num);
+
+exit:
+	return err;
+}
+
+/* wl reassoc <bssid>
+ * Options:
+ * -c CL, --chanspecs=CL, where CL is a comma or space separated list of chanspecs
+ */
+static int
+wl_reassoc(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = WL_REASSOC_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(chanspec_t);
+	wl_reassoc_params_t *params;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv == NULL) {
+		fprintf(stderr, "no arguments to wl_reassoc\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	params = (wl_reassoc_params_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	if (!wl_ether_atoe(*argv, &params->bssid)) {
+		fprintf(stderr, "could not parse %s as an Ethernet MAC address\n", *argv);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	/* default to plain old ioctl */
+	params_size = ETHER_ADDR_LEN;
+
+	if (*++argv != NULL) {
+		if ((err = wl_parse_reassoc_params(argv, params)) != BCME_OK) {
+			fprintf(stderr, "could not parse reassociation parameters\n");
+			goto exit;
+		}
+		params_size = WL_REASSOC_PARAMS_FIXED_SIZE +
+		        dtoh32(params->chanspec_num) * sizeof(chanspec_t);
+	}
+
+	err = wlu_set(wl, WLC_REASSOC, params, params_size);
+
+exit:
+	free(params);
+	return err;
+}
+
+int
+wl_parse_channel_list(char* list_str, uint16* channel_list, int channel_num)
+{
+	int num;
+	int val;
+	char* str;
+	char* endptr = NULL;
+
+	if (list_str == NULL)
+		return -1;
+
+	str = list_str;
+	num = 0;
+	while (*str != '\0') {
+		val = (int)strtol(str, &endptr, 0);
+		if (endptr == str) {
+			fprintf(stderr,
+				"could not parse channel number starting at"
+				" substring \"%s\" in list:\n%s\n",
+				str, list_str);
+			return -1;
+		}
+		str = endptr + strspn(endptr, " ,");
+
+		if (num == channel_num) {
+			fprintf(stderr, "too many channels (more than %d) in channel list:\n%s\n",
+				channel_num, list_str);
+			return -1;
+		}
+
+		channel_list[num++] = (uint16)val;
+	}
+
+	return num;
+}
+
+int
+wl_parse_chanspec_list(char *list_str, chanspec_t *chanspec_list, int chanspec_num)
+{
+	int num = 0;
+	chanspec_t chanspec;
+	char *next, str[8];
+	size_t len;
+
+	if ((next = list_str) == NULL)
+		return BCME_ERROR;
+
+	while ((len = strcspn(next, " ,")) > 0) {
+		if (len >= sizeof(str)) {
+			fprintf(stderr, "string \"%s\" before ',' or ' ' is too long\n", next);
+			return BCME_ERROR;
+		}
+		strncpy(str, next, len);
+		str[len] = 0;
+		chanspec = wf_chspec_aton(str);
+		if (chanspec == 0) {
+			fprintf(stderr, "could not parse chanspec starting at "
+			        "\"%s\" in list:\n%s\n", str, list_str);
+			return BCME_ERROR;
+		}
+		if (num == chanspec_num) {
+			fprintf(stderr, "too many chanspecs (more than %d) in chanspec list:\n%s\n",
+				chanspec_num, list_str);
+			return BCME_ERROR;
+		}
+		chanspec_list[num++] = chanspec;
+		next += len;
+		next += strspn(next, " ,");
+	}
+
+	return num;
+}
+
+static void bcm_print_vs_ie(uint8 *parse, int len)
+{
+	bcm_tlv_t *ie;
+
+	while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
+		int len_tmp = 0;
+		printf("VS_IE:");
+		printf("%02x%02x", ie->id, ie->len);
+		while (len_tmp < ie->len) {
+			printf("%02x", ie->data[len_tmp]);
+			len_tmp++;
+		}
+		printf("\n");
+
+		if ((parse = (uint8 *)bcm_next_tlv(ie, &len)) == NULL)
+			break;
+	}
+}
+
+/* channel info structure */
+typedef struct {
+	uint	chan;		/* channel number */
+	uint	freq;		/* in Mhz */
+} chan_info_t;
+
+static chan_info_t chan_info[] = {
+	/* B channels */
+	{ 1,	2412},
+	{ 2,	2417},
+	{ 3,	2422},
+	{ 4,	2427},
+	{ 5,	2432},
+	{ 6,	2437},
+	{ 7,	2442},
+	{ 8,	2447},
+	{ 9,	2452},
+	{ 10,	2457},
+	{ 11,	2462},
+	{ 12,	2467},
+	{ 13,	2472},
+	{ 14,	2484},
+
+	/* A channels */
+	/* 11a usa low */
+	{ 36,	5180},
+	{ 40,	5200},
+	{ 44,	5220},
+	{ 48,	5240},
+	{ 52,	5260},
+	{ 56,	5280},
+	{ 60,	5300},
+	{ 64,	5320},
+
+	/* 11a Europe */
+	{ 100,	5500},
+	{ 104,	5520},
+	{ 108,	5540},
+	{ 112,	5560},
+	{ 116,	5580},
+	{ 120,	5600},
+	{ 124,	5620},
+	{ 128,	5640},
+	{ 132,	5660},
+	{ 136,	5680},
+	{ 140,	5700},
+	{ 144,	5720},
+
+	/* 11a usa high */
+	{ 149,	5745},
+	{ 153,	5765},
+	{ 157,	5785},
+	{ 161,	5805},
+
+	/* 11a japan */
+	{ 184,	4920},
+	{ 188,	4940},
+	{ 192,	4960},
+	{ 196,	4980},
+	{ 200,	5000},
+	{ 204,	5020},
+	{ 208,	5040},
+	{ 212,	5060},
+	{ 216,	5080}
+};
+
+uint
+freq2channel(uint freq)
+{
+	int i;
+
+	for (i = 0; i < (int)ARRAYSIZE(chan_info); i++) {
+		if (chan_info[i].freq == freq)
+			return (chan_info[i].chan);
+	}
+	return (0);
+}
+
+void
+dump_rateset(uint8 *rates, uint count)
+{
+	uint i;
+	uint r;
+	bool b;
+
+	printf("[ ");
+	for (i = 0; i < count; i++) {
+		r = rates[i] & 0x7f;
+		b = rates[i] & 0x80;
+		if (r == 0)
+			break;
+		printf("%d%s%s ", (r / 2), (r % 2)?".5":"", b?"(b)":"");
+	}
+	printf("]");
+}
+
+/* Helper routine to print the infrastructure mode while pretty printing the BSS list */
+static const char *
+capmode2str(uint16 capability)
+{
+	capability &= (DOT11_CAP_ESS | DOT11_CAP_IBSS);
+
+	if (capability == DOT11_CAP_ESS)
+		return "Managed";
+	else if (capability == DOT11_CAP_IBSS)
+		return "Ad Hoc";
+	else
+		return "<unknown>";
+}
+
+/*
+ * Traverse a string of 1-byte tag/1-byte length/variable-length value
+ * triples, returning a pointer to the substring whose first element
+ * matches tag
+ */
+static uint8 *
+wlu_parse_tlvs(uint8 *tlv_buf, int buflen, uint key)
+{
+	uint8 *cp;
+	int totlen;
+
+	cp = tlv_buf;
+	totlen = buflen;
+
+	/* find tagged parameter */
+	while (totlen >= 2) {
+		uint tag;
+		int len;
+
+		tag = *cp;
+		len = *(cp +1);
+
+		/* validate remaining totlen */
+		if ((tag == key) && (totlen >= (len + 2)))
+			return (cp);
+
+		cp += (len + 2);
+		totlen -= (len + 2);
+	}
+
+	return NULL;
+}
+
+static int
+wlu_bcmp(const void *b1, const void *b2, int len)
+{
+	return (memcmp(b1, b2, len));
+}
+
+/* Is this body of this tlvs entry a WPA entry? If */
+/* not update the tlvs buffer pointer/length */
+static bool
+wlu_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, uint *tlvs_len)
+{
+	uint8 *ie = *wpaie;
+
+	/* If the contents match the WPA_OUI and type=1 */
+	if ((ie[1] >= 6) && !wlu_bcmp(&ie[2], WPA_OUI "\x01", 4)) {
+		return TRUE;
+	}
+
+	/* point to the next ie */
+	ie += ie[1] + 2;
+	/* calculate the length of the rest of the buffer */
+	*tlvs_len -= (int)(ie - *tlvs);
+	/* update the pointer to the start of the buffer */
+	*tlvs = ie;
+
+	return FALSE;
+}
+
+static void
+wl_dump_wpa_rsn_ies(uint8* cp, uint len)
+{
+	uint8 *parse = cp;
+	uint parse_len = len;
+	uint8 *wpaie;
+	uint8 *rsnie;
+
+	while ((wpaie = wlu_parse_tlvs(parse, parse_len, DOT11_MNG_WPA_ID)))
+		if (wlu_is_wpa_ie(&wpaie, &parse, &parse_len))
+			break;
+	if (wpaie)
+		wl_rsn_ie_dump((bcm_tlv_t*)wpaie);
+
+	rsnie = wlu_parse_tlvs(cp, len, DOT11_MNG_RSN_ID);
+	if (rsnie)
+		wl_rsn_ie_dump((bcm_tlv_t*)rsnie);
+
+	return;
+}
+
+static void
+wl_rsn_ie_dump(bcm_tlv_t *ie)
+{
+	int i;
+	int rsn;
+	wpa_ie_fixed_t *wpa = NULL;
+	rsn_parse_info_t rsn_info;
+	wpa_suite_t *suite;
+	uint8 std_oui[3];
+	int unicast_count = 0;
+	int akm_count = 0;
+	uint16 capabilities;
+	uint cntrs;
+	int err;
+
+	if (ie->id == DOT11_MNG_RSN_ID) {
+		rsn = TRUE;
+		memcpy(std_oui, WPA2_OUI, WPA_OUI_LEN);
+		err = wl_rsn_ie_parse_info(ie->data, ie->len, &rsn_info);
+	} else {
+		rsn = FALSE;
+		memcpy(std_oui, WPA_OUI, WPA_OUI_LEN);
+		wpa = (wpa_ie_fixed_t*)ie;
+		err = wl_rsn_ie_parse_info((uint8*)&wpa->version, wpa->length - WPA_IE_OUITYPE_LEN,
+		                           &rsn_info);
+	}
+	if (err || rsn_info.version != WPA_VERSION)
+		return;
+
+	if (rsn)
+		printf("RSN (WPA2):\n");
+	else
+		printf("WPA:\n");
+
+	/* Check for multicast suite */
+	if (rsn_info.mcast) {
+		printf("\tmulticast cipher: ");
+		if (!wlu_bcmp(rsn_info.mcast->oui, std_oui, 3)) {
+			switch (rsn_info.mcast->type) {
+			case WPA_CIPHER_NONE:
+				printf("NONE\n");
+				break;
+			case WPA_CIPHER_WEP_40:
+				printf("WEP64\n");
+				break;
+			case WPA_CIPHER_WEP_104:
+				printf("WEP128\n");
+				break;
+			case WPA_CIPHER_TKIP:
+				printf("TKIP\n");
+				break;
+			case WPA_CIPHER_AES_OCB:
+				printf("AES-OCB\n");
+				break;
+			case WPA_CIPHER_AES_CCM:
+				printf("AES-CCMP\n");
+				break;
+			default:
+				printf("Unknown-%s(#%d)\n", rsn ? "RSN" : "WPA",
+				       rsn_info.mcast->type);
+				break;
+			}
+		}
+		else {
+			printf("Unknown-%02X:%02X:%02X(#%d) ",
+			       rsn_info.mcast->oui[0], rsn_info.mcast->oui[1],
+			       rsn_info.mcast->oui[2], rsn_info.mcast->type);
+		}
+	}
+
+	/* Check for unicast suite(s) */
+	if (rsn_info.ucast) {
+		unicast_count = ltoh16_ua(&rsn_info.ucast->count);
+		printf("\tunicast ciphers(%d): ", unicast_count);
+		for (i = 0; i < unicast_count; i++) {
+			suite = &rsn_info.ucast->list[i];
+			if (!wlu_bcmp(suite->oui, std_oui, 3)) {
+				switch (suite->type) {
+				case WPA_CIPHER_NONE:
+					printf("NONE ");
+					break;
+				case WPA_CIPHER_WEP_40:
+					printf("WEP64 ");
+					break;
+				case WPA_CIPHER_WEP_104:
+					printf("WEP128 ");
+					break;
+				case WPA_CIPHER_TKIP:
+					printf("TKIP ");
+					break;
+				case WPA_CIPHER_AES_OCB:
+					printf("AES-OCB ");
+					break;
+				case WPA_CIPHER_AES_CCM:
+					printf("AES-CCMP ");
+					break;
+				default:
+					printf("WPA-Unknown-%s(#%d) ", rsn ? "RSN" : "WPA",
+					       suite->type);
+					break;
+				}
+			}
+			else {
+				printf("Unknown-%02X:%02X:%02X(#%d) ",
+					suite->oui[0], suite->oui[1], suite->oui[2],
+					suite->type);
+			}
+		}
+		printf("\n");
+	}
+	/* Authentication Key Management */
+	if (rsn_info.akm) {
+		akm_count = ltoh16_ua(&rsn_info.akm->count);
+		printf("\tAKM Suites(%d): ", akm_count);
+		for (i = 0; i < akm_count; i++) {
+			suite = &rsn_info.akm->list[i];
+			if (!wlu_bcmp(suite->oui, std_oui, 3)) {
+				switch (suite->type) {
+				case RSN_AKM_NONE:
+					printf("None ");
+					break;
+				case RSN_AKM_UNSPECIFIED:
+					printf("%s ", rsn ? "WPA2" : "WPA");
+					break;
+				case RSN_AKM_PSK:
+					printf("%s ", rsn ? "WPA2-PSK" : "WPA-PSK");
+					break;
+				case RSN_AKM_FBT_1X:
+					printf("FT-802.1x ");
+					break;
+				case RSN_AKM_FBT_PSK:
+					printf("FT-PSK ");
+					break;
+				default:
+					printf("Unknown-%s(#%d)  ",
+					       rsn ? "RSN" : "WPA", suite->type);
+					break;
+				}
+			}
+			else {
+				printf("Unknown-%02X:%02X:%02X(#%d)  ",
+					suite->oui[0], suite->oui[1], suite->oui[2],
+					suite->type);
+			}
+		}
+		printf("\n");
+	}
+
+	/* Capabilities */
+	if (rsn_info.capabilities) {
+		capabilities = ltoh16_ua(rsn_info.capabilities);
+		printf("\tCapabilities(0x%04x): ", capabilities);
+		if (rsn)
+			printf("%sPre-Auth, ", (capabilities & RSN_CAP_PREAUTH) ? "" : "No ");
+
+		printf("%sPairwise, ", (capabilities & RSN_CAP_NOPAIRWISE) ? "No " : "");
+
+		cntrs = wl_rsn_ie_decode_cntrs((capabilities & RSN_CAP_PTK_REPLAY_CNTR_MASK) >>
+		                               RSN_CAP_PTK_REPLAY_CNTR_SHIFT);
+
+		printf("%d PTK Replay Ctr%s", cntrs, (cntrs > 1)?"s":"");
+
+		if (rsn) {
+			cntrs = wl_rsn_ie_decode_cntrs(
+				(capabilities & RSN_CAP_GTK_REPLAY_CNTR_MASK) >>
+				RSN_CAP_GTK_REPLAY_CNTR_SHIFT);
+
+			printf("%d GTK Replay Ctr%s\n", cntrs, (cntrs > 1)?"s":"");
+		} else {
+			printf("\n");
+		}
+	} else {
+		printf("\tNo %s Capabilities advertised\n", rsn ? "RSN" : "WPA");
+	}
+
+}
+
+/* Validates and parses the RSN or WPA IE contents into a rsn_parse_info_t structure
+ * Returns 0 on success, or 1 if the information in the buffer is not consistant with
+ * an RSN IE or WPA IE.
+ * The buf pointer passed in should be pointing at the version field in either an RSN IE
+ * or WPA IE.
+ */
+static int
+wl_rsn_ie_parse_info(uint8* rsn_buf, uint len, rsn_parse_info_t *rsn)
+{
+	uint16 count;
+
+	memset(rsn, 0, sizeof(rsn_parse_info_t));
+
+	/* version */
+	if (len < sizeof(uint16))
+		return 1;
+
+	rsn->version = ltoh16_ua(rsn_buf);
+	len -= sizeof(uint16);
+	rsn_buf += sizeof(uint16);
+
+	/* Multicast Suite */
+	if (len < sizeof(wpa_suite_mcast_t))
+		return 0;
+
+	rsn->mcast = (wpa_suite_mcast_t*)rsn_buf;
+	len -= sizeof(wpa_suite_mcast_t);
+	rsn_buf += sizeof(wpa_suite_mcast_t);
+
+	/* Unicast Suite */
+	if (len < sizeof(uint16))
+		return 0;
+
+	count = ltoh16_ua(rsn_buf);
+
+	if (len < (sizeof(uint16) + count * sizeof(wpa_suite_t)))
+		return 1;
+
+	rsn->ucast = (wpa_suite_ucast_t*)rsn_buf;
+	len -= (sizeof(uint16) + count * sizeof(wpa_suite_t));
+	rsn_buf += (sizeof(uint16) + count * sizeof(wpa_suite_t));
+
+	/* AKM Suite */
+	if (len < sizeof(uint16))
+		return 0;
+
+	count = ltoh16_ua(rsn_buf);
+
+	if (len < (sizeof(uint16) + count * sizeof(wpa_suite_t)))
+		return 1;
+
+	rsn->akm = (wpa_suite_auth_key_mgmt_t*)rsn_buf;
+	len -= (sizeof(uint16) + count * sizeof(wpa_suite_t));
+	rsn_buf += (sizeof(uint16) + count * sizeof(wpa_suite_t));
+
+	/* Capabilites */
+	if (len < sizeof(uint16))
+		return 0;
+
+	rsn->capabilities = rsn_buf;
+
+	return 0;
+}
+
+static uint
+wl_rsn_ie_decode_cntrs(uint cntr_field)
+{
+	uint cntrs;
+
+	switch (cntr_field) {
+	case RSN_CAP_1_REPLAY_CNTR:
+		cntrs = 1;
+		break;
+	case RSN_CAP_2_REPLAY_CNTRS:
+		cntrs = 2;
+		break;
+	case RSN_CAP_4_REPLAY_CNTRS:
+		cntrs = 4;
+		break;
+	case RSN_CAP_16_REPLAY_CNTRS:
+		cntrs = 16;
+		break;
+	default:
+		cntrs = 0;
+		break;
+	}
+
+	return cntrs;
+}
+
+
+void
+wl_dump_raw_ie(bcm_tlv_t *ie, uint len)
+{
+	uint dump_len;
+
+	if (len == 0) {
+		return;
+	} else if (len == 1) {
+		printf("IE header truncated: ID: 0x%02X\n", ie->id);
+		return;
+	} else if (len < (uint)(ie->len + TLV_HDR_LEN)) {
+		printf("IE data truncated: ID: 0x%02X Len: %d\n", ie->id, ie->len);
+		dump_len = len - TLV_HDR_LEN;
+	} else {
+		printf("ID: 0x%02X Len: %d\n", ie->id, ie->len);
+		dump_len = ie->len;
+	}
+
+	/* choose how to format the data based on data len */
+	if (dump_len > 16)
+		printf("Data:\n");
+	else if (dump_len > 0)
+		printf("Data: ");
+
+	if (dump_len > 0)
+		wl_hexdump(ie->data, dump_len);
+
+	if (dump_len < ie->len)
+		printf("<missing %d bytes>\n", ie->len - dump_len);
+
+	return;
+}
+
+
+/* Pretty print the BSS list */
+static void
+dump_networks(char *network_buf)
+{
+	wl_scan_results_t *list = (wl_scan_results_t*)network_buf;
+	wl_bss_info_t *bi;
+	uint i;
+
+	if (list->count == 0)
+		return;
+	else if (list->version != WL_BSS_INFO_VERSION &&
+	         list->version != LEGACY2_WL_BSS_INFO_VERSION &&
+	         list->version != LEGACY_WL_BSS_INFO_VERSION) {
+		fprintf(stderr, "Sorry, your driver has bss_info_version %d "
+			"but this program supports only version %d.\n",
+			list->version, WL_BSS_INFO_VERSION);
+		return;
+	}
+
+	bi = list->bss_info;
+	for (i = 0; i < list->count; i++, bi = (wl_bss_info_t*)((int8*)bi + dtoh32(bi->length))) {
+		dump_bss_info(bi);
+	}
+}
+
+static void
+bcm_wps_version(uint8 *wps_ie)
+{
+	uint16 wps_len;
+	uint16 wps_off, wps_suboff;
+	uint16 wps_key;
+	uint8 wps_field_len;
+
+	wps_len = (uint16)*(wps_ie+TLV_LEN_OFF); /* Get the length of the WPS OUI header */
+	wps_off = WPS_OUI_FIXED_HEADER_OFF; /* Skip the fixed headers */
+	wps_field_len = 1;
+
+	/* Parsing the OUI header looking for version number */
+	while ((wps_len >= wps_off + 2) && (wps_field_len))
+	{
+		wps_key = (((uint8)wps_ie[wps_off]*256) + (uint8)wps_ie[wps_off+1]);
+		if (wps_key == WPS_ID_VENDOR_EXT) {
+			/* Key found */
+			wps_suboff = wps_off + WPS_OUI_HEADER_SIZE;
+
+			/* Looking for the Vendor extension code 0x00 0x37 0x2A
+			 * and the Version 2 sudId 0x00
+			 * if found then the next byte is the len of field which is always 1
+			 * for version field the byte after is the version number
+			 */
+			if (!wlu_bcmp(&wps_ie[wps_suboff],  WFA_VENDOR_EXT_ID, WPS_OUI_LEN)&&
+				(wps_ie[wps_suboff+WPS_WFA_SUBID_V2_OFF] == WPS_WFA_SUBID_VERSION2))
+			{
+				printf("V%d.%d ", (wps_ie[wps_suboff+WPS_WFA_V2_OFF]>>4),
+				(wps_ie[wps_suboff+WPS_WFA_V2_OFF] & 0x0f));
+				return;
+			}
+		}
+		/* Jump to next field */
+		wps_field_len = wps_ie[wps_off+WPS_OUI_HEADER_LEN+1];
+		wps_off += WPS_OUI_HEADER_SIZE + wps_field_len;
+	}
+
+	/* If nothing found from the parser then this is the WPS version 1.0 */
+	printf("V1.0 ");
+}
+
+static void
+bcm_is_wps_configured(uint8 *wps_ie)
+{
+	/* Before calling this function the test of WPS_OUI type 4 should be already done
+	 * If the contents match the WPS_OUI_SC_STATE
+	 */
+	uint16 wps_key;
+	wps_key = (wps_ie[WPS_SCSTATE_OFF]*256) + wps_ie[WPS_SCSTATE_OFF+1];
+	if ((wps_ie[TLV_LEN_OFF] > (WPS_SCSTATE_OFF+5))&&
+		(wps_key == WPS_ID_SC_STATE))
+	{
+		switch (wps_ie[WPS_SCSTATE_OFF+WPS_OUI_HEADER_SIZE])
+		{
+			case WPS_SCSTATE_UNCONFIGURED:
+				printf("Unconfigured\n");
+				break;
+			case WPS_SCSTATE_CONFIGURED:
+				printf("Configured\n");
+				break;
+			default:
+				printf("Unknown State\n");
+		}
+	}
+}
+
+/* Looking for WPS OUI in the propriatary_ie */
+static bool
+bcm_is_wps_ie(uint8 *ie, uint8 **tlvs, uint32 *tlvs_len)
+{
+	bool retval = FALSE;
+	/* If the contents match the WPS_OUI and type=4 */
+	if ((ie[TLV_LEN_OFF] > (WPS_OUI_LEN+1)) &&
+		!wlu_bcmp(&ie[TLV_BODY_OFF], WPS_OUI "\x04", WPS_OUI_LEN + 1)) {
+		retval = TRUE;
+	}
+
+	/* point to the next ie */
+	ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
+	/* calculate the length of the rest of the buffer */
+	*tlvs_len -= (int)(ie - *tlvs);
+	/* update the pointer to the start of the buffer */
+	*tlvs = ie;
+
+	return retval;
+}
+
+static void
+wl_dump_wps(uint8* cp, uint len)
+{
+	uint8 *parse = cp;
+	uint32 parse_len = len;
+	uint8 *proprietary_ie;
+
+	while ((proprietary_ie = wlu_parse_tlvs(parse, parse_len, DOT11_MNG_WPA_ID))) {
+		if (bcm_is_wps_ie(proprietary_ie, &parse, &parse_len)) {
+			/* Print WPS status */
+			printf("WPS: ");
+			/* Print the version get from vendor extension field */
+			bcm_wps_version(proprietary_ie);
+			/* Print the WPS configure or Unconfigure option */
+			bcm_is_wps_configured(proprietary_ie);
+			break;
+		}
+	}
+}
+
+/* vendor specific TLV match */
+static bool bcm_vs_ie_match(uint8 *ie, uint8 *oui, int oui_len, uint8 type)
+{
+	/* If the contents match the OUI and the type */
+	if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
+	    !wlu_bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
+	    type == ie[TLV_BODY_OFF + oui_len]) {
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static bcm_tlv_t *bcm_find_vs_ie(uint8 *parse, int len,
+	uint8 *oui, uint8 oui_len, uint8 oui_type)
+{
+	bcm_tlv_t *ie;
+
+	while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
+		if (bcm_vs_ie_match((uint8 *)ie, oui, oui_len, oui_type))
+			return ie;
+		if ((ie = bcm_next_tlv(ie, &len)) == NULL)
+			break;
+	}
+	return NULL;
+}
+
+static void
+wl_dump_ext_cap(uint8* cp, uint len)
+{
+	uint8 *parse = cp;
+	uint parse_len = len;
+	uint8 *ext_cap_ie;
+
+	if ((ext_cap_ie = wlu_parse_tlvs(parse, parse_len, DOT11_MNG_EXT_CAP_ID))) {
+		wl_ext_cap_ie_dump((bcm_tlv_t*)ext_cap_ie);
+	} else
+		printf("Extended Capabilities: Not_Available\n");
+
+}
+
+static void
+wl_ext_cap_ie_dump(bcm_tlv_t* ext_cap_ie)
+{
+
+	printf("Extended Capabilities: ");
+
+	if (ext_cap_ie->len >= CEIL(DOT11_EXT_CAP_IW, NBBY)) {
+		/* check IW bit */
+		if (isset(ext_cap_ie->data, DOT11_EXT_CAP_IW))
+			printf("IW ");
+	}
+
+	if (ext_cap_ie->len >= CEIL(DOT11_EXT_CAP_CIVIC_LOC, NBBY)) {
+		/* check Civic Location bit */
+		if (isset(ext_cap_ie->data, DOT11_EXT_CAP_CIVIC_LOC))
+			printf("Civic_Location ");
+	}
+
+	if (ext_cap_ie->len >= CEIL(DOT11_EXT_CAP_LCI, NBBY)) {
+		/* check Geospatial Location bit */
+		if (isset(ext_cap_ie->data, DOT11_EXT_CAP_LCI))
+			printf("Geospatial_Location ");
+	}
+
+	if (ext_cap_ie->len > 0) {
+		/* check 20/40 BSS Coexistence Management support bit */
+		if (isset(ext_cap_ie->data, DOT11_EXT_CAP_OBSS_COEX_MGMT))
+			printf("20/40_Bss_Coexist ");
+	}
+
+	if (ext_cap_ie->len >= CEIL(DOT11_EXT_CAP_BSSTRANS_MGMT, NBBY)) {
+		/* check BSS Transition Management support bit */
+		if (isset(ext_cap_ie->data, DOT11_EXT_CAP_BSSTRANS_MGMT))
+			printf("BSS_Transition");
+	}
+
+	printf("\n");
+}
+
+void
+dump_bss_info(wl_bss_info_t *bi)
+{
+	char ssidbuf[SSID_FMT_BUF_LEN];
+	char chspec_str[CHANSPEC_STR_LEN];
+	wl_bss_info_107_t *old_bi;
+	int mcs_idx = 0, start_idx = 0;
+	bool start_idx_valid = FALSE;
+	uint16 capability;
+
+	/* Convert version 107 to 109 */
+	if (dtoh32(bi->version) == LEGACY_WL_BSS_INFO_VERSION) {
+		old_bi = (wl_bss_info_107_t *)bi;
+		bi->chanspec = CH20MHZ_CHSPEC(old_bi->channel);
+		bi->ie_length = old_bi->ie_length;
+		bi->ie_offset = sizeof(wl_bss_info_107_t);
+	} else {
+		/* do endian swap and format conversion for chanspec if we have
+		 * not created it from legacy bi above
+		 */
+		bi->chanspec = wl_chspec_from_driver(bi->chanspec);
+	}
+
+	wl_format_ssid(ssidbuf, bi->SSID, bi->SSID_len);
+
+	printf("SSID: \"%s\"\n", ssidbuf);
+
+	printf("Mode: %s\t", capmode2str(dtoh16(bi->capability)));
+	printf("RSSI: %d dBm\t", (int16)(dtoh16(bi->RSSI)));
+
+	/*
+	 * SNR has valid value in only 109 version.
+	 * So print SNR for 109 version only.
+	 */
+	if (dtoh32(bi->version) == WL_BSS_INFO_VERSION) {
+		printf("SNR: %d dB\t", (int16)(dtoh16(bi->SNR)));
+	}
+
+	printf("noise: %d dBm\t", bi->phy_noise);
+	if (bi->flags) {
+		uint16 flags = dtoh16(bi->flags);
+		printf("Flags: ");
+		if (flags & WL_BSS_FLAGS_FROM_BEACON)
+			printf("FromBcn ");
+		if (flags & WL_BSS_FLAGS_FROM_CACHE)
+			printf("Cached ");
+		if (flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)
+			printf("RSSI on-channel ");
+		printf("\t");
+	}
+	printf("Channel: %s\n", wf_chspec_ntoa(bi->chanspec, chspec_str));
+
+	printf("BSSID: %s\t", wl_ether_etoa(&bi->BSSID));
+
+	printf("Capability: ");
+	capability = dtoh16(bi->capability);
+	if (capability & DOT11_CAP_ESS)
+		printf("ESS ");
+	if (capability & DOT11_CAP_IBSS)
+		printf("IBSS ");
+	if (capability & DOT11_CAP_POLLABLE)
+		printf("Pollable ");
+	if (capability & DOT11_CAP_POLL_RQ)
+		printf("PollReq ");
+	if (capability & DOT11_CAP_PRIVACY)
+		printf("WEP ");
+	if (capability & DOT11_CAP_SHORT)
+		printf("ShortPre ");
+	if (capability & DOT11_CAP_PBCC)
+		printf("PBCC ");
+	if (capability & DOT11_CAP_AGILITY)
+		printf("Agility ");
+	if (capability & DOT11_CAP_SHORTSLOT)
+		printf("ShortSlot ");
+	if (capability & DOT11_CAP_RRM)
+		printf("RRM ");
+	if (capability & DOT11_CAP_CCK_OFDM)
+		printf("CCK-OFDM ");
+	printf("\n");
+
+	printf("Supported Rates: ");
+	dump_rateset(bi->rateset.rates, dtoh32(bi->rateset.count));
+	printf("\n");
+	if (dtoh32(bi->ie_length)) {
+		wl_dump_wpa_rsn_ies((uint8 *)(((uint8 *)bi) + dtoh16(bi->ie_offset)),
+		                    dtoh32(bi->ie_length));
+
+		wl_dump_ext_cap((uint8 *)(((uint8 *)bi) + dtoh16(bi->ie_offset)),
+		                    dtoh32(bi->ie_length));
+
+	}
+
+	if (dtoh32(bi->version) != LEGACY_WL_BSS_INFO_VERSION && bi->n_cap) {
+		if (bi->vht_cap)
+			printf("VHT Capable:\n");
+		else
+			printf("HT Capable:\n");
+		if (CHSPEC_IS8080(bi->chanspec)) {
+			 printf("\tChanspec: 5GHz channel %d-%d 80+80MHz (0x%x)\n",
+			 wf_chspec_primary80_channel(bi->chanspec),
+			 wf_chspec_secondary80_channel(bi->chanspec),
+			 bi->chanspec);
+		}
+		else {
+			printf("\tChanspec: %sGHz channel %d %dMHz (0x%x)\n",
+				CHSPEC_IS2G(bi->chanspec)?"2.4":"5", CHSPEC_CHANNEL(bi->chanspec),
+				(CHSPEC_IS160(bi->chanspec) ?
+				160:(CHSPEC_IS80(bi->chanspec) ?
+				80 : (CHSPEC_IS40(bi->chanspec) ?
+				40 : (CHSPEC_IS20(bi->chanspec) ? 20 : 10)))),
+				bi->chanspec);
+		}
+		printf("\tPrimary channel: %d\n", bi->ctl_ch);
+		printf("\tHT Capabilities: ");
+		if (dtoh32(bi->nbss_cap) & HT_CAP_40MHZ)
+			printf("40Mhz ");
+		if (dtoh32(bi->nbss_cap) & HT_CAP_SHORT_GI_20)
+			printf("SGI20 ");
+		if (dtoh32(bi->nbss_cap) & HT_CAP_SHORT_GI_40)
+			printf("SGI40 ");
+		printf("\n\tSupported HT MCS :");
+		for (mcs_idx = 0; mcs_idx < (MCSSET_LEN * 8); mcs_idx++) {
+			if (isset(bi->basic_mcs, mcs_idx) && !start_idx_valid) {
+				printf(" %d", mcs_idx);
+				start_idx = mcs_idx;
+				start_idx_valid = TRUE;
+			}
+
+			if (!isset(bi->basic_mcs, mcs_idx) && start_idx_valid) {
+				if ((mcs_idx - start_idx) > 1)
+					printf("-%d", (mcs_idx - 1));
+				start_idx_valid = FALSE;
+
+			}
+		}
+		printf("\n");
+
+		if (bi->vht_cap) {
+			int i;
+			uint mcs, rx_mcs, prop_mcs = VHT_PROP_MCS_MAP_NONE;
+			char *mcs_str, *rx_mcs_str;
+
+			if (bi->vht_mcsmap) {
+				printf("\tNegotiated VHT MCS:\n");
+				for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
+					mcs = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_mcsmap));
+
+					/* roundup to be in sync with driver
+					 * wlc_bss2wl_bss().
+					 */
+					if (dtoh16(bi->length) >= (OFFSETOF(wl_bss_info_t,
+						vht_mcsmap_prop) +
+						ROUNDUP(dtoh32(bi->ie_length), 4) +
+						sizeof(uint16))) {
+						prop_mcs = VHT_MCS_MAP_GET_MCS_PER_SS(i,
+							dtoh16(bi->vht_mcsmap_prop));
+					}
+					mcs_str =
+						(mcs == VHT_CAP_MCS_MAP_0_9 ? "0-9 " :
+						(mcs == VHT_CAP_MCS_MAP_0_8 ? "0-8 " :
+						(mcs == VHT_CAP_MCS_MAP_0_7 ? "0-7 " :
+						 " -- ")));
+					if (prop_mcs != VHT_PROP_MCS_MAP_NONE)
+						mcs_str =
+							(mcs == VHT_CAP_MCS_MAP_0_9 ? "0-11      " :
+							(mcs == VHT_CAP_MCS_MAP_0_8 ? "0-8, 10-11" :
+							(mcs == VHT_CAP_MCS_MAP_0_7 ? "0-7, 10-11" :
+							 "    --    ")));
+
+					if (mcs != VHT_CAP_MCS_MAP_NONE) {
+						printf("\t\tNSS%d : %s \n", i,
+							mcs_str);
+					}
+				}
+			} else {
+				printf("\tSupported VHT MCS:\n");
+				for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
+					mcs = VHT_MCS_MAP_GET_MCS_PER_SS(i,
+						dtoh16(bi->vht_txmcsmap));
+
+					rx_mcs = VHT_MCS_MAP_GET_MCS_PER_SS(i,
+						dtoh16(bi->vht_rxmcsmap));
+
+					/* roundup to be in sync with driver
+					 * wlc_bss2wl_bss().
+					 */
+					if (dtoh16(bi->length) >= (OFFSETOF(wl_bss_info_t,
+						vht_txmcsmap_prop) +
+						ROUNDUP(dtoh32(bi->ie_length), 4) +
+						sizeof(uint16))) {
+						prop_mcs = VHT_MCS_MAP_GET_MCS_PER_SS(i,
+							dtoh16(bi->vht_txmcsmap_prop));
+					}
+
+					mcs_str =
+						(mcs == VHT_CAP_MCS_MAP_0_9 ? "0-9 " :
+						(mcs == VHT_CAP_MCS_MAP_0_8 ? "0-8 " :
+						(mcs == VHT_CAP_MCS_MAP_0_7 ? "0-7 " : " -- ")));
+					if (prop_mcs != VHT_PROP_MCS_MAP_NONE)
+						mcs_str =
+						    (mcs == VHT_CAP_MCS_MAP_0_9 ? "0-11      " :
+						    (mcs == VHT_CAP_MCS_MAP_0_8 ? "0-8, 10-11" :
+						    (mcs == VHT_CAP_MCS_MAP_0_7 ? "0-7, 10-11" :
+						     "    --    ")));
+
+					rx_mcs_str =
+						(rx_mcs == VHT_CAP_MCS_MAP_0_9 ? "0-9 " :
+						(rx_mcs == VHT_CAP_MCS_MAP_0_8 ? "0-8 " :
+						(rx_mcs == VHT_CAP_MCS_MAP_0_7 ? "0-7 " : " -- ")));
+					if (prop_mcs != VHT_PROP_MCS_MAP_NONE)
+						rx_mcs_str =
+						    (rx_mcs == VHT_CAP_MCS_MAP_0_9 ? "0-11      " :
+						    (rx_mcs == VHT_CAP_MCS_MAP_0_8 ? "0-8, 10-11" :
+						    (rx_mcs == VHT_CAP_MCS_MAP_0_7 ? "0-7, 10-11" :
+						     "    --    ")));
+
+					if ((mcs != VHT_CAP_MCS_MAP_NONE) ||
+						(rx_mcs != VHT_CAP_MCS_MAP_NONE)) {
+						printf("\t\tNSS%d Tx: %s  Rx: %s\n", i,
+							mcs_str, rx_mcs_str);
+					}
+				}
+			}
+		}
+		bi->chanspec = wl_chspec_to_driver(bi->chanspec);
+	}
+
+	if (dtoh32(bi->ie_length))
+	{
+		wl_dump_wps((uint8 *)(((uint8 *)bi) + dtoh16(bi->ie_offset)),
+			dtoh32(bi->ie_length));
+	}
+
+	if (dtoh16(bi->flags) & WL_BSS_FLAGS_HS20) {
+		printf("Hotspot 2.0 capable\n");
+	}
+
+	if (bcm_find_vs_ie((uint8 *)(((uint8 *)bi) + dtoh16(bi->ie_offset)),
+		dtoh32(bi->ie_length),
+		(uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_OSEN) != NULL) {
+		printf("OSEN supported\n");
+	}
+	bcm_print_vs_ie((uint8 *)(((uint8 *)bi) + dtoh16(bi->ie_offset)),
+		dtoh32(bi->ie_length));
+
+	printf("\n");
+}
+
+static int
+wl_bcnlenhist(void *wl, cmd_t *cmd, char **argv)
+{
+	wlc_bcn_len_hist_t *bcnlenhist = NULL;
+	uint32 *bcns_len = NULL;
+	char* dump_buf = NULL;
+	uint32 counter = 0;
+	int	index = 0;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	dump_buf = malloc(WLC_IOCTL_SMLEN);
+	if (dump_buf == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n", WLC_IOCTL_SMLEN);
+		return -1;
+	}
+	memset(dump_buf, 0, WLC_IOCTL_SMLEN);
+
+	if (argv[1])
+		err = wlu_iovar_getbuf(wl, "bcnlenhist", argv[1], 1, dump_buf, WLC_IOCTL_SMLEN);
+	else
+		err = wlu_iovar_getbuf(wl, "bcnlenhist", NULL, 0, dump_buf, WLC_IOCTL_SMLEN);
+
+	if (BCME_OK == err) {
+		bcnlenhist = (wlc_bcn_len_hist_t *)dump_buf;
+
+		index = bcnlenhist->cur_index;
+		counter = bcnlenhist->ringbuff_len;
+		bcns_len = bcnlenhist->bcnlen_ring;
+
+		index--;
+		printf("LAST %d BEACON LENGTH's:  ", counter);
+		for (; counter--; index--) {
+			if (index < 0)
+				index = bcnlenhist->ringbuff_len - 1;
+			printf("%d  ", bcns_len[index]);
+		}
+
+		printf("\nMAX BCNLEN: %d\n", bcnlenhist->max_bcnlen);
+
+		if (bcnlenhist->min_bcnlen == (int)0x7fffffff)
+			printf("MIN BCNLEN: 0\n\n");
+		else
+			printf("MIN BCNLEN: %d\n\n", bcnlenhist->min_bcnlen);
+	}
+
+	free(dump_buf);
+
+	return err;
+}
+
+static int
+wl_dump_networks(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	char *dump_buf, *dump_buf_orig;
+	uint32 status = 0;
+	bool iscan = FALSE;
+
+	dump_buf_orig = dump_buf = malloc(WL_DUMP_BUF_LEN);
+	if (dump_buf == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n", WL_DUMP_BUF_LEN);
+		return BCME_NOMEM;
+	}
+
+	iscan = (cmd->get != WLC_SCAN_RESULTS);
+	if (iscan) {
+		int buflen = 1920;	/* usually fits about 10 BSS infos */
+
+		if (*(++argv)) {
+			char *endptr = NULL;
+			buflen = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		ret = wl_get_iscan(wl, dump_buf, buflen);
+	} else
+		ret = wl_get_scan(wl, WLC_SCAN_RESULTS, dump_buf, WL_DUMP_BUF_LEN);
+
+	if (ret == 0) {
+		if (iscan) {
+			status = dtoh32(((wl_iscan_results_t *)dump_buf)->status);
+			dump_buf += OFFSETOF(wl_iscan_results_t, results);
+		}
+		dump_networks(dump_buf);
+		if (iscan) {
+			switch (status) {
+			case WL_SCAN_RESULTS_PARTIAL:
+				printf("iscanresults incomplete\n");
+				break;
+			case WL_SCAN_RESULTS_SUCCESS:
+				printf("iscanresults complete\n");
+				break;
+			case WL_SCAN_RESULTS_PENDING:
+				printf("iscanresults pending\n");
+				break;
+			case WL_SCAN_RESULTS_ABORTED:
+				printf("iscanresults aborted\n");
+				break;
+			default:
+				printf("iscanresults returned unknown status %d\n", status);
+				break;
+			}
+		}
+	}
+
+exit:
+	free(dump_buf_orig);
+	return ret;
+}
+
+static int
+wl_dump_chanlist(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 chan_buf[WL_NUMCHANNELS + 1];
+	wl_uint32_list_t *list;
+	int ret;
+	uint i;
+
+	UNUSED_PARAMETER(argv);
+
+	list = (wl_uint32_list_t *)(void *)chan_buf;
+	list->count = htod32(WL_NUMCHANNELS);
+	ret = wlu_get(wl, cmd->get, chan_buf, sizeof(chan_buf));
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < dtoh32(list->count); i++)
+		printf("%d ", dtoh32(list->element[i]));
+	printf("\n");
+	return ret;
+}
+
+/* Dump chanspecs based on the driver's current configuration of band, band-width & locale. */
+static int
+wl_dump_chanspecs_defset(void *wl, cmd_t *cmd, char **argv)
+{
+	const char* fn_name = "wl_dump_chanspecs_defset";
+	wl_uint32_list_t *list;
+	int ret, buflen;
+	chanspec_t c = 0;
+	uint i;
+	int err;
+	int num_chanspecs = 0;
+	char chspec_str[CHANSPEC_STR_LEN];
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+
+	strcpy(buf, "chanspecs_defset");
+	buflen = strlen(buf) + 1;
+
+	/* toss the command name */
+	argv++;
+
+	/* Validate arguments if any */
+	if (*argv) {
+		fprintf(stderr,
+		    "%s: This IOVAR doesn't take any arguments.\n", fn_name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	num_chanspecs += NUM_CHANSPECS_LIST_SIZE;
+
+	/* Add list */
+	list = (wl_uint32_list_t *)(buf + buflen);
+	list->count = htod32(num_chanspecs);
+	buflen += sizeof(uint32)*(num_chanspecs + 1);
+
+	/* if buflen is greater then WLC_IOCTL_MAXLEN return error */
+	ret = BCME_IOCTL_ERROR;
+	while (buflen <= WLC_IOCTL_MAXLEN) {
+		int bcmerr;
+
+		ret = wlu_get(wl, WLC_GET_VAR, &buf[0], buflen);
+		if (ret == 0)
+			break;
+
+		/* If the error is not buffer too short break */
+		ret = wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+		if (ret < 0 || bcmerr != BCME_BUFTOOSHORT)
+			break;
+
+		/* If the error is buffer too short, increment the num_chanspecs */
+		num_chanspecs += NUM_CHANSPECS_LIST_SIZE;
+		list->count = htod32(num_chanspecs);
+		/* increase the buffer length by the space for the chanspecs added */
+		buflen += sizeof(uint32)*(NUM_CHANSPECS_LIST_SIZE);
+	}
+
+	/* Incase of error return */
+	if (ret) {
+		err = BCME_IOCTL_ERROR;
+		goto exit;
+	}
+
+	list = (wl_uint32_list_t *)buf;
+	for (i = 0; i < dtoh32(list->count); i++) {
+		c = (chanspec_t)dtoh32(list->element[i]);
+		wf_chspec_ntoa(c, chspec_str);
+		printf("%s (0x%04x)\n", chspec_str, c);
+	}
+	printf("\n");
+	return ret;
+
+	exit:
+		return err;
+}
+
+static int
+wl_dump_chanspecs(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_dump_chanspecs";
+	wl_uint32_list_t *list;
+	chanspec_t c = 0, *chanspec;
+	int ret, buflen;
+	uint i;
+	int err, opt_err;
+	bool band_set = FALSE, bw_set = FALSE, is80p80 = FALSE;
+	char abbrev[WLC_CNTRY_BUF_SZ] = ""; /* default.. current locale */
+	char chspec_str[CHANSPEC_STR_LEN];
+	char *country_abbrev;
+	int num_chanspecs = 0;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+
+	/* multiple commands are using this API to dump a channel list:
+	 * chanspecs
+	 * roam_channels_in_cache
+	 * roam_channels_in_hotlist
+	 */
+	strcpy(buf, cmd->name);
+	buflen = strlen(buf) + 1;
+
+	/* toss the command name */
+	argv++;
+
+	/* Validate arguments if any */
+	if (*argv) {
+		miniopt_init(&to, fn_name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 'b') {
+				if (!to.good_int) {
+					fprintf(stderr,
+					        "%s: could not parse \"%s\" as an int for band\n",
+					        fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 5) && (to.val != 2)) {
+					fprintf(stderr,
+					        "%s: invalid band %d\n",
+					        fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 5)
+					c |= WL_CHANSPEC_BAND_5G;
+				else
+					c |= WL_CHANSPEC_BAND_2G;
+				band_set = TRUE;
+			}
+			if (to.opt == 'w') {
+				/* For 80+80 case, using flag is80p80 for it */
+				if (!strcmp(to.valstr, "80+80"))  {
+					is80p80 = TRUE;
+				}
+				if ((!to.good_int) && (!is80p80)) {
+					fprintf(stderr,
+					        "%s: could not parse \"%s\" as an int for"
+					        " bandwidth\n",
+					        fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 20) && (to.val != 40) && (to.val != 80) &&
+					(to.val != 160) && (!is80p80)) {
+					fprintf(stderr,
+					        "%s: invalid bandwidth %d\n",
+					        fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 20)
+					c |= WL_CHANSPEC_BW_20;
+				else if (to.val == 40)
+					c |= WL_CHANSPEC_BW_40;
+				else {
+					if (ioctl_version == 1) {
+						fprintf(stderr,
+						        "%s: bandwidth 80 MHz is not supported by "
+						        "this version driver.\n",
+						        fn_name);
+						err = BCME_USAGE_ERROR;
+						goto exit;
+
+					}
+					if (is80p80)
+						c |= WL_CHANSPEC_BW_8080;
+					else if (to.val == 160)
+						c |= WL_CHANSPEC_BW_160;
+					else
+						c |= WL_CHANSPEC_BW_80;
+				}
+
+				bw_set = TRUE;
+			}
+			if (to.opt == 'c') {
+				if (!to.valstr) {
+					fprintf(stderr,
+					        "%s: please provide country abbrev \n", fn_name);
+					err = BCME_USAGE_ERROR;
+					goto exit;
+				}
+				strncpy(abbrev, to.valstr, WLC_CNTRY_BUF_SZ - 1);
+				abbrev[WLC_CNTRY_BUF_SZ - 1] = '\0';
+			}
+		}
+		if (!bw_set || !band_set) {
+			if (!band_set)
+				fprintf(stderr, "%s: you need to set a band, '-b <5|2>'\n",
+				        fn_name);
+			if (!bw_set)
+				fprintf(stderr,
+				        "%s: you need to set a bandwidth, "
+				        "'-w <20|40|80|160|80+80>'\n",
+				        fn_name);
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+	}
+
+	/* convert chanspec to legacy if needed */
+	if (c != 0) {
+		c = wl_chspec_to_driver(c);
+		if (c == INVCHANSPEC) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+	}
+
+	/* Add chanspec argument */
+	chanspec = (chanspec_t *) (buf + buflen);
+	*chanspec = c;
+	buflen += (sizeof(chanspec_t));
+
+	/* Add country abbrev */
+	country_abbrev = buf + buflen;
+	strncpy(country_abbrev, abbrev, WLC_CNTRY_BUF_SZ);
+	buflen += WLC_CNTRY_BUF_SZ;
+
+	num_chanspecs += NUM_CHANSPECS_LIST_SIZE;
+
+	/* Add list */
+	list = (wl_uint32_list_t *)(buf + buflen);
+	list->count = htod32(num_chanspecs);
+	buflen += sizeof(uint32)*(num_chanspecs + 1);
+
+	/* if buflen is greater then WLC_IOCTL_MAXLEN return error */
+	ret = BCME_IOCTL_ERROR;
+	while (buflen <= WLC_IOCTL_MAXLEN) {
+		int bcmerr;
+
+		ret = wlu_get(wl, WLC_GET_VAR, &buf[0], buflen);
+		if (ret == 0)
+			break;
+
+		/* If the error is not buffer too short break */
+		ret = wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+		if (ret < 0 || bcmerr != BCME_BUFTOOSHORT)
+			break;
+
+		/* reconstruct the argument */
+		strcpy(buf, cmd->name);
+
+		/* Add chanspec argument */
+		*chanspec = c;
+
+		/* Add country abbrev */
+		strncpy(country_abbrev, abbrev, WLC_CNTRY_BUF_SZ);
+
+		/* If the error is buffer too short, increment the num_chanspecs */
+		num_chanspecs += NUM_CHANSPECS_LIST_SIZE;
+		list->count = htod32(num_chanspecs);
+		/* increase the buffer length by the space for the chanspecs added */
+		buflen += sizeof(uint32)*(NUM_CHANSPECS_LIST_SIZE);
+	}
+
+	/* Incase of error return */
+	if (ret) {
+		err = BCME_IOCTL_ERROR;
+		goto exit;
+	}
+
+	list = (wl_uint32_list_t *)buf;
+	for (i = 0; i < dtoh32(list->count); i++) {
+		c = wl_chspec32_from_driver(list->element[i]);
+		wf_chspec_ntoa(c, chspec_str);
+		printf("%s (0x%04x)\n", chspec_str, c);
+	}
+	printf("\n");
+	return ret;
+
+exit:
+	return err;
+}
+
+static int
+wl_channels_in_country(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_channels_in_country_t *cic;
+	int ret;
+	uint i, len;
+
+	cic = (wl_channels_in_country_t *)buf;
+	cic->buflen = WLC_IOCTL_MAXLEN;
+	cic->count = 0;
+
+	/* country abbrev must follow */
+	if (!*++argv) {
+		fprintf(stderr, "missing country abbrev\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	len = strlen(*argv);
+	if ((len > 3) || (len < 2)) {
+		fprintf(stderr, "invalid country abbrev: %s\n", *argv);
+		return BCME_BADARG;
+	}
+
+	strcpy(cic->country_abbrev, *argv);
+
+	/* band must follow */
+	if (!*++argv) {
+		fprintf(stderr, "missing band\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!stricmp(*argv, "a"))
+		cic->band = WLC_BAND_5G;
+	else if (!stricmp(*argv, "b"))
+		cic->band = WLC_BAND_2G;
+	else {
+		fprintf(stderr, "unsupported band: %s\n", *argv);
+		return BCME_UNSUPPORTED;
+	}
+
+	cic->buflen = htod32(cic->buflen);
+	cic->band = htod32(cic->band);
+	cic->count = htod32(cic->count);
+	ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < dtoh32(cic->count); i++)
+		printf("%d ", dtoh32(cic->channel[i]));
+	printf("\n");
+
+	return ret;
+}
+
+int
+wl_get_scan(void *wl, int opc, char *scan_buf, uint buf_len)
+{
+	wl_scan_results_t *list = (wl_scan_results_t*)scan_buf;
+	int ret;
+
+	list->buflen = htod32(buf_len);
+	ret = wlu_get(wl, opc, scan_buf, buf_len);
+	if (ret < 0)
+		return ret;
+	ret = 0;
+
+	list->buflen = dtoh32(list->buflen);
+	list->version = dtoh32(list->version);
+	list->count = dtoh32(list->count);
+	if (list->buflen == 0) {
+		list->version = 0;
+		list->count = 0;
+	} else if (list->version != WL_BSS_INFO_VERSION &&
+	           list->version != LEGACY2_WL_BSS_INFO_VERSION &&
+	           list->version != LEGACY_WL_BSS_INFO_VERSION) {
+		fprintf(stderr, "Sorry, your driver has bss_info_version %d "
+			"but this program supports only version %d.\n",
+			list->version, WL_BSS_INFO_VERSION);
+		list->buflen = 0;
+		list->count = 0;
+	}
+
+	return ret;
+}
+
+static int
+wl_get_iscan(void *wl, char *scan_buf, uint buf_len)
+{
+	wl_iscan_results_t list;
+	wl_scan_results_t *results;
+	int ret;
+
+	memset(&list, '\0', sizeof(list));
+	list.results.buflen = htod32(buf_len);
+	ret = wlu_iovar_getbuf(wl, "iscanresults", &list, WL_ISCAN_RESULTS_FIXED_SIZE,
+	                      scan_buf, WLC_IOCTL_MAXLEN);
+
+	if (ret < 0)
+		return ret;
+
+	ret = 0;
+
+	results = &((wl_iscan_results_t*)scan_buf)->results;
+	results->buflen = dtoh32(results->buflen);
+	results->version = dtoh32(results->version);
+	results->count = dtoh32(results->count);
+	if (results->buflen == 0) {
+		printf("wl_get_iscan buflen 0\n");
+		results->version = 0;
+		results->count = 0;
+	} else if (results->version != WL_BSS_INFO_VERSION &&
+	           results->version != LEGACY2_WL_BSS_INFO_VERSION &&
+	           results->version != LEGACY_WL_BSS_INFO_VERSION) {
+		fprintf(stderr, "Sorry, your driver has bss_info_version %d "
+			"but this program supports only version %d.\n",
+			results->version, WL_BSS_INFO_VERSION);
+		results->buflen = 0;
+		results->count = 0;
+	}
+
+	return ret;
+}
+
+static int
+wl_spect(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, spect;
+	char *endptr = NULL;
+
+	if (!*++argv) {
+		if ((ret = wlu_get(wl, cmd->get, &spect, sizeof(spect))) < 0) {
+			return ret;
+		}
+
+		spect = dtoh32(spect);
+		switch (spect) {
+		case SPECT_MNGMT_OFF:
+			printf("Off\n");
+			break;
+
+		case SPECT_MNGMT_LOOSE_11H:
+			printf("Loose interpretation of 11h spec - may join non 11h AP.\n");
+			break;
+
+		case SPECT_MNGMT_STRICT_11H:
+			printf("Strict interpretation of 11h spec - may not join non 11h AP.\n");
+			break;
+
+		case SPECT_MNGMT_STRICT_11D:
+			printf("802.11d mode\n");
+			break;
+
+		case SPECT_MNGMT_LOOSE_11H_D:
+			printf("Loose interpretation of 11h+d spec - may join non-11h APs\n");
+			break;
+
+		default:
+			printf("invalid value 0x%x\n", spect);
+			return BCME_BADARG;
+		}
+		return (0);
+	} else {
+		spect = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		if (spect < SPECT_MNGMT_OFF || spect > SPECT_MNGMT_LOOSE_11H_D)
+			return BCME_BADARG;
+
+		spect = htod32(spect);
+		return wlu_set(wl, cmd->set, &spect, sizeof(spect));
+	}
+}
+
+static int
+wl_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct ether_addr bssid;
+	wlc_ssid_t ssid;
+	char ssidbuf[SSID_FMT_BUF_LEN];
+	wl_bss_info_t *bi;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_get(wl, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN)) == 0) {
+		/* The adapter is associated. */
+		*(uint32*)buf = htod32(WLC_IOCTL_MAXLEN);
+		if ((ret = wlu_get(wl, WLC_GET_BSS_INFO, buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+
+		bi = (wl_bss_info_t*)(buf + 4);
+		if (dtoh32(bi->version) == WL_BSS_INFO_VERSION ||
+		    dtoh32(bi->version) == LEGACY2_WL_BSS_INFO_VERSION ||
+		    dtoh32(bi->version) == LEGACY_WL_BSS_INFO_VERSION)
+			dump_bss_info(bi);
+		else
+			fprintf(stderr, "Sorry, your driver has bss_info_version %d "
+				"but this program supports only version %d.\n",
+				bi->version, WL_BSS_INFO_VERSION);
+	} else {
+		printf("Not associated. Last associated with ");
+
+		if ((ret = wlu_get(wl, WLC_GET_SSID, &ssid, sizeof(wlc_ssid_t))) < 0) {
+			printf("\n");
+			return ret;
+		}
+
+		wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len));
+		printf("SSID: \"%s\"\n", ssidbuf);
+	}
+
+	return 0;
+}
+
+static int
+wl_deauth_rc(void *wl, cmd_t *cmd, char **argv)
+{
+	scb_val_t scb_val;
+	int ret;
+
+	if (!*++argv) {
+		fprintf(stderr, "STA MAC not specified, deauth all\n");
+		ret = wlu_set(wl, WLC_SCB_DEAUTHENTICATE, (void *)&ether_bcast,
+			ETHER_ADDR_LEN);
+		return ret;
+
+	} else if (!wl_ether_atoe(*argv, &scb_val.ea)) {
+		fprintf(stderr, "Malformed STA MAC parameter\n");
+		ret = BCME_USAGE_ERROR;
+
+	} else if (!*++argv) {
+		/* No reason code furnished, so driver will use its default */
+		ret = wlu_set(wl, WLC_SCB_DEAUTHENTICATE, &scb_val.ea,
+			ETHER_ADDR_LEN);
+
+	} else {
+		scb_val.val = htod32((uint32)strtoul(*argv, NULL, 0));
+		ret = wlu_set(wl, cmd->set, &scb_val, sizeof(scb_val));
+	}
+	return ret;
+}
+
+static int
+wl_wpa_auth(void *wl, cmd_t *cmd, char **argv)
+{
+	int bsscfg_idx = 0;
+	int consumed;
+	int wpa_auth = 0;
+	int ret = 0;
+	int i;
+	static struct {
+		int val;
+		const char *name;
+	} auth_mode[] =
+		  /* Keep the numeric values in the staticly initialized
+		   * help string consistent.  Unfortunately, there isn't
+		   * an automatic way for that.
+		   */
+		{{WPA_AUTH_NONE,	"WPA-NONE"},
+		 {WPA_AUTH_UNSPECIFIED,	"WPA-802.1x"},
+		 {WPA_AUTH_PSK,		"WPA-PSK"},
+		 {WPA2_AUTH_UNSPECIFIED, "WPA2-802.1x"},
+		 {WPA2_AUTH_PSK,	"WPA2-PSK"},
+#ifdef BCMWAPI_WAI
+		{WAPI_AUTH_UNSPECIFIED, "WAPI-AS"},
+		{WAPI_AUTH_PSK,        "WAPI-PSK"},
+#endif /* BCMWAPI_WAI */
+		 {WPA2_AUTH_1X_SHA256,	"1X-SHA256"},
+		 {WPA2_AUTH_FT,		"FT"},
+		 {WPA2_AUTH_PSK_SHA256,	"PSK-SHA256"},
+		 {WPA_AUTH_DISABLED,	"disabled"}};
+
+	/* skip the command name */
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv, cmd->name, &bsscfg_idx, &consumed)) != 0)
+		return ret;
+
+	argv += consumed;
+
+	if (!*argv) {
+		/* no arg, so this is a GET. */
+
+		if (!consumed)
+			ret = wlu_iovar_getint(wl, "wpa_auth", &wpa_auth);
+		else
+			ret = wl_bssiovar_getint(wl, "wpa_auth", bsscfg_idx, &wpa_auth);
+
+		if (ret < 0)
+			return ret;
+
+		/* Show all AKM suites enabled */
+		printf("0x%x", wpa_auth);
+
+		if (wpa_auth == WPA_AUTH_DISABLED)
+			printf(" Disabled");
+
+		for (i = 0; i < (int)ARRAYSIZE(auth_mode); i++) {
+			if (wpa_auth & auth_mode[i].val)
+				printf(" %s", auth_mode[i].name);
+		}
+
+		printf("\n");
+		return ret;
+
+
+	} else {
+		/* there's an arg, so this is a SET. */
+		ret = 1;
+
+		/* Validate the user input range */
+		if (isdigit((int)*argv[0])) {
+			unsigned int range = 0;
+
+			/* param is a number; look for value in the list */
+			wpa_auth = strtoul(*argv, NULL, 0);
+
+			/* Validate the user input range */
+
+			for (i = 0; i < (int)ARRAYSIZE(auth_mode); i++)
+				range |= auth_mode[i].val;
+
+			range = (~range) & 0xFFFF;
+
+			if (range & wpa_auth) {
+				ret = 1;
+				goto usage;
+			} else {
+				ret = 0;
+			}
+
+		} else {
+
+			int arg_count = 0;
+			char** p_argv;
+			int j = 0;
+			unsigned int range = 0;
+
+			wpa_auth = 0;
+			p_argv = argv;
+
+			for (i = 0; i < (int)ARRAYSIZE(auth_mode); i++)
+				range |= auth_mode[i].val;
+
+			range = (~range) & (0xFFFF);
+
+			while (*p_argv) {
+				arg_count++;
+				p_argv++;
+				}
+
+			p_argv = argv;
+
+			for (j = 0; j < arg_count; j++) {
+				bool found = FALSE;
+
+				argv = p_argv + j;
+
+				/* treat param as string to be matched in list */
+				for (i = 0; i < (int)ARRAYSIZE(auth_mode); i++) {
+					if (!stricmp(auth_mode[i].name, *argv)) {
+
+						found = TRUE;
+						wpa_auth |= auth_mode[i].val;
+						ret = 0;
+
+						/* traverse the list */
+						argv++;
+						if (!*argv)
+							break;
+					}
+				}
+
+				if ((found == FALSE) || (range & wpa_auth))
+					goto usage;
+			}
+
+		}
+		if (ret)
+			fprintf(stderr, "%s is not a valid WPA auth mode\n", *argv);
+		else {
+			if (!consumed)
+				ret = wlu_iovar_setint(wl, "wpa_auth", wpa_auth);
+			else
+				ret = wl_bssiovar_setint(wl, "wpa_auth", bsscfg_idx, wpa_auth);
+		}
+	}
+
+	return ret;
+
+usage:
+	fprintf(stderr, "Inavlid user argument.\n");
+	fprintf(stderr, "Values may be a bitvector or list of names from the set.\n");
+
+	for (i = 0; i < (int)ARRAYSIZE(auth_mode); i++) {
+		fprintf(stderr, "\n0x%04x  %s", auth_mode[i].val, auth_mode[i].name);
+	}
+
+	printf("\n");
+	return ret;
+}
+
+static int
+wl_set_pmk(void *wl, cmd_t *cmd, char **argv)
+{
+	wsec_pmk_t psk;
+	size_t key_len;
+
+	if (!*++argv) {
+		return BCME_USAGE_ERROR;
+	}
+	key_len = strlen(*argv);
+	if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) {
+		fprintf(stderr, "passphrase must be between %d and %d characters long\n",
+		       WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN);
+		return BCME_BADARG;
+	}
+	psk.key_len = htod16((ushort) key_len);
+	psk.flags = htod16(WSEC_PASSPHRASE);
+	memcpy(psk.key, *argv, key_len);
+	return wlu_set(wl, cmd->set, &psk, sizeof(psk));
+}
+
+static int
+wl_wsec(void *wl, cmd_t *cmd, char **argv)
+{
+	int wsec;
+	int bsscfg_idx = 0;
+	int consumed;
+	char *endptr = NULL;
+	int error;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "wsec", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	if (!*argv) {
+		/* This is a GET */
+		if (consumed == 0) {
+			error = wlu_get(wl, WLC_GET_WSEC, &wsec, sizeof(uint32));
+			wsec = dtoh32(wsec);
+		}
+		else
+			error = wl_bssiovar_getint(wl, "wsec", bsscfg_idx, &wsec);
+
+		if (!error)
+			wl_printint(wsec);
+	} else {
+		/* This is a SET */
+		if (!stricmp(*argv, "off"))
+			wsec = 0;
+		else {
+			wsec = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		if (consumed == 0) {
+			wsec = htod32(wsec);
+			error = wlu_set(wl, WLC_SET_WSEC, &wsec, sizeof(uint32));
+		}
+		else
+			error = wl_bssiovar_setint(wl, "wsec", bsscfg_idx, wsec);
+	}
+
+	return error;
+}
+
+int
+parse_wep(char **argv, wl_wsec_key_t *key, bool options)
+{
+	char hex[] = "XX";
+	unsigned char *data = key->data;
+	char *keystr = *argv;
+
+	switch (strlen(keystr)) {
+	case 5:
+	case 13:
+	case 16:
+		key->len = strlen(keystr);
+		memcpy(data, keystr, key->len + 1);
+		break;
+	case 12:
+	case 28:
+	case 34:
+	case 66:
+		/* strip leading 0x */
+		if (!strnicmp(keystr, "0x", 2))
+			keystr += 2;
+		else
+			return -1;
+		/* fall through */
+	case 10:
+	case 26:
+	case 32:
+	case 64:
+		key->len = strlen(keystr) / 2;
+		while (*keystr) {
+			strncpy(hex, keystr, 2);
+			*data++ = (char) strtoul(hex, NULL, 16);
+			keystr += 2;
+		}
+		break;
+	default:
+		return -1;
+	}
+
+	switch (key->len) {
+	case 5:
+		key->algo = CRYPTO_ALGO_WEP1;
+		break;
+	case 13:
+		key->algo = CRYPTO_ALGO_WEP128;
+		break;
+	case 16:
+		/* default to AES-CCM */
+		key->algo = CRYPTO_ALGO_AES_CCM;
+		break;
+	case 32:
+		key->algo = CRYPTO_ALGO_TKIP;
+		break;
+	default:
+		return -1;
+	}
+
+	/* Set as primary key by default */
+	key->flags |= WL_PRIMARY_KEY;
+
+	if (options) {
+		/* Get options */
+		while (*++argv) {
+			if (!strnicmp("ccm", *argv, 3) && key->len == 16)
+				key->algo = CRYPTO_ALGO_AES_CCM;
+			else if (!strnicmp("ocb", *argv, 3) && key->len == 16)
+				key->algo = CRYPTO_ALGO_AES_OCB_MPDU;
+			else if (!strnicmp("notx", *argv, 4))
+				key->flags &= ~WL_PRIMARY_KEY;
+			else if (!wl_ether_atoe(*argv, &key->ea))
+				memset(&key->ea, 0, ETHER_ADDR_LEN);
+		}
+	}
+
+	return 0;
+}
+
+/* get a power value from the opaque ppr structure */
+static int8 wl_ppr_get_pwr(ppr_t* pprptr, reg_rate_index_t rate_idx, wl_tx_bw_t bw)
+{
+	clm_rate_group_id_t group_id = ppr_table[rate_idx].id;
+	int8 power = WL_RATE_DISABLED;
+	switch (ppr_group_table[group_id].rate_type) {
+		case PPR_RATE_DSSS:
+			{
+				ppr_dsss_rateset_t rateset;
+				ppr_get_dsss(pprptr, bw, ppr_group_table[group_id].chain, &rateset);
+				power = rateset.pwr[rate_idx-ppr_group_table[group_id].first_rate];
+			}
+			break;
+		case PPR_RATE_OFDM:
+			{
+				ppr_ofdm_rateset_t rateset;
+				ppr_get_ofdm(pprptr, bw, ppr_group_table[group_id].mode,
+					ppr_group_table[group_id].chain, &rateset);
+				power = rateset.pwr[rate_idx-ppr_group_table[group_id].first_rate];
+			}
+			break;
+		case PPR_RATE_HT:
+			{
+				ppr_ht_mcs_rateset_t rateset;
+				ppr_get_ht_mcs(pprptr, bw, ppr_group_table[group_id].nss,
+					ppr_group_table[group_id].mode,
+					ppr_group_table[group_id].chain, &rateset);
+				power = rateset.pwr[rate_idx-ppr_group_table[group_id].first_rate];
+			}
+			break;
+		case PPR_RATE_VHT:
+			{
+				ppr_vht_mcs_rateset_t rateset;
+				ppr_get_vht_mcs(pprptr, bw, ppr_group_table[group_id].nss,
+					ppr_group_table[group_id].mode,
+					ppr_group_table[group_id].chain, &rateset);
+				power = rateset.pwr[rate_idx-ppr_group_table[group_id].first_rate];
+			}
+			break;
+		default:
+			break;
+	}
+
+	return power;
+}
+
+static int
+wl_get_chanspec_txpwr_max(void *wl, cmd_t *cmd, char **argv)
+{
+	int i, err;
+	char chspec_str[CHANSPEC_STR_LEN];
+
+	wl_chanspec_txpwr_max_t *chanspec_txpwr;
+	wl_chanspec_txpwr_max_t params;
+
+	miniopt_t to;
+	chanspec_t chanspec = 0;
+	int opt_err;
+	bool band_set = FALSE, bw_set = FALSE;
+
+	/* toss the command name */
+	argv++;
+
+	/* Validate arguments if any */
+	if (*argv) {
+		miniopt_init(&to, __FUNCTION__, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 'b') {
+				if (!to.good_int) {
+					fprintf(stderr, "%s: could not parse [%s] as band\n",
+						__FUNCTION__, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val != 5) && (to.val != 2)) {
+					fprintf(stderr, "%s: invalid band %d\n",
+						__FUNCTION__, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 5)
+					chanspec |= WL_CHANSPEC_BAND_5G;
+				else
+					chanspec |= WL_CHANSPEC_BAND_2G;
+				band_set = TRUE;
+			}
+			if (to.opt == 'w') {
+				if (!to.good_int) {
+					fprintf(stderr, "%s: could not parse [%s] as bandwidth\n",
+						__FUNCTION__, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val == 20)
+					chanspec |= WL_CHANSPEC_BW_20;
+				else if (to.val == 40)
+					chanspec |= WL_CHANSPEC_BW_40;
+				else if (to.val == 80)
+					chanspec |= WL_CHANSPEC_BW_80;
+				else if (to.val == 160)
+					chanspec |= WL_CHANSPEC_BW_160;
+				else if (to.val == 8080)
+					chanspec |= WL_CHANSPEC_BW_8080;
+				else {
+					fprintf(stderr, "%s: invalid bandwidth %d\n",
+					         __FUNCTION__, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				bw_set = TRUE;
+			}
+		}
+		if (!bw_set || !band_set) {
+			if (!band_set)
+				fprintf(stderr, "%s: you need to set a band, '-b <5|2>'\n",
+				        __FUNCTION__);
+			if (!bw_set)
+				fprintf(stderr,
+				        "%s: you need to set a bandwidth, '-w <20|40|80>'\n",
+				        __FUNCTION__);
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+	}
+
+	/* convert chanspec to legacy if needed */
+	if (chanspec != 0) {
+		chanspec = wl_chspec_to_driver(chanspec);
+		if (chanspec == INVCHANSPEC) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+	}
+
+	memset(&params, 0, WL_CHANSPEC_TXPWR_MAX_LEN);
+	params.ver = WL_CHANSPEC_TXPWR_MAX_VER;
+	params.len = WL_CHANSPEC_TXPWR_MAX_LEN;
+	params.count = 1;
+	params.txpwr[0].chanspec = chanspec;
+
+	if ((err = wlu_iovar_getbuf(wl, cmd->name, &params, sizeof(params),
+		buf, WLC_IOCTL_MAXLEN)) < 0) {
+		return err;
+	}
+
+	chanspec_txpwr = (wl_chanspec_txpwr_max_t *)buf;
+
+	if (chanspec_txpwr->ver != WL_CHANSPEC_TXPWR_MAX_VER) {
+		fprintf(stderr, "Error: version [%d] mismatch Driver version:%d\n",
+			WL_CHANSPEC_TXPWR_MAX_VER, chanspec_txpwr->ver);
+		return err;
+	}
+
+	for (i = 0; i < (int)(dtoh32(chanspec_txpwr->count)); i++) {
+		chanspec = wl_chspec32_from_driver(chanspec_txpwr->txpwr[i].chanspec);
+		wf_chspec_ntoa(chanspec, chspec_str);
+
+		printf("%s\t(0x%04x)\t%2d.%02d(dbm)\n",
+			chspec_str, chanspec,
+			DIV_QUO(chanspec_txpwr->txpwr[i].txpwr_max, 4),
+			DIV_REM(chanspec_txpwr->txpwr[i].txpwr_max, 4));
+	}
+	printf("\n");
+
+exit:
+	return err;
+}
+
+/* This version number must be incremented for every
+ * modification to the curpower output format. Minor changes
+ * warrant a decimal point increment. Major (potential
+ * script-breaking) changes should be met with a major increment.
+ */
+#define CURPOWER_OUTPUT_FORMAT_VERSION "8"
+
+#define RATE_STR_LEN 64
+#define CURPOWER_VER_STR "cptlv-"
+#define WL_CAP_CMD	"cap"
+
+static int
+wl_get_curpower_tlv_ver(void *wl)
+{
+	int error;
+	int ret = 0;
+
+	/* Get the CAP variable; search for curpower ver */
+	strncpy(buf, WL_CAP_CMD, WLC_IOCTL_MAXLEN);
+	if ((error = wlu_get(wl, WLC_GET_VAR, buf, WLC_IOCTL_MEDLEN)) >= 0) {
+		char seps[] = " ";
+		char *token;
+		buf[WLC_IOCTL_MEDLEN] = '\0';
+		token = strtok(buf, seps);
+		while (token != NULL) {
+			if (!memcmp(token, CURPOWER_VER_STR, strlen(CURPOWER_VER_STR))) {
+				char *ver = &token[strlen(CURPOWER_VER_STR)];
+				ret = atoi(ver);
+			}
+			token = strtok(NULL, seps);
+		}
+	}
+	return ret;
+}
+
+static int
+wl_get_current_power(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int mimo;
+	int i;
+	char chanspec_str[CHANSPEC_STR_LEN];
+	bool verbose = FALSE;
+	bool brief = FALSE;
+	int16 power_target;
+	char rate_str[RATE_STR_LEN];
+	int clk;
+	int val;
+	chanspec_t  chanspec;
+	uint8 *ppr_ser;
+	uint32 pprsize;
+	uint32 txchain_bitmap = 0;
+	size_t ppr_rpt_size;
+	tx_pwr_rpt_t *ppr_wl = NULL;
+	ppr_t* ppr_board = NULL;
+	ppr_t* ppr_target = NULL;
+	ppr_t* ppr_reg = NULL;
+	uint8  ppr_dim = 0;
+
+	int tlv_ver = wl_get_curpower_tlv_ver(wl);
+	/* firmware will crash if clk = 0 while using curpower */
+	if ((err = wlu_get(wl, WLC_GET_CLK, &clk, sizeof(int))) < 0)
+		goto exit;
+
+	if (!clk) {
+		fprintf(stderr, "Error: clock not active, do wl up (if not done already) "
+				"and force mpc 0 to active clock\n");
+		err = BCME_ERROR;
+		goto exit;
+	}
+
+	if ((err = wlu_iovar_getint(wl, "chanspec", (int *)&val)) < 0) {
+		goto exit;
+	}
+	chanspec = wl_chspec32_from_driver(val);
+
+	if ((err = wlu_iovar_get(wl, "hw_txchain", &txchain_bitmap, sizeof(txchain_bitmap))) < 0)
+		goto exit;
+
+	/* Special cases for 4365 3x3 config: hw_txchain can take a value between [8-15];
+	 * there are still 4 PHY cores but one or more cores are not used
+	 */
+	if (txchain_bitmap > 8 && txchain_bitmap <= 15)
+		ppr_dim = 4;
+	else
+		ppr_dim = bcm_bitcount((uint8 *)&txchain_bitmap, sizeof(uint8));
+
+
+	if (tlv_ver) {
+		if ((ppr_board = ppr_create(NULL, ppr_chanspec_bw(chanspec))) == NULL) {
+			err = BCME_NOMEM;
+			goto exit;
+		}
+		if ((ppr_target = ppr_create(NULL, ppr_chanspec_bw(chanspec))) == NULL) {
+			err = BCME_NOMEM;
+			goto exit;
+		}
+		if ((ppr_reg = ppr_create(NULL, ppr_chanspec_bw(chanspec))) == NULL) {
+			err = BCME_NOMEM;
+			goto exit;
+		}
+		pprsize = ppr_get_tlv_size(ppr_target, ppr_chanspec_bw(chanspec), ppr_dim);
+	} else {
+		pprsize = ppr_ser_size_by_bw(ppr_get_max_bw());
+	}
+	ppr_rpt_size = sizeof(tx_pwr_rpt_t) + pprsize*WL_TXPPR_SER_BUF_NUM;
+	ppr_wl = (tx_pwr_rpt_t *)malloc(ppr_rpt_size);
+
+	if (!tlv_ver) {
+		for (i = 0; i < WL_TXPPR_SER_BUF_NUM; i++) {
+			ppr_ser  = ppr_wl->pprdata + i*pprsize;
+			ppr_init_ser_mem_by_bw(ppr_ser, ppr_get_max_bw(), pprsize);
+		}
+	}
+
+	if (ppr_wl == NULL) {
+		fprintf(stderr, "Allocating mem failed for curpower\n");
+		err = BCME_NOMEM;
+		goto exit;
+	}
+
+	memset(ppr_wl, WL_RATE_DISABLED, ppr_rpt_size);
+
+	ppr_wl->ppr_len  = pprsize;
+	ppr_wl->version  = TX_POWER_T_VERSION;
+
+	if (argv[1] && (!strcmp(argv[1], "--verbose") || !strcmp(argv[1], "-v"))) {
+		verbose = TRUE;
+		argv++;
+	}
+	if (argv[1] && (!strcmp(argv[1], "--brief") || !strcmp(argv[1], "-b"))) {
+		brief = TRUE;
+		argv++;
+	}
+	argv++;
+	if (*argv)
+		fprintf(stderr, "Ignoring arguments for %s\n", cmd->name);
+
+	if ((err = wlu_get(wl, cmd->get, ppr_wl, ppr_rpt_size)) < 0) {
+		fprintf(stderr, "Error: Curpower failed. ");
+		fprintf(stderr, "Bring up interface and disable mpc if necessary (wl mpc 0)\n");
+		goto exit;
+	}
+
+	/* parse */
+	if (ppr_wl->version != TX_POWER_T_VERSION) {
+		printf("error: version mismatch - driver %d, wl executable was expecting %d\n",
+			ppr_wl->version, TX_POWER_T_VERSION);
+		err = BCME_ERROR;
+	} else {
+		int8 temp_val;
+		int divquo, divrem;
+		bool neg;
+
+		ppr_wl->flags = dtoh32(ppr_wl->flags);
+		ppr_wl->chanspec = wl_chspec_from_driver(ppr_wl->chanspec);
+		ppr_wl->local_chanspec = wl_chspec_from_driver(ppr_wl->local_chanspec);
+
+		mimo = (ppr_wl->flags & WL_TX_POWER_F_HT) |
+		       (ppr_wl->flags & WL_TX_POWER_F_MIMO) |
+		       (ppr_wl->flags & WL_TX_POWER_F_SISO);
+		ppr_ser  = ppr_wl->pprdata;
+
+		if (tlv_ver) {
+			(void)ppr_convert_from_tlv(ppr_board, ppr_wl->pprdata, ppr_wl->ppr_len);
+			ppr_ser += ppr_wl->ppr_len;
+			(void)ppr_convert_from_tlv(ppr_target, ppr_ser, ppr_wl->ppr_len);
+			ppr_ser += ppr_wl->ppr_len;
+			(void)ppr_convert_from_tlv(ppr_reg, ppr_ser, ppr_wl->ppr_len);
+		} else {
+			/* Try non TLV decode */
+			if ((err = ppr_deserialize_create(NULL, ppr_wl->pprdata, ppr_wl->ppr_len,
+					&ppr_board)) != BCME_OK) {
+				fprintf(stderr, "Error: read ppr board limit failed\n");
+				goto exit;
+			}
+			ppr_ser += ppr_wl->ppr_len;
+			if ((err = ppr_deserialize_create(NULL, ppr_ser, ppr_wl->ppr_len,
+					&ppr_target)) != BCME_OK) {
+				fprintf(stderr, "Error: read ppr target power failed\n");
+				goto exit;
+			}
+			ppr_ser += ppr_wl->ppr_len;
+			if ((err = ppr_deserialize_create(NULL, ppr_ser, ppr_wl->ppr_len, &ppr_reg))
+				!= BCME_OK) {
+				fprintf(stderr, "Error: read ppr regulatory limits failed\n");
+				goto exit;
+			}
+		}
+
+		/* dump */
+		if (verbose)
+			printf("%-23s%s\n", "Output Format Version:",
+				CURPOWER_OUTPUT_FORMAT_VERSION);
+
+		printf("%-23s%s, %s\n", "Power Control:",
+		       (ppr_wl->flags & WL_TX_POWER_F_ENABLED) ? "On" : "Off",
+		       (ppr_wl->flags & WL_TX_POWER_F_HW) ? "HW" : "SW");
+		printf("%-23s%s\n", "Current Channel:",
+		       wf_chspec_ntoa(ppr_wl->chanspec, chanspec_str));
+		printf("%-23s%s\n", "BSS Channel:",
+		       wf_chspec_ntoa(ppr_wl->local_chanspec, chanspec_str));
+		printf("%-23s%d.%d dBm\n", "BSS Local Max:",
+		       DIV_QUO(ppr_wl->local_max, 4), DIV_REM(ppr_wl->local_max, 4));
+		printf("%-23s%d.%d dB\n", "BSS Local Constraint:",
+		       DIV_QUO(ppr_wl->local_constraint, 4), DIV_REM(ppr_wl->local_constraint, 4));
+		printf("%-23s", "Channel Width:");
+		switch (ppr_wl->channel_bandwidth) {
+			case WL_BW_2P5MHZ:
+				printf("2.5MHz\n");
+				break;
+			case WL_BW_5MHZ:
+				printf("5MHz\n");
+				break;
+			case WL_BW_10MHZ:
+				printf("10MHz\n");
+				break;
+			case WL_BW_20MHZ:
+				printf("20MHz\n");
+				break;
+			case WL_BW_40MHZ:
+				printf("40MHz\n");
+				break;
+			case WL_BW_80MHZ:
+				printf("80MHz\n");
+				break;
+			case WL_BW_160MHZ:
+				printf("160MHz\n");
+				break;
+			case WL_BW_8080MHZ:
+				printf("80+80MHz\n");
+				break;
+		default:
+			fprintf(stderr, "Error: Unknown bandwidth %d\n",
+				ppr_wl->channel_bandwidth);
+			err = BCME_RANGE;
+			goto exit;
+		}
+
+		temp_val = (int8)(ppr_wl->user_target & 0xff);
+		divquo = DIV_QUO(temp_val, 4);
+		divrem = DIV_REM(temp_val, 4);
+		neg = (divrem < 0) || (divquo < 0);
+		divrem = ABS(divrem);
+		divquo = ABS(divquo);
+		divquo = neg ? -divquo : divquo;
+
+		printf("%-23s%d.%d dBm\n", "User Target:",
+		       divquo, divrem);
+		printf("%-23s%d.%d dB\n", "SROM Antgain 2G:",
+		       DIV_QUO(ppr_wl->antgain[0], 4), DIV_REM(ppr_wl->antgain[0], 4));
+		printf("%-23s%d.%d dB\n", "SROM Antgain 5G:",
+		       DIV_QUO(ppr_wl->antgain[1], 4), DIV_REM(ppr_wl->antgain[1], 4));
+		printf("%-23s", "SAR:");
+		if (ppr_wl->sar != WLC_TXPWR_MAX)
+			printf("%d.%d dB\n", DIV_QUO(ppr_wl->sar, 4), DIV_REM(ppr_wl->sar, 4));
+		else
+			printf("-\n");
+		printf("%-23s", "Open loop:");
+		if (ppr_wl->flags & WL_TX_POWER_F_OPENLOOP)
+			printf("On\n");
+		else
+			printf("Off\n");
+		printf("%-23s", "Current rate:");
+		wl_rate_print(rate_str, ppr_wl->last_tx_ratespec);
+		printf("[%s] %s\n", get_reg_rate_string_from_ratespec(ppr_wl->last_tx_ratespec),
+			rate_str);
+		printf("\n");
+
+		printf("Regulatory Limits:\n");
+		if (brief)
+		{
+			wl_txpwr_array_row_print(ppr_reg, ppr_wl->channel_bandwidth,
+				get_reg_rate_index_from_ratespec(ppr_wl->last_tx_ratespec));
+		}
+		else
+		{
+			wl_txpwr_array_print(ppr_reg, ppr_wl->channel_bandwidth, verbose,
+				CHSPEC_IS5G(chanspec));
+		}
+		printf("\n");
+
+		printf("%-23s%d\n", "Core Index:", ppr_wl->display_core);
+		printf("Board Limits:\n");
+		if (brief)
+		{
+			wl_txpwr_array_row_print(ppr_board, ppr_wl->channel_bandwidth,
+				get_reg_rate_index_from_ratespec(ppr_wl->last_tx_ratespec));
+		}
+		else
+		{
+			wl_txpwr_array_print(ppr_board, ppr_wl->channel_bandwidth, verbose,
+				CHSPEC_IS5G(chanspec));
+		}
+		printf("\n");
+
+		printf("Power Targets:\n");
+		if (brief)
+		{
+			wl_txpwr_array_row_print(ppr_target, ppr_wl->channel_bandwidth,
+				get_reg_rate_index_from_ratespec(ppr_wl->last_tx_ratespec));
+		}
+		else
+		{
+			wl_txpwr_array_print(ppr_target, ppr_wl->channel_bandwidth, verbose,
+				CHSPEC_IS5G(chanspec));
+		}
+		printf("\n");
+
+		/* print the different power estimate combinations */
+		if (mimo) {
+			printf("Maximum Power Target among all rates:\t");
+			for (i = 0; i < ppr_wl->rf_cores; i++) {
+				power_target = (int8)ppr_wl->tx_power_max[i];
+				divquo = DIV_QUO(power_target, 4);
+				divrem = DIV_REM(power_target, 4);
+				neg = (divrem < 0) || (divquo < 0);
+				divrem = ABS(divrem);
+				divquo = ABS(divquo);
+				divquo = neg ? -divquo : divquo;
+				printf("%2d.%02d  ", divquo, divrem);
+			}
+			printf("\n");
+
+			printf("Last est. power                     :\t");
+			for (i = 0; i < ppr_wl->rf_cores; i++)
+				printf("%2d.%02d  ",
+				       DIV_QUO((int8)ppr_wl->est_Pout[i], 4),
+				       DIV_REM(ppr_wl->est_Pout[i], 4));
+			printf("\n");
+
+			printf("Power Target for the current rate   :\t");
+			for (i = 0; i < ppr_wl->rf_cores; i++)
+			{
+				if (ppr_wl->target_offsets[i] != WL_RATE_DISABLED)
+				{
+					power_target = (int8)ppr_wl->tx_power_max[i] -
+						ppr_wl->target_offsets[i];
+					/*      for ACPHY, clip the power_target if it
+					        is larger than the SAR limit for the
+					        current path. For non-ACPHY or
+					        WLC_SARLIMIT disabled, this threshold is
+					        set to be MAX pwr, ie. 127
+					*/
+					if (power_target > ppr_wl->SARLIMIT[i])
+						power_target = ppr_wl->SARLIMIT[i];
+					divquo = DIV_QUO(power_target, 4);
+					divrem = DIV_REM(power_target, 4);
+					neg = (divrem < 0) || (divquo < 0);
+					divrem = ABS(divrem);
+					divquo = ABS(divquo);
+					divquo = neg ? -divquo : divquo;
+
+					printf("%2d.%02d  ", divquo, divrem);
+
+				}
+				else
+				{
+					printf("-    ");
+				}
+			}
+			printf("\n");
+
+			printf("Last adjusted est. power            :\t");
+			for (i = 0; i < ppr_wl->rf_cores; i++)
+				printf("%2d.%02d  ",
+				       DIV_QUO((int8)ppr_wl->est_Pout[i], 4),
+				       DIV_REM(ppr_wl->est_Pout[i], 4));
+			printf("\n");
+		} else {
+			printf("Last est. power:\t%2d.%02d dBm\n",
+			       DIV_QUO((int8)ppr_wl->est_Pout[0], 4),
+			       DIV_REM(ppr_wl->est_Pout[0], 4));
+		}
+
+		if (!mimo && CHSPEC_IS2G(chanspec)) {
+			printf("Last CCK est. power:\t%2d.%02d dBm\n",
+			       DIV_QUO((int8)ppr_wl->est_Pout_cck, 4),
+			       DIV_REM(ppr_wl->est_Pout_cck, 4));
+		}
+exit:
+		if (ppr_board != NULL) {
+			ppr_delete(NULL, ppr_board);
+		}
+		if (ppr_target != NULL) {
+			ppr_delete(NULL, ppr_target);
+		}
+		if (ppr_reg != NULL) {
+			ppr_delete(NULL, ppr_reg);
+		}
+	}
+	free(ppr_wl);
+	return err;
+}
+
+static int wl_get_txpwr_target_max(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	txpwr_target_max_t target_pwr;
+	int i;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_iovar_get(wl, cmd->name, (void *)&target_pwr,  sizeof(target_pwr))) < 0) {
+		fprintf(stderr, "Error: txpwr_target failed. Make sure interface is up.\n");
+		return err;
+	}
+
+	if (target_pwr.version != TXPWR_TARGET_VERSION) {
+		fprintf(stderr, "Error: version [%d] mismatch Driver version:%d\n",
+			TXPWR_TARGET_VERSION, target_pwr.version);
+		return err;
+	}
+
+	printf("Maximum Tx Power Target (chanspec:0x%x):\t", target_pwr.chanspec);
+	for (i = 0; i < target_pwr.rf_cores; i++)
+		printf("%2d.%02d  ",
+		       DIV_QUO(target_pwr.txpwr[i], 4),
+		       DIV_REM(target_pwr.txpwr[i], 4));
+	printf("\n");
+
+	return err;
+}
+
+/*	print a single row of the power data.
+	convert data from dB to qdB;
+	decide if the pwr data is 20 or 40MHz data;
+	print "-" in the other channels
+ */
+void
+wl_txpwr_print_row(const char *label, uint8 chains, txpwr_row_t powers,
+	int8 unsupported_rate, int8 channel_bandwidth, bool verbose)
+{
+	char tmp[]	  = "-      ";
+	char rate2P5[]    = "-      ";
+	char rate5[]      = "-       ";
+	char rate10[]     = "-      ";
+	char rate20[]     = "-      ";
+	char rate20in40[] = "-      ";
+	char rate40[]     = "-      ";
+	char rate80[]     = "-      ";
+	char rate20in80[] = "-      ";
+	char rate40in80[] = "-      ";
+	char rate160[]       = "-      ";
+	char rate20in160[]   = "-      ";
+	char rate40in160[]   = "-      ";
+	char rate80in160[]   = "-      ";
+	char rate8080[]      = "-      ";
+	char rate8080chan2[] = "-      ";
+	char rate20in8080[]  = "-      ";
+	char rate40in8080[]  = "-      ";
+	char rate80in8080[]  = "-      ";
+
+	if (powers.pwr2p5 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr2p5/4);
+		strncpy(rate2P5, tmp, strlen(tmp));
+	}
+	if (powers.pwr5 != unsupported_rate) {
+		sprintf(tmp, "%2.2f ", (float)powers.pwr5/4);
+		strncpy(rate5, tmp, strlen(tmp));
+	}
+	if (powers.pwr10 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr10/4);
+		strncpy(rate10, tmp, strlen(tmp));
+	}
+	if (powers.pwr20 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr20/4);
+		strncpy(rate20, tmp, strlen(tmp));
+	}
+	if (powers.pwr20in40 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr20in40/4);
+		strncpy(rate20in40, tmp, strlen(tmp));
+	}
+	if (powers.pwr40 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr40/4);
+		strncpy(rate40, tmp, strlen(tmp));
+	}
+	if (powers.pwr80 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr80/4);
+		strncpy(rate80, tmp, strlen(tmp));
+	}
+	if (powers.pwr20in80 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr20in80/4);
+		strncpy(rate20in80, tmp, strlen(tmp));
+	}
+	if (powers.pwr40in80 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr40in80/4);
+		strncpy(rate40in80, tmp, strlen(tmp));
+	}
+	if (powers.pwr20 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr20/4);
+		strncpy(rate20, tmp, strlen(tmp));
+	}
+	if (powers.pwr160 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr160/4);
+		strncpy(rate160, tmp, strlen(tmp));
+	}
+	if (powers.pwr20in160 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr20in160/4);
+		strncpy(rate20in160, tmp, strlen(tmp));
+	}
+	if (powers.pwr40in160 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr40in160/4);
+		strncpy(rate40in160, tmp, strlen(tmp));
+	}
+	if (powers.pwr80in160 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr80in160/4);
+		strncpy(rate80in160, tmp, strlen(tmp));
+	}
+	if (powers.pwr8080 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr8080/4);
+		strncpy(rate8080, tmp, strlen(tmp));
+	}
+	if (powers.pwr8080chan2 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr8080chan2/4);
+		strncpy(rate8080chan2, tmp, strlen(tmp));
+	}
+	if (powers.pwr20in8080 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr20in8080/4);
+		strncpy(rate20in8080, tmp, strlen(tmp));
+	}
+	if (powers.pwr40in8080 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr40in8080/4);
+		strncpy(rate40in8080, tmp, strlen(tmp));
+	}
+	if (powers.pwr80in8080 != unsupported_rate) {
+		sprintf(tmp, "%2.2f", (float)powers.pwr80in8080/4);
+		strncpy(rate80in8080, tmp, strlen(tmp));
+	}
+
+
+	printf("%-23s%d       ", label, chains);
+	if (!verbose) {
+		switch (channel_bandwidth) {
+		case WL_BW_2P5MHZ:
+			printf("%s\n", rate2P5);
+			break;
+		case WL_BW_5MHZ:
+			printf("%s\n", rate5);
+			break;
+		case WL_BW_10MHZ:
+			printf("%s\n", rate10);
+			break;
+		case WL_BW_20MHZ:
+			printf("%s\n", rate20);
+			break;
+		case WL_BW_40MHZ:
+			printf("%s%s\n", rate20in40, rate40);
+			break;
+		case WL_BW_80MHZ:
+			printf("%s%s%s\n", rate20in80, rate40in80, rate80);
+			break;
+		case WL_BW_160MHZ:
+			printf("%s%s%s%s\n", rate20in160, rate40in160, rate80in160, rate160);
+			break;
+		case WL_BW_8080MHZ:
+			printf("%s%s%s%s%s\n", rate20in8080, rate40in8080, rate80in8080,
+				rate8080, rate8080chan2);
+			break;
+		}
+	} else {
+		printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+			rate2P5, rate5, rate10,
+			rate20, rate20in40, rate40, rate20in80, rate40in80, rate80,
+			rate20in160, rate40in160, rate80in160, rate160,
+			rate20in8080, rate40in8080, rate80in8080, rate8080, rate8080chan2);
+	}
+
+}
+
+static void
+wl_txpwr_array_row_print(ppr_t *pprptr, int8 channel_bandwidth,	reg_rate_index_t rate_index)
+{
+	const char *label;
+	txpwr_row_t powers;
+	memset(&powers, (unsigned char)WL_RATE_DISABLED, sizeof(txpwr_row_t));
+
+	if (rate_index == NO_RATE)
+	{
+		printf("(NO_RATE)             -      -      -      -      "
+			"-      -      -      -      "
+			"-      -      -      -      -      -      -      -      "
+			"-      -      -    \n");
+	}
+	else
+	{
+		clm_rate_group_id_t group_id = ppr_table[rate_index].id;
+		label = ppr_table[rate_index].label;
+
+		switch (channel_bandwidth) {
+		case WL_BW_2P5MHZ:
+			powers.pwr2p5    = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_2P5);
+			break;
+
+		case WL_BW_5MHZ:
+			powers.pwr5      = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_5);
+			break;
+
+		case WL_BW_10MHZ:
+			powers.pwr10     = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_10);
+			break;
+
+		case WL_BW_20MHZ:
+			powers.pwr20     = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_20);
+			break;
+
+		case WL_BW_40MHZ:
+			powers.pwr20in40 = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_20IN40);
+			powers.pwr40     = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_40);
+			break;
+
+		case WL_BW_80MHZ:
+			powers.pwr80     = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_80);
+			powers.pwr20in80 = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_20IN80);
+			powers.pwr40in80 = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_40IN80);
+			break;
+
+		case WL_BW_160MHZ:
+			powers.pwr160     = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_160);
+			powers.pwr20in160 = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_20IN160);
+			powers.pwr40in160 = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_40IN160);
+			powers.pwr80in160 = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_80IN160);
+			break;
+
+		case WL_BW_8080MHZ:
+			powers.pwr8080      = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_8080);
+			powers.pwr8080chan2 = wl_ppr_get_pwr(pprptr, rate_index,
+				WL_TX_BW_8080CHAN2);
+			powers.pwr20in8080  = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_20IN8080);
+			powers.pwr40in8080  = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_40IN8080);
+			powers.pwr80in8080  = wl_ppr_get_pwr(pprptr, rate_index, WL_TX_BW_80IN8080);
+			break;
+		}
+
+		wl_txpwr_print_row(label, ppr_group_table[group_id].chain, powers,
+			WL_RATE_DISABLED, channel_bandwidth, TRUE);
+	}
+}
+
+void
+wl_txpwr_print_header(int8 channel_bandwidth, bool verbose)
+{
+	if (!verbose)
+	{
+		switch (channel_bandwidth) {
+		case WL_BW_2P5MHZ:
+			printf("Rate                  Chains 2.5MHz\n");
+			break;
+		case WL_BW_5MHZ:
+			printf("Rate                  Chains 5MHz\n");
+			break;
+		case WL_BW_10MHZ:
+			printf("Rate                  Chains 10MHz\n");
+			break;
+		case WL_BW_20MHZ:
+			printf("Rate                  Chains 20MHz\n");
+			break;
+		case WL_BW_40MHZ:
+			printf("Rate                  Chains 20in40 40MHz\n");
+			break;
+		case WL_BW_80MHZ:
+			printf("Rate                  Chains 20in80 40in80 80MHz\n");
+			break;
+		case WL_BW_160MHZ:
+			printf("                             20in   40in   80in\n");
+			printf("Rate                  Chains 160    160    160    160\n");
+			break;
+		case WL_BW_8080MHZ:
+			printf("                             20in   40in   80in   chan1  chan2\n");
+			printf("Rate                  Chains 80+80  80+80  80+80  80+80  80+80\n");
+			break;
+
+		}
+	} else {
+		printf("                                                            20in"
+			"          20in   40in          20in   40in   80in          20in   40in   "
+			"80in   chan1  chan2\n");
+		printf("Rate                  Chains 2.5      5      10      20     40     40"
+				"     80     80     80     160    160    160    160    80+80"
+				"  80+80  80+80  80+80  80+80\n");
+	}
+}
+
+static void
+wl_txpwr_array_print(ppr_t* pprptr, int8 bw, bool verbose, bool is5G)
+{
+	clm_rate_group_id_t i;
+	reg_rate_index_t rate_index = DSSS1;
+	wl_txpwr_print_header(bw, verbose);
+	for (i = RATE_GROUP_ID_DSSS; i < RATE_GROUP_ID_COUNT; i++) {
+		wl_txpwr_ppr_print(pprptr, verbose, ppr_group_table[i].rate_type, i, bw,
+			&rate_index, is5G);
+		/* VHT rates are printed in three parts: MCS + VHT8_9 and VHT10_11 */
+		if (ppr_group_table[i].rate_type == PPR_RATE_VHT)
+			i+=2; /* Skip VHT groups because it is alread printed */
+	}
+}
+
+
+/* Print power values for a group of rates. If not in verbose mode and rates
+ * are uniform, only one power value per channel is printed for the whole group
+ */
+static void
+wl_txpwr_ppr_print(ppr_t* pprptr, int vb, ppr_rate_type_t type,
+	clm_rate_group_id_t gid, int8 bw, reg_rate_index_t *rate_index, bool is5G)
+{
+	int8* rates[5] = {0}; /* Dynamic array of up to 5 ratesets for each channel in bw */
+	uint nchannels, rateset_sz;
+	uint vht_extra_rateset_sz = WL_RATESET_SZ_VHT_MCS - WL_RATESET_SZ_HT_MCS;
+	uint vht_prop_sz = WL_RATESET_SZ_VHT_MCS_P - WL_RATESET_SZ_VHT_MCS;
+	uint i, j;
+	const char *label;
+	uint buniform;
+	uint8 chains = ppr_group_table[gid].chain;
+
+	if (pprptr == NULL) {
+		fprintf(stderr, "illegal ppr data!\n");
+		return;
+	}
+
+	switch (bw) {
+		case WL_BW_2P5MHZ:
+		case WL_BW_5MHZ:
+		case WL_BW_10MHZ:
+		case WL_BW_20MHZ:
+			nchannels = 1;
+			break;
+		case WL_BW_40MHZ:
+			nchannels = 2;
+			break;
+		case WL_BW_80MHZ:
+			nchannels = 3;
+			break;
+		case WL_BW_160MHZ:
+			nchannels = 4;
+			break;
+		case WL_BW_8080MHZ:
+			nchannels = 5;
+			break;
+		default:
+			fprintf(stderr, "Error: Unknown bandwidth %d\n", bw);
+			return;
+	}
+
+	switch (type) {
+		case PPR_RATE_DSSS:
+			rateset_sz = sizeof(ppr_dsss_rateset_t);
+			break;
+		case PPR_RATE_OFDM:
+			rateset_sz = sizeof(ppr_ofdm_rateset_t);
+			break;
+		case PPR_RATE_HT:
+			rateset_sz = sizeof(ppr_ht_mcs_rateset_t);
+			break;
+		case PPR_RATE_VHT:
+			rateset_sz = sizeof(ppr_vht_mcs_rateset_t);
+			break;
+		default:
+			fprintf(stderr, "Error: Unknown rate %d\n", type);
+			return;
+	}
+
+	/* Allocate nchannel * rateset_sz array of powers */
+	for (i = 0; i < nchannels; i++) {
+		if ((rates[i] = (int8*)malloc(sizeof(int8) * rateset_sz)) == NULL) {
+			fprintf(stderr, "Error allocating rates array\n");
+			for (j = 0; j < i; j++) free(rates[j]);
+			return;
+		}
+	}
+
+	/* Load channel ratesets for specific type and group id into rate array */
+	switch (bw) {
+		case WL_BW_2P5MHZ:
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_2P5, rates[0]);
+			break;
+		case WL_BW_5MHZ:
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_5, rates[0]);
+			break;
+		case WL_BW_10MHZ:
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_10, rates[0]);
+			break;
+		case WL_BW_20MHZ:
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_20, rates[0]);
+			break;
+		case WL_BW_40MHZ:
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_40, rates[0]);
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_20IN40, rates[1]);
+			break;
+		case WL_BW_80MHZ:
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_80, rates[0]);
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_40IN80, rates[1]);
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_20IN80, rates[2]);
+			break;
+		case WL_BW_160MHZ:
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_160, rates[0]);
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_80IN160, rates[1]);
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_40IN160, rates[2]);
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_20IN160, rates[3]);
+			break;
+		case WL_BW_8080MHZ:
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_8080, rates[0]);
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_80IN8080, rates[1]);
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_40IN8080, rates[2]);
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_20IN8080, rates[3]);
+			wl_txpwr_ppr_get_rateset(pprptr, type, gid, WL_TX_BW_8080CHAN2, rates[4]);
+			break;
+	}
+
+	if (type == PPR_RATE_DSSS && is5G) {
+		int tx_pwr_min = ppr_get_min(pprptr, WL_RATE_DISABLED);
+		for (i = 0; i < nchannels; i++) {
+			for (j = 0; j < rateset_sz; j++) {
+				if (rates[i][j] == tx_pwr_min)
+					rates[i][j] = WL_RATE_DISABLED;
+			}
+		}
+	}
+
+	/* Split VHT rates into different groups. */
+	if (type == PPR_RATE_VHT) {
+		rateset_sz -= (sizeof(ppr_vht_mcs_rateset_t) - sizeof(ppr_ht_mcs_rateset_t));
+
+	}
+
+	/* Uniform group if for each channel, all rates are equal */
+	buniform = !vb;
+	for (i = 0; i < nchannels && buniform; i++) {
+		buniform &= wl_array_check_val(rates[i], rateset_sz, rates[i][0]);
+	}
+
+	if (buniform) {
+		/* Uniform, so just print first rate */
+		label = get_clm_rate_group_label(gid);
+		if (strcmp(label, ""))
+			wl_txpwr_ppr_print_row(label, chains, bw, vb, rates, 0);
+	} else {
+		for (i = 0; i < rateset_sz; i++) {
+			label = ppr_table[*rate_index + i].label;
+			if (strcmp(label, ""))
+				wl_txpwr_ppr_print_row(label, chains, bw, vb, rates, i);
+		}
+	}
+
+	/* Print VHT8-9 and VHT10-11 as seperate groups */
+	if (type == PPR_RATE_VHT) {
+		/* VHT8-9 */
+		buniform = !vb;
+		for (i = 0; i < nchannels && buniform; i++) {
+			int8* vht_extra_rateset = &rates[i][rateset_sz];
+			buniform &= wl_array_check_val(vht_extra_rateset, vht_extra_rateset_sz,
+				vht_extra_rateset[0]);
+		}
+
+		if (buniform) {
+			/* Uniform, so just print first extra rate */
+			label = get_clm_rate_group_label(gid+1); /* VHT8-9 label */
+			if (strcmp(label, ""))
+				wl_txpwr_ppr_print_row(label, chains, bw, vb, rates, rateset_sz);
+		} else {
+			for (i = rateset_sz; i < (rateset_sz + vht_extra_rateset_sz); i++) {
+				label = ppr_table[*rate_index + i].label;
+				if (strcmp(label, ""))
+					wl_txpwr_ppr_print_row(label, chains, bw, vb, rates, i);
+			}
+		}
+
+		/* VHT10-11 */
+		buniform = !vb;
+		for (i = 0; i < nchannels && buniform; i++) {
+			int8* vht_prop_rateset = &rates[i][rateset_sz + vht_extra_rateset_sz];
+			buniform &= wl_array_check_val(vht_prop_rateset, vht_prop_sz,
+				vht_prop_rateset[0]);
+		}
+
+		if (buniform) {
+			/* Uniform, so just print first extra rate */
+			label = get_clm_rate_group_label(gid+2); /* VHT10-11 label */
+			if (strcmp(label, ""))
+				wl_txpwr_ppr_print_row(label, chains, bw, vb, rates,
+						rateset_sz + vht_extra_rateset_sz);
+		} else {
+			i = rateset_sz + vht_extra_rateset_sz;
+			for (; i < (rateset_sz + vht_extra_rateset_sz + vht_prop_sz);
+				i++) {
+				label = ppr_table[*rate_index + i].label;
+				if (strcmp(label, ""))
+					wl_txpwr_ppr_print_row(label, chains, bw, vb, rates, i);
+			}
+		}
+	}
+
+	*rate_index += rateset_sz;
+	if (type == PPR_RATE_VHT) {
+		*rate_index += (vht_extra_rateset_sz + vht_prop_sz);
+	}
+
+	for (i = 0; i < nchannels; i++) {
+		free(rates[i]);
+	}
+}
+
+/* Print row of power values for a specific rate. */
+void wl_txpwr_ppr_print_row(const char* label, int8 chains, int8 bw, bool vb,
+	int8** rates, uint rate_index)
+{
+	txpwr_row_t powers;
+	memset(&powers, (unsigned char)WL_RATE_DISABLED, sizeof(txpwr_row_t));
+
+	/* Set relevant power values based on bandwidth */
+	switch (bw) {
+		case WL_BW_2P5MHZ:
+			powers.pwr2p5 = rates[0][rate_index];
+			break;
+		case WL_BW_5MHZ:
+			powers.pwr5 = rates[0][rate_index];
+			break;
+		case WL_BW_10MHZ:
+			powers.pwr10 = rates[0][rate_index];
+			break;
+		case WL_BW_20MHZ:
+			powers.pwr20 = rates[0][rate_index];
+			break;
+		case WL_BW_40MHZ:
+			powers.pwr40 = rates[0][rate_index];
+			powers.pwr20in40 = rates[1][rate_index];
+			break;
+		case WL_BW_80MHZ:
+			powers.pwr80 = rates[0][rate_index];
+			powers.pwr40in80 = rates[1][rate_index];
+			powers.pwr20in80 = rates[2][rate_index];
+			break;
+		case WL_BW_160MHZ:
+			powers.pwr160 = rates[0][rate_index];
+			powers.pwr80in160 = rates[1][rate_index];
+			powers.pwr40in160 = rates[2][rate_index];
+			powers.pwr20in160 = rates[3][rate_index];
+			break;
+		case WL_BW_8080MHZ:
+			powers.pwr8080 = rates[0][rate_index];
+			powers.pwr80in8080 = rates[1][rate_index];
+			powers.pwr40in8080 = rates[2][rate_index];
+			powers.pwr20in8080 = rates[3][rate_index];
+			powers.pwr8080chan2 = rates[4][rate_index];
+			break;
+		default:
+			break;
+	}
+
+	wl_txpwr_print_row(label, chains, powers, WL_RATE_DISABLED, bw, vb);
+}
+
+/* Helper function which gets arbitrary rateset as a function of rate_type.
+ * Returns rateset into a int8 array.
+ */
+void wl_txpwr_ppr_get_rateset(ppr_t* pprptr, ppr_rate_type_t type,
+	clm_rate_group_id_t gid, wl_tx_bw_t bw, int8* rateset)
+{
+	const ppr_group_t* group = &ppr_group_table[gid];
+	switch (type) {
+		case PPR_RATE_DSSS:
+			/* ASSERT(rateset_sz == sizeof(ppr_dsss_rateset_t)) */
+			ppr_get_dsss(pprptr, bw, group->chain,
+				(ppr_dsss_rateset_t*)rateset);
+			break;
+		case PPR_RATE_OFDM:
+			/* ASSERT(rateset_sz == sizeof(ppr_ofdm_rateset_t)) */
+			ppr_get_ofdm(pprptr, bw, group->mode, group->chain,
+				(ppr_ofdm_rateset_t*)rateset);
+			break;
+		case PPR_RATE_HT:
+			/* ASSERT(rateset_sz == sizeof(ppr_ht_mcs_rateset_t)) */
+			ppr_get_ht_mcs(pprptr, bw, group->nss, group->mode, group->chain,
+				(ppr_ht_mcs_rateset_t*)rateset);
+			break;
+		case PPR_RATE_VHT:
+			/* ASSERT(rateset_sz == sizeof(ppr_vht_mcs_rateset_t)) */
+			ppr_get_vht_mcs(pprptr, bw, group->nss, group->mode, group->chain,
+				(ppr_vht_mcs_rateset_t*)rateset);
+			break;
+		default:
+			/* ASSERT(0) */
+			break;
+	}
+}
+
+/* helper function to check if the array are uniformly same as the input value */
+static int wl_array_check_val(int8 *pwr, uint count, int8 val)
+{
+	uint i;
+	for (i = 0; i < count; i++) {
+		if (pwr[i] != val)
+			return FALSE;
+	}
+	return TRUE;
+}
+
+#define WL_JOIN_PARAMS_MAX WL_JOIN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(chanspec_t)
+
+/* when prescanned option is specified */
+static int
+wl_join_prescanned(void *wl, wl_join_params_t *join_params, uint *join_params_size)
+{
+	/* load with prescanned channels and bssids */
+	int ret, err = 0;
+	char *destbuf;
+	wl_scan_results_t *scanres = NULL;
+	wl_bss_info_t *bi;
+	uint i, cnt, bssid_cnt, bi_len;
+
+	if ((destbuf = malloc(WL_DUMP_BUF_LEN)) == NULL) {
+		fprintf(stderr, "Failed to allocate %d-byte buffer for scanresults\n",
+			WL_DUMP_BUF_LEN);
+		err = BCME_NOMEM;
+		goto pexit;
+	}
+
+	if ((ret = wl_get_scan(wl, WLC_SCAN_RESULTS, destbuf, WL_DUMP_BUF_LEN)) != 0) {
+		fprintf(stderr, "failed to fetch scan results, err %d\n", ret);
+		err = ret;
+		goto pexit;
+	}
+
+	scanres = (wl_scan_results_t *)destbuf;
+	if (scanres->version != WL_BSS_INFO_VERSION) {
+		fprintf(stderr, "scan parsing failed (expect version %d, got %d)\n",
+			WL_BSS_INFO_VERSION, scanres->version);
+		err = -1;
+		goto pexit;
+	}
+
+	/* find matching ssids to fill the channel list */
+	for (cnt = i = 0, bi = scanres->bss_info; i < scanres->count;
+		 i++, bi = (wl_bss_info_t*)((int8*)bi + bi_len)) {
+		bi_len = dtoh32(bi->length);
+		if ((bi->SSID_len != join_params->ssid.SSID_len) ||
+			memcmp(bi->SSID, join_params->ssid.SSID,
+			join_params->ssid.SSID_len)) {
+			continue;
+		} else {
+			dump_bss_info(bi);
+			printf("--------------------------------\n");
+		}
+
+		memcpy(&join_params->params.chanspec_list[cnt],
+			&bi->chanspec, sizeof(chanspec_t));
+		cnt++;
+	}
+	bssid_cnt = (uint16)cnt;
+
+	/* append the corresponding bssids */
+	destbuf = (char*)&join_params->params.chanspec_list[cnt];
+	*join_params_size = destbuf - (char*)join_params;
+	*join_params_size += (cnt * sizeof(struct ether_addr));
+
+	if (*join_params_size > WL_JOIN_PARAMS_MAX) {
+		fprintf(stderr, "Can't fit bssids for all %d APs found\n", cnt);
+		err = -1;
+		goto pexit;
+	}
+
+	for (cnt = i = 0, bi = scanres->bss_info;
+		 (i < scanres->count) && (cnt < bssid_cnt);
+		 i++, bi = (wl_bss_info_t*)((int8*)bi + bi_len)) {
+		bi_len = dtoh32(bi->length);
+		if ((bi->SSID_len != join_params->ssid.SSID_len) ||
+			memcmp(bi->SSID, join_params->ssid.SSID,
+			join_params->ssid.SSID_len)) {
+			continue;
+		}
+
+		memcpy(destbuf, &bi->BSSID, sizeof(struct ether_addr));
+		destbuf += sizeof(struct ether_addr);
+		cnt++;
+	}
+
+	if (cnt != bssid_cnt) {
+		fprintf(stderr, "Mismatched channel and bssid counts!\n");
+		err = -1;
+		goto pexit;
+	}
+
+	if (cnt == 0) {
+		printf("No matches found, issuing normal join.\n");
+	} else {
+		printf("Passing %d channel/bssid pairs.\n", cnt);
+	}
+	join_params->params.bssid_cnt = htod16(bssid_cnt);
+
+pexit:
+	if (scanres)
+		free((char*)scanres);
+	else
+		free(destbuf);
+	return err;
+}
+
+/* wl join <ssid> [key <0-3>:xxxxx]
+ *                [imode bss|ibss]
+ *                [amode open|shared|openshared|wpa|wpapsk|wpa2|wpa2psk|wpanone|ftpsk]
+ *                [options]
+ * Options:
+ * -b MAC, --bssid=MAC, where MAC is in xx:xx:xx:xx:xx:xx format
+ * -c CL, --chanspecs=CL, where CL is a comma or space separated list of chanspecs
+ * -p, -passive: uses  join iovar instead of SET_SSID ioctl to force passive assoc scan
+ */
+
+static int
+wl_join(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK, idx = 0;
+	wl_join_params_t *join_params;
+	uint join_params_size;
+	wl_wsec_key_t key;
+	int wsec = 0, auth = 0, infra = 1;
+	int wpa_auth = WPA_AUTH_DISABLED;
+	char* cmd_name;
+	bool prescanned = FALSE;
+	int passive = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	cmd_name = *argv++;
+
+	/* allocate the max storage */
+	join_params_size = WL_JOIN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(chanspec_t);
+	if ((join_params = malloc(join_params_size)) == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for assoc params\n", join_params_size);
+		return BCME_NOMEM;
+	}
+	memset(join_params, 0, join_params_size);
+	memcpy(&join_params->params.bssid, &ether_bcast, ETHER_ADDR_LEN);
+
+	/* verify that SSID was specified and is a valid length */
+	if (!*argv || (strlen(*argv) > DOT11_MAX_SSID_LEN)) {
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	join_params->ssid.SSID_len = strlen(*argv);
+	memcpy(join_params->ssid.SSID, *argv, join_params->ssid.SSID_len);
+
+	/* default to plain old ioctl */
+	join_params_size = sizeof(wlc_ssid_t);
+
+	/* get infrastructure mode */
+	if (wlu_iovar_getint(wl, "infra_configuration", &infra) < 0) {
+		fprintf(stderr, "iovar infra_configuration GET failed, ret %d\n", ret);
+		goto exit;
+	}
+	infra = dtoh32(infra);
+
+	/* get authentication mode */
+	if ((ret = wlu_get(wl, WLC_GET_AUTH, &auth, sizeof(int))) < 0) {
+		fprintf(stderr, "ioctl WLC_GET_AUTH failed, ret %d\n", ret);
+		goto exit;
+	}
+	auth = dtoh32(auth);
+
+	/* get current wsec */
+	if (wlu_iovar_getint(wl, "wsec", &wsec) < 0) {
+		wsec = 0;
+	}
+	wsec = dtoh32(wsec);
+
+	/* get WPA_auth mode */
+	if ((ret = wlu_get(wl, WLC_GET_WPA_AUTH, &wpa_auth, sizeof(wpa_auth))) < 0) {
+		fprintf(stderr, "ioctl WLC_GET_WPA_AUTH failed, ret %d\n", ret);
+		goto exit;
+	}
+	wpa_auth = dtoh32(wpa_auth);
+
+	while (*++argv) {
+		if (!stricmp(*argv, "wepkey") || !stricmp(*argv, "wep") || !stricmp(*argv, "key")) {
+			/* specified wep key */
+			memset(&key, 0, sizeof(key));
+			if (!*++argv) {
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			/* WEP index specified */
+			if (*(argv[0]+1) == ':') {
+				idx = *argv[0] - 0x30;
+				if (idx < 0 || idx > 3) {
+					fprintf(stderr, "Invalid key index %d specified\n", idx);
+					ret = BCME_BADARG;
+					goto exit;
+				}
+				argv[0] += 2; /* colon + digit */
+			}
+			key.index = idx;
+
+			if (parse_wep(argv, &key, FALSE)) {
+				ret = BCME_BADARG;
+				goto exit;
+			}
+
+			key.index = htod32(key.index);
+			key.len = htod32(key.len);
+			key.algo = htod32(key.algo);
+			key.flags = htod32(key.flags);
+
+			if ((ret = wlu_set(wl, WLC_SET_KEY, &key, sizeof(wl_wsec_key_t))) < 0) {
+				goto exit;
+			}
+			wsec |= WEP_ENABLED;
+		}
+		/* specified infrastructure mode */
+		else if (!stricmp(*argv, "imode") ||
+		         !stricmp(*argv, "infra") ||
+		         !stricmp(*argv, "mode")) {
+			if (!*++argv) {
+				fprintf(stderr, "%s %s: expected argument after \"infra\" keyword "
+				        "but command line ended.\n", wlu_av0, cmd_name);
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			} else if (!stricmp(*argv, "ibss") ||
+			           !stricmp(*argv, "adhoc") ||
+			           !stricmp(*argv, "ad-hoc")) {
+				infra = WL_BSSTYPE_INDEP;
+			} else if (!stricmp(*argv, "bss") ||
+			           !stricmp(*argv, "managed") ||
+			           !strnicmp(*argv, "infra", 5)) {
+				infra = WL_BSSTYPE_INFRA;
+			} else {
+				fprintf(stderr, "%s %s: unrecongnized parameter \"%s\" after "
+				        "\"infra\" keyword\n", wlu_av0, cmd_name, *argv);
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		/* specified authentication mode */
+		else if (!stricmp(*argv, "amode") || !strnicmp(*argv, "auth", 4)) {
+			if (!*++argv) {
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			auth = WL_AUTH_OPEN_SYSTEM;
+			wpa_auth = WPA_AUTH_DISABLED;
+			if (!stricmp(*argv, "open"))
+				auth = WL_AUTH_OPEN_SYSTEM;
+			else if (!stricmp(*argv, "shared"))
+				auth = WL_AUTH_SHARED_KEY;
+			else if (!stricmp(*argv, "openshared"))
+				auth = WL_AUTH_OPEN_SHARED;
+			else if (!stricmp(*argv, "wpanone"))
+				wpa_auth = WPA_AUTH_NONE;
+			else if (!stricmp(*argv, "wpa"))
+				wpa_auth = WPA_AUTH_UNSPECIFIED;
+			else if (!stricmp(*argv, "wpapsk"))
+				 wpa_auth = WPA_AUTH_PSK;
+			else if (!stricmp(*argv, "wpa2"))
+				wpa_auth = WPA2_AUTH_UNSPECIFIED;
+			else if (!stricmp(*argv, "wpa2psk"))
+				wpa_auth = WPA2_AUTH_PSK;
+#ifdef BCMWAPI_WAI
+			else if (!stricmp(*argv, "wapi"))
+				wpa_auth = WAPI_AUTH_UNSPECIFIED;
+			else if (!stricmp(*argv, "wapipsk"))
+				wpa_auth = WAPI_AUTH_PSK;
+#endif /* BCMWAPI_WAI */
+			else if (!stricmp(*argv, "ftpsk"))
+				wpa_auth = WPA2_AUTH_PSK | WPA2_AUTH_FT;
+			else if (!stricmp(*argv, "wpa2-sha256"))
+				wpa_auth = WPA2_AUTH_1X_SHA256;
+			else if (!stricmp(*argv, "wpa2psk-sha256"))
+				wpa_auth = WPA2_AUTH_PSK_SHA256;
+			else {
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		else if (!stricmp(*argv, "-passive") || !stricmp(*argv, "-p")) {
+			/* Use extended join iovar to assoc_scan passively */
+			passive = 1;
+		}
+		/* optional assoc params */
+		else if ((ret = wl_parse_assoc_params(argv, &join_params->params,
+				&prescanned)) == BCME_OK) {
+			join_params_size = WL_JOIN_PARAMS_FIXED_SIZE +
+				dtoh32(join_params->params.chanspec_num) * sizeof(chanspec_t);
+			break;
+		}
+		else {
+			fprintf(stderr, "%s %s: unable to parse parameter \"%s\"\n",
+				wlu_av0, cmd_name, *argv);
+			goto exit;
+		}
+	}
+
+	/* set infrastructure mode */
+	infra = htod32(infra);
+	if ((ret = wlu_set(wl, WLC_SET_INFRA, &infra, sizeof(int))) < 0) {
+		fprintf(stderr, "ioctl WLC_SET_INFRA failed, ret %d\n", ret);
+		goto exit;
+	}
+
+	/* set authentication mode */
+	auth = htod32(auth);
+	if ((ret = wlu_set(wl, WLC_SET_AUTH, &auth, sizeof(int))) < 0) {
+		fprintf(stderr, "ioctl WLC_SET_AUTH failed, ret %d\n", ret);
+		goto exit;
+	}
+
+	/* set wsec mode */
+	wsec = htod32(wsec);
+	if ((ret = wlu_iovar_setint(wl, "wsec", wsec)) < 0) {
+		fprintf(stderr, "iovar wsec SET failed, ret %d\n", ret);
+		goto exit;
+	}
+
+	/* set WPA_auth mode */
+	wpa_auth = htod32(wpa_auth);
+	if ((ret = wlu_set(wl, WLC_SET_WPA_AUTH, &wpa_auth, sizeof(wpa_auth))) < 0) {
+		fprintf(stderr, "ioctl WLC_SET_WPA_AUTH failed, ret %d\n", ret);
+		goto exit;
+	}
+
+	if (passive) {
+		wl_extjoin_params_t *extjoin_params;
+		int extjoin_size;
+		int i;
+		printf("Using passive assoc scan\n");
+		extjoin_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
+			join_params->params.chanspec_num * sizeof(chanspec_t);
+		if ((extjoin_params = malloc(extjoin_size)) == NULL) {
+			fprintf(stderr, "Error allocating %d bytes for extjoin \n", extjoin_size);
+			ret = BCME_NOMEM;
+			goto exit;
+		}
+
+		/* Copy assoc params from legacy struct into extended struct */
+		memset(extjoin_params, 0, extjoin_size);
+		memcpy(&extjoin_params->ssid.SSID, &join_params->ssid.SSID, DOT11_MAX_SSID_LEN);
+		extjoin_params->ssid.SSID_len = htod32(join_params->ssid.SSID_len);
+
+		memcpy(&extjoin_params->assoc.bssid, &join_params->params.bssid, ETHER_ADDR_LEN);
+		extjoin_params->assoc.chanspec_num = join_params->params.chanspec_num;
+		for (i = 0; i < join_params->params.chanspec_num; i++) {
+			extjoin_params->assoc.chanspec_list[i] =
+				join_params->params.chanspec_list[i];
+		}
+
+		extjoin_params->scan.scan_type = WL_SCANFLAGS_PASSIVE;
+		extjoin_params->scan.nprobes = -1;
+		extjoin_params->scan.active_time = -1;
+		extjoin_params->scan.passive_time = -1;
+		extjoin_params->scan.home_time = -1;
+
+
+		ret = wlu_var_setbuf(wl, "join", extjoin_params, extjoin_size);
+		free(extjoin_params);
+	} else {
+		/* join parameters starts with the ssid */
+		join_params->ssid.SSID_len = htod32(join_params->ssid.SSID_len);
+
+		if (prescanned) {
+			if ((ret = wl_join_prescanned(wl, join_params, &join_params_size)) < 0)
+				goto exit;
+		}
+
+		ret = wlu_set(wl, WLC_SET_SSID, join_params, join_params_size);
+	}
+
+exit:
+	free(join_params);
+	return ret;
+}
+
+/* Set or Get the "bssid" iovar, with an optional config index argument:
+ *	wl bssid [-C N]|[--cfg=N] bssid
+ *
+ * Option:
+ *	-C N
+ *	--cfg=N
+ *	--config=N
+ *	--configuration=N
+ *		specify the config index N
+ * If cfg index not given on a set, the WLC_SET_BSSID ioctl will be used
+ */
+static int
+wl_bssid(void *wl, cmd_t *cmd, char **argv)
+{
+	struct ether_addr ea;
+	int bsscfg_idx = 0;
+	int consumed;
+	int error;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "bssid", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	if (*argv == NULL) {
+		if (consumed == 0) {
+			/* no config index, use WLC_GET_BSSID on the interface */
+			error = wlu_get(wl, WLC_GET_BSSID, &ea, ETHER_ADDR_LEN);
+		} else {
+			/* use "bssid" iovar since a config option was given */
+			error = wlu_bssiovar_get(wl, "bssid", bsscfg_idx, &ea, ETHER_ADDR_LEN);
+		}
+		if (error < 0)
+			return error;
+		printf("%s\n", wl_ether_etoa(&ea));
+
+	} else {
+
+		if (!wl_ether_atoe(*argv, &ea))
+			return BCME_USAGE_ERROR;
+
+		if (consumed == 0) {
+			/* no config index given, use WLC_SET_BSSID */
+			error = wlu_set(wl, WLC_SET_BSSID, &ea, ETHER_ADDR_LEN);
+		} else {
+			/* use "bssid" iovar since a config option was given */
+			error = wl_bssiovar_set(wl, "bssid", bsscfg_idx, &ea, ETHER_ADDR_LEN);
+		}
+	}
+	return error;
+}
+
+/* Set or Get the "ssid" iovar, with an optional config index argument:
+ *	wl ssid [-C N]|[--cfg=N] ssid
+ *
+ * Option:
+ *	-C N
+ *	--cfg=N
+ *	--config=N
+ *	--configuration=N
+ *		specify the config index N
+ * If cfg index not given on a set, the WLC_SET_SSID ioctl will be used
+ */
+int
+wl_ssid(void *wl, cmd_t *cmd, char **argv)
+{
+	char ssidbuf[SSID_FMT_BUF_LEN];
+	wlc_ssid_t ssid = { 0, {0} };
+	int bsscfg_idx = 0;
+	int consumed;
+	int error;
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "ssid", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	if (*argv == NULL) {
+		if (consumed == 0) {
+			/* no config index, use WLC_GET_SSID on the interface */
+			if (cmd->get == WLC_GET_SSID)
+				error = wlu_get(wl, WLC_GET_SSID, &ssid, sizeof(ssid));
+			else
+				error = wlu_iovar_get(wl, cmd->name, &ssid, sizeof(ssid));
+		} else {
+			if (cmd->get == WLC_GET_SSID) {
+				/* use "ssid" iovar since a config option was given */
+				error = wlu_bssiovar_get(wl, "ssid", bsscfg_idx, &ssid,
+				                        sizeof(ssid));
+			} else {
+				error = wlu_bssiovar_get(wl, cmd->name, bsscfg_idx, &ssid,
+				                        sizeof(ssid));
+			}
+		}
+		if (error < 0)
+			return error;
+
+		ssid.SSID_len = dtoh32(ssid.SSID_len);
+		wl_format_ssid(ssidbuf, ssid.SSID, ssid.SSID_len);
+		printf("Current %s: \"%s\"\n",
+		       (cmd->get == WLC_GET_SSID)? "SSID": cmd->name,
+		       ssidbuf);
+	} else {
+		if (strlen(argv[0]) > DOT11_MAX_SSID_LEN) {
+			fprintf(stderr, "SSID arg \"%s\" must be 32 chars or less\n", argv[0]);
+			return BCME_BADARG;
+		}
+		ssid.SSID_len = strlen(argv[0]);
+		memcpy(ssid.SSID, argv[0], ssid.SSID_len);
+
+		wl_format_ssid(ssidbuf, ssid.SSID, ssid.SSID_len);
+		printf("Setting %s: \"%s\"\n", (cmd->set == WLC_SET_SSID)? "SSID": cmd->name,
+		       ssidbuf);
+
+		ssid.SSID_len = htod32(ssid.SSID_len);
+		if (consumed == 0) {
+			/* no config index given, use WLC_SET_SSID */
+			if (cmd->set == WLC_SET_SSID) {
+				error = wlu_set(wl, WLC_SET_SSID, &ssid, sizeof(wlc_ssid_t));
+			} else {
+				error = wlu_iovar_set(wl, cmd->name, &ssid, sizeof(wlc_ssid_t));
+			}
+		} else {
+			if (cmd->set == WLC_SET_SSID) {
+				/* use "ssid" iovar since a config option was given */
+				error = wl_bssiovar_set(wl, "ssid", bsscfg_idx, &ssid,
+				                        sizeof(wlc_ssid_t));
+			} else
+				error = wl_bssiovar_set(wl, cmd->name, bsscfg_idx, &ssid,
+				                        sizeof(wlc_ssid_t));
+		}
+	}
+	return error;
+}
+
+static const char*
+wl_smfs_map_type(uint8 type)
+{
+	static const struct {uint8 type; char name[32];} type_names[] = {
+		{SMFS_TYPE_AUTH, "Authentication_Request"},
+		{SMFS_TYPE_ASSOC, "Association_Request"},
+		{SMFS_TYPE_REASSOC, "Reassociation_Request"},
+		{SMFS_TYPE_DISASSOC_TX, "Disassociation_Request_TX"},
+		{SMFS_TYPE_DISASSOC_RX, "Disassociation_Request_RX"},
+		{SMFS_TYPE_DEAUTH_TX, "Deauthentication_Request_TX"},
+		{SMFS_TYPE_DEAUTH_RX, "Deauthentication_Request_RX"}
+	};
+
+	const char *tname = "UNKNOWN";
+	uint i;
+
+	for (i = 0; i < ARRAYSIZE(type_names); i++) {
+		if (type_names[i].type == type)
+		    tname = type_names[i].name;
+	}
+	return tname;
+}
+
+static int
+wl_disp_smfs(char *inbuf)
+{
+	static const char *codename[] = {"Status_code", "Reason_code"};
+	wl_smf_stats_t *smf_stats;
+	wl_smfs_elem_t *elemt = NULL;
+	const char *namebuf;
+	uint32 version;
+	int count;
+
+	smf_stats = (wl_smf_stats_t *) inbuf;
+	namebuf = wl_smfs_map_type(smf_stats->type);
+
+	version = dtoh32(smf_stats->version);
+	if (version != SMFS_VERSION) {
+		fprintf(stderr, "Sorry, your driver has smfs_version %d "
+			"but this program supports only version %d.\n",
+			version, SMFS_VERSION);
+		return -1;
+	}
+
+	printf("Frame type: %s\n", namebuf);
+	printf("\tIgnored Count: %d\n", dtoh32(smf_stats->ignored_cnt));
+	printf("\tMalformed Count: %d\n", dtoh32(smf_stats->malformed_cnt));
+
+	count = dtoh32(smf_stats->count_total);
+
+	if (count) {
+		namebuf = codename[dtoh32(smf_stats->codetype)];
+		printf("\tSuccessful/Failed Count:\n");
+		elemt = &smf_stats->elem[0];
+	}
+
+	while (count) {
+		printf("\t\t%s %d Count: %d\n",  namebuf, dtoh16(elemt->code),
+		  dtoh32(elemt->count));
+		elemt ++;
+		count --;
+	}
+
+	return 0;
+
+}
+
+/*
+ * Check for the smfstats parameters. One of defined parameters can be passed in.
+ */
+static int
+wl_smfs_option(char **argv, int* idx, int *consumed, int* clear)
+{
+	int err = 0;
+	char *p;
+	char const * smfs_opt[] = {"auth", "assoc", "reassoc", "disassoc_tx",
+							   "disassoc_rx", "deauth_tx", "deauth_rx"};
+	char const * clear_opt = "clear";
+	int i;
+	char const * cur_opt;
+
+	if (*argv == NULL) {
+		goto exit;
+	}
+
+	p = *argv++;
+
+	for (i = 0; i < SMFS_TYPE_MAX; i++) {
+		cur_opt = smfs_opt[i];
+		if (!strcmp(p, cur_opt)) {
+			*idx = i;
+			*consumed += 1;
+			goto exit;
+		}
+	}
+
+	if (!strcmp(p, clear_opt))
+		*clear = 1;
+
+exit:
+	return err;
+}
+
+/* Get or Clear (set)  the "smfstats" iovar, with an optional config index argument:
+ *	wl smfstats [-C N]|[--cfg=N] 0
+ *
+ * Option:
+ *	-C N
+ *	--cfg=N
+ *	--config=N
+ *	--configuration=N
+ *		specify the config index N
+ * If cfg index not given on a set, the WLC_SET_SMF_STATS ioctl will be used
+ */
+static int
+wl_smfstats(void *wl, cmd_t *cmd, char **argv)
+{
+	int bsscfg_idx = 0;
+	int cfg_consumed = 0, smfs_consumed = 0;
+	int err;
+	int i, val;
+	int smf_index = 0;
+	int smfs_clear = 0;
+
+	BCM_REFERENCE(cmd);
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((err = wl_cfg_option(argv, "smfstats", &bsscfg_idx, &cfg_consumed)) != 0)
+		return err;
+
+	argv += cfg_consumed;
+
+	if ((err = wl_smfs_option(argv, &smf_index, &smfs_consumed, &smfs_clear)) != 0)
+		return err;
+
+	if (!smfs_clear) {
+		if (cfg_consumed == 0) {
+			if (smfs_consumed) {
+				err = wlu_iovar_getbuf(wl, "smfstats", &smf_index, sizeof(int),
+				   buf, WLC_IOCTL_SMLEN);
+				if (!err)
+					err = wl_disp_smfs(buf);
+			}
+			else {
+				for (i = 0; i < SMFS_TYPE_MAX; i++) {
+					smf_index = i;
+					err = wlu_iovar_getbuf(wl, "smfstats", &smf_index,
+					   sizeof(int), buf, WLC_IOCTL_SMLEN);
+					if (!err)
+						err = wl_disp_smfs(buf);
+				}
+			}
+		} else {
+			/* use "stats" iovar since a config option was given */
+			if (smfs_consumed) {
+				err = wl_bssiovar_getbuf(wl, "smfstats", bsscfg_idx, &smf_index,
+				  sizeof(int), buf, WLC_IOCTL_SMLEN);
+				if (!err)
+					err = wl_disp_smfs(buf);
+			}
+			else {
+				for (i = 0; i < SMFS_TYPE_MAX; i++) {
+					smf_index = i;
+					err = wl_bssiovar_getbuf(wl, "smfstats", bsscfg_idx,
+						&smf_index, sizeof(int), buf, WLC_IOCTL_SMLEN);
+					if (!err)
+						err = wl_disp_smfs(buf);
+				}
+			}
+		}
+		if (err < 0)
+			return err;
+	} else {
+		val = 0;
+
+		if (cfg_consumed == 0)
+			err = wlu_iovar_setint(wl, "smfstats", val);
+		else
+			err = wl_bssiovar_setint(wl, "smfstats", bsscfg_idx, val);
+
+	}
+	return err;
+}
+
+
+/* Quarter dBm units to mW
+ * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
+ * Table is offset so the last entry is largest mW value that fits in
+ * a uint16.
+ */
+
+#define QDBM_OFFSET 153 /* QDBM_OFFSET */
+#define QDBM_TABLE_LEN 40 /* QDBM_TABLE_LEN */
+
+/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
+ * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
+ */
+#define QDBM_TABLE_LOW_BOUND 6493 /* QDBM_TABLE_LOW_BOUND */
+
+/* Largest mW value that will round down to the last table entry,
+ * QDBM_OFFSET + QDBM_TABLE_LEN-1.
+ * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
+ */
+#define QDBM_TABLE_HIGH_BOUND 64938 /* QDBM_TABLE_HIGH_BOUND */
+
+static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
+/* qdBm:        +0	+1	+2	+3	+4	+5	+6	+7	*/
+/* 153: */      6683,	7079,	7499,	7943,	8414,	8913,	9441,	10000,
+/* 161: */      10593,	11220,	11885,	12589,	13335,	14125,	14962,	15849,
+/* 169: */      16788,	17783,	18836,	19953,	21135,	22387,	23714,	25119,
+/* 177: */      26607,	28184,	29854,	31623,	33497,	35481,	37584,	39811,
+/* 185: */      42170,	44668,	47315,	50119,	53088,	56234,	59566,	63096
+};
+
+static uint16
+wl_qdbm_to_mw(int8 qdbm)
+{
+	uint factor = 1;
+	int idx = qdbm - QDBM_OFFSET;
+
+	if (idx >= QDBM_TABLE_LEN) {
+		/* clamp to max uint16 mW value */
+		return 0xFFFF;
+	}
+
+	/* scale the qdBm index up to the range of the table 0-40
+	 * where an offset of 40 qdBm equals a factor of 10 mW.
+	 */
+	while (idx < 0) {
+		idx += 40;
+		factor *= 10;
+	}
+
+	/* return the mW value scaled down to the correct factor of 10,
+	 * adding in factor/2 to get proper rounding.
+	 */
+	return ((nqdBm_to_mW_map[idx] + factor/2) / factor);
+}
+
+static int8
+wl_mw_to_qdbm(uint16 mw)
+{
+	uint8 qdbm;
+	int offset;
+	uint mw_uint = mw;
+	uint boundary;
+
+	/* handle boundary case */
+	if (mw_uint <= 1)
+		return WL_RATE_DISABLED;
+
+	offset = QDBM_OFFSET;
+
+	/* move mw into the range of the table */
+	while (mw_uint < QDBM_TABLE_LOW_BOUND) {
+		mw_uint *= 10;
+		offset -= 40;
+	}
+
+	for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) {
+		boundary = nqdBm_to_mW_map[qdbm] +
+			(nqdBm_to_mW_map[qdbm+1] - nqdBm_to_mW_map[qdbm])/2;
+		if (mw_uint < boundary) break;
+	}
+
+	qdbm += (int8)offset;
+
+	return (qdbm);
+}
+
+#define WLC_TXPWR_DB_FACTOR 4
+#define UNIT_MW		1 /* UNIT_MW */
+#define UNIT_QDBM	2 /* UNIT_QDBM */
+#define UNIT_DBM	3 /* UNIT_DBM */
+
+static int
+wl_txpwr1(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, val, new_val = 0, unit;
+	const char *name = "qtxpower";
+	bool override = FALSE;
+	int8 temp_val;
+
+	if (!*++argv) {
+		int divquo, divrem;
+		bool neg;
+
+		if (cmd->get < 0)
+			return -1;
+		if ((ret = wlu_iovar_getint(wl, name, &val)) < 0)
+			return ret;
+
+		override = ((val & WL_TXPWR_OVERRIDE) != 0);
+		val &= ~WL_TXPWR_OVERRIDE;
+		temp_val = (int8)(val & 0xff);
+
+		divquo = DIV_QUO(temp_val, 4);
+		divrem = DIV_REM(temp_val, 4);
+		neg = (divrem < 0) || (divquo < 0);
+		divrem = ABS(divrem);
+		divquo = ABS(divquo);
+		divquo = neg ? -divquo : divquo;
+
+		printf("TxPower is %d qdbm, %d.%d dbm, %d mW  Override is %s\n",
+		       temp_val, divquo, divrem,
+		       (temp_val < 4) ? 0 : wl_qdbm_to_mw(temp_val),
+		       override ? "On" : "Off");
+		return 0;
+	} else {
+		/* for set */
+		bool unit_set = FALSE;
+		unit = UNIT_DBM;	/* default units */
+
+		/* override can be used in combo with any unit */
+		if (!strcmp(*argv, "-o")) {
+				override = TRUE;
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+		}
+
+		if (!strcmp(*argv, "-d")) {
+				unit = UNIT_DBM;
+				unit_set = TRUE;
+			argv++;
+		}
+		else if (!strcmp(*argv, "-q")) {
+				unit = UNIT_QDBM;
+				unit_set = TRUE;
+			argv++;
+		}
+		else if (!strcmp(*argv, "-m")) {
+				unit = UNIT_MW;
+				unit_set = TRUE;
+			argv++;
+		}
+
+		/* override can be used in combo with any unit */
+		if (!strcmp(*argv, "-o")) {
+			override = TRUE;
+			argv++;
+		}
+
+		if (!*argv)
+			return BCME_USAGE_ERROR;
+
+		val = atoi(*argv);
+
+		if (!unit_set) {
+			if (val == -1) {
+				val = WLC_TXPWR_MAX;		/* Max val of 127 qdbm */
+					unit = UNIT_QDBM;
+			} else if (val <= 0) {
+				return BCME_BADARG;
+			}
+		}
+
+		if ((val <= 0) && (unit == UNIT_MW)) {
+			return BCME_BADARG;
+		}
+
+		switch (unit) {
+		case UNIT_MW:
+			new_val = (uint8)wl_mw_to_qdbm((uint16)MIN(val, 0xffff));
+			break;
+		case UNIT_DBM:
+			if (val > (WLC_TXPWR_MAX / WLC_TXPWR_DB_FACTOR))
+				return BCME_BADARG;
+			val *= WLC_TXPWR_DB_FACTOR;
+			if (val < WL_RATE_DISABLED)
+				val = WL_RATE_DISABLED;
+			temp_val = (int8)val;
+			new_val = (uint8)temp_val; /* need to keep sign bit in low byte */
+			break;
+		case UNIT_QDBM:
+			if (val > WLC_TXPWR_MAX)
+				return BCME_BADARG;
+			if (val < WL_RATE_DISABLED)
+				val = WL_RATE_DISABLED;
+			temp_val = val;
+			new_val = (uint8)temp_val; /* need to keep sign bit in low byte */
+			break;
+		}
+
+		if (override)
+			new_val |= WL_TXPWR_OVERRIDE;
+
+		return wlu_iovar_setint(wl, name, new_val);
+	}
+}
+
+
+static int
+wl_txpwr(void *wl, cmd_t *cmd, char **argv)
+{
+	int error;
+	uint32 val;
+	char *endptr = NULL;
+	uint32 override;
+	const char *name = "qtxpower";
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv) {
+		if ((error = wlu_iovar_getint(wl, name, (int *)&val)) < 0)
+			return error;
+
+		/* Report power in mw with WL_TXPWR_OVERRIDE
+		 * bit indicating the status
+		 */
+		override = ((val & WL_TXPWR_OVERRIDE) != 0);
+		val &= ~WL_TXPWR_OVERRIDE;
+		printf("%d.%d dBm = %d mw.  %s\n", DIV_QUO(val, 4), DIV_REM(val, 4),
+			wl_qdbm_to_mw((uint8)(MIN(val, 0xff))), (override ? "(Override ON)" : ""));
+		return 0;
+	} else {
+		if (!strcmp(*argv, "-u")) {
+			override = 0;
+			argv++;
+		} else
+			override = WL_TXPWR_OVERRIDE;
+
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			/* not all the value string was parsed by strtol */
+			return BCME_USAGE_ERROR;
+		}
+
+		val = wl_mw_to_qdbm((uint16)MIN(val, 0xffff));
+
+		/* wl command input power will override current power set if told so */
+		val |= override;
+
+		return wlu_iovar_setint(wl, name, val);
+	}
+}
+
+static int
+wl_get_txpwr_limit(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	uint8 val_qdbm;
+	uint16 val_mw;
+	tx_power_legacy_t power;
+
+	UNUSED_PARAMETER(argv);
+
+	ret = wlu_get(wl, cmd->get, &power, sizeof(power));
+	if (ret < 0)
+		return ret;
+
+	val_qdbm = MIN(power.txpwr_band_max[0], power.txpwr_local_max);
+	val_mw = wl_qdbm_to_mw((uint8)(MIN(val_qdbm, 0xff)));
+
+	printf("%d mW (%d.%d dBm)\n", val_mw, DIV_QUO(val_qdbm, 4), DIV_REM(val_qdbm, 4));
+
+	return ret;
+}
+
+int
+wl_maclist(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct maclist *maclist = (struct maclist *) buf;
+	struct ether_addr *ea;
+	uint i, max = (WLC_IOCTL_MEDLEN - sizeof(int)) / ETHER_ADDR_LEN;
+	uint len;
+	struct ether_addr tmp_ea;
+	bool found;
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		maclist->count = htod32(max);
+		if ((ret = wlu_get(wl, cmd->get, maclist, WLC_IOCTL_MEDLEN)) < 0)
+			return ret;
+		maclist->count = dtoh32(maclist->count);
+		for (i = 0, ea = maclist->ea; i < maclist->count && i < max; i++, ea++)
+			printf("%s %s\n", cmd->name, wl_ether_etoa(ea));
+		return 0;
+	} else {
+		if (cmd->set < 0)
+			return -1;
+		/* Clear list */
+		maclist->count = htod32(0);
+		if (!strncmp(*argv, "none", strlen("none")) ||
+			!strncmp(*argv, "clear", strlen("clear")))
+			return wlu_set(wl, cmd->set, maclist, sizeof(int));
+		/* Get old list */
+		maclist->count = htod32(max);
+		if ((ret = wlu_get(wl, cmd->get, maclist, WLC_IOCTL_MEDLEN)) < 0)
+			return ret;
+		/* Append to old list */
+		maclist->count = dtoh32(maclist->count);
+		if (!strncmp(*argv, "del", strlen("del"))) {
+			argv++;
+			ea = &tmp_ea;
+			while (*argv && maclist->count < max) {
+
+				if (!wl_ether_atoe(*argv, ea)) {
+					printf("Problem parsing MAC address \"%s\".\n", *argv);
+					return -1;
+				}
+				found = FALSE;
+				for (i = 0; i < maclist->count; i++) {
+					if (!memcmp(&maclist->ea[i], ea, ETHER_ADDR_LEN)) {
+						memcpy(&maclist->ea[i],
+						&maclist->ea[maclist->count-1], ETHER_ADDR_LEN);
+						maclist->count--;
+						found = TRUE;
+					}
+				}
+				if (!found)
+					printf("WARNING: cannot find any matched entry"
+					"for deleting %s\n", wl_ether_etoa(ea));
+			argv++;
+			}
+		} else {
+			ea = &maclist->ea[maclist->count];
+			while (*argv && maclist->count < max) {
+				if (!wl_ether_atoe(*argv, ea)) {
+					printf("Problem parsing MAC address \"%s\".\n", *argv);
+					return BCME_USAGE_ERROR;
+				}
+				maclist->count++;
+				ea++;
+				argv++;
+			}
+		}
+		/* Set new list */
+		len = sizeof(maclist->count) + maclist->count * sizeof(maclist->ea);
+		maclist->count = htod32(maclist->count);
+		return wlu_set(wl, cmd->set, maclist, len);
+	}
+}
+
+#define	IOCTLECHO_MAX_SIZE	1000
+
+#if IOCTLECHO_MAX_SIZE + 2 > WLC_IOCTL_MAXLEN
+#error INVALID IOCTLECHO_MAX_SIZE
+#endif
+
+#ifndef ATE_BUILD
+static int
+wl_echo(void *wl, cmd_t *cmd, char **argv)
+{
+char *endptr;
+uint len = 0;
+uint  i;
+int	ret;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (argv[1])
+		len = strtoul(argv[1], &endptr, 0);
+
+	if (len > IOCTLECHO_MAX_SIZE) {
+		printf("maximum allowed size is : %d\n", IOCTLECHO_MAX_SIZE);
+		len = IOCTLECHO_MAX_SIZE;
+	}
+
+	memset(buf, 0, len+2);
+
+	for (i = 0; i < len; i++)
+		buf[2+i] = (char)i;
+
+	((ushort*)buf)[0] = len;
+
+	if ((ret = wlu_get(wl, WLC_ECHO, buf, len+2)) < 0)
+		return ret;
+
+	if (((ushort*)buf)[0] != len)	{
+		printf("error read size is different then write size\n");
+		return -1;
+	}
+
+	for (i = 0; i < ((ushort*)buf)[0]; i++)
+		if (buf[2+i] != (char)i) {
+			printf("error read data is different then write data\n");
+			return -1;
+		}
+
+	printf("write buffer and read buffer are identical\n");
+
+	return 0;
+
+}
+#endif /* !ATE_BUILD */
+
+static int
+wl_out(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	return wlu_set(wl, WLC_OUT, NULL, 0);
+}
+
+static int
+wl_band(void *wl, cmd_t *cmd, char **argv)
+{
+	uint band;
+	int error;
+
+	UNUSED_PARAMETER(cmd);
+
+	error = 0;
+
+	argv++;
+
+	if (*argv == NULL) {	/* get current band */
+		if ((error = wlu_get(wl, WLC_GET_BAND, &band, sizeof(uint))) < 0)
+			return (error);
+		band = dtoh32(band);
+
+		if (band == WLC_BAND_AUTO)
+			printf("auto\n");
+		else if (band == WLC_BAND_5G)
+			printf("a\n");
+		else if (band == WLC_BAND_2G)
+			printf("b\n");
+		else {
+			printf("unrecognized band value %d\n", band);
+			error = BCME_ERROR;
+		}
+	} else {		/* set the band */
+		if (!stricmp(*argv, "auto"))
+			band = WLC_BAND_AUTO;
+		else if (!stricmp(*argv, "a"))
+			band = WLC_BAND_5G;
+		else if (!stricmp(*argv, "b"))
+			band = WLC_BAND_2G;
+		else {
+			printf("unsupported band: %s\n", *argv);
+			return BCME_UNSUPPORTED;
+		}
+
+		band = htod32(band);
+		error = wlu_set(wl, WLC_SET_BAND, &band, sizeof(uint));
+
+	}
+	return (error);
+}
+
+static int
+wl_bandlist(void *wl, cmd_t *cmd, char **argv)
+{
+	uint list[3];
+	int error;
+	uint i;
+
+	UNUSED_PARAMETER(cmd);
+
+	error = 0;
+
+	argv++;
+
+	if ((error = wlu_get(wl, WLC_GET_BANDLIST, list, sizeof(list))) < 0)
+		return (error);
+	list[0] = dtoh32(list[0]);
+	list[1] = dtoh32(list[1]);
+	list[2] = dtoh32(list[2]);
+
+	/* list[0] is count, followed by 'count' bands */
+
+	if (list[0] > 2)
+		list[0] = 2;
+
+	for (i = 1; i <= list[0]; i++)
+		if (list[i] == WLC_BAND_5G)
+			printf("a ");
+		else if (list[i] == WLC_BAND_2G)
+			printf("b ");
+		else
+			printf("? ");
+	printf("\n");
+
+	return (0);
+}
+
+static int
+wl_phylist(void *wl, cmd_t *cmd, char **argv)
+{
+	char phylist_buf[128];
+	int error;
+	char *cp;
+
+	UNUSED_PARAMETER(cmd);
+
+	error = 0;
+
+	argv++;
+
+	if ((error = wlu_get(wl, WLC_GET_PHYLIST, phylist_buf, sizeof(phylist_buf))) < 0)
+		return (error);
+
+	cp = phylist_buf;
+
+	for (; *cp; cp++)
+		printf("%c ", *cp);
+	printf("\n");
+
+	return (0);
+}
+
+#ifdef linux
+#define UPGRADE_BUFSIZE	512 /* upgrade buffer size */
+#else
+#define UPGRADE_BUFSIZE	1024 /* upgrade buffer size */
+#endif /* linux */
+
+static int
+wl_upgrade(void *wl, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return (-1);
+#elif	defined(DONGLEBUILD)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return 0;
+#else
+	FILE *fp;
+	int ret = 0;
+	struct {
+		uint32 offset;
+		char buf[UPGRADE_BUFSIZE];
+	} block;
+	uint32 offset;
+	uint len;
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	if (!(fp = fopen(*argv, "rb"))) {
+		fprintf(stderr, "%s: No such file or directory\n", *argv);
+		return BCME_BADARG;
+	}
+
+	printf("Programming %s...", *argv);
+	fflush(stdout);
+	offset = 0;
+	block.offset = htod32(offset);
+	while ((len = fread(block.buf, 1, sizeof(block.buf), fp))) {
+		if ((ret = wlu_set(wl, cmd->set, &block, 4 + len)) < 0)
+			break;
+		offset += len;
+		block.offset = htod32(offset);
+		printf(".");
+		fflush(stdout);
+	}
+
+	if (ferror(fp)) {
+		ret = ferror(fp);
+		printf("\nerror reading %s\n", *argv);
+	} else {
+		long status = WLC_UPGRADE_PENDING;
+		int retries;
+
+		printf("\nCommitting image to flash...\n");
+		while (status == WLC_UPGRADE_PENDING) {
+			retries = 10;
+retry:
+			if ((ret = wlu_get(wl, WLC_UPGRADE_STATUS,
+				&status, sizeof(status))) < 0) {
+				/* the first attempt to get status will
+				 * likely fail due to dev reset
+				 */
+				if (retries--)
+					goto retry;
+				break;
+			}
+			status = dtoh32(status);
+		}
+		if (status == WLC_UPGRADE_SUCCESS)
+			printf("\nDone\n\nSuccessfully downloaded %d bytes\n", block.offset);
+		else
+			fprintf(stderr, "\n*** UPGRADE FAILED! *** (status %ld)\n", status);
+	}
+
+	fclose(fp);
+	return ret;
+#endif   /* BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+wl_get_pktcnt(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	get_pktcnt_t pktcnt;
+
+	UNUSED_PARAMETER(argv);
+
+	memset(&pktcnt, 0, sizeof(pktcnt));
+	if ((ret = wlu_get(wl, cmd->get, &pktcnt, sizeof(pktcnt))) < 0)
+		return ret;
+
+	printf("Receive: good packet %d, bad packet %d, othercast good packet %d\n",
+		dtoh32(pktcnt.rx_good_pkt), dtoh32(pktcnt.rx_bad_pkt),
+		dtoh32(pktcnt.rx_ocast_good_pkt));
+	printf("Transmit: good packet %d, bad packet %d\n",
+		dtoh32(pktcnt.tx_good_pkt), dtoh32(pktcnt.tx_bad_pkt));
+
+	return ret;
+}
+
+static cntry_name_t *
+wlc_cntry_name_to_country(char *long_name)
+{
+	cntry_name_t *cntry;
+	for (cntry = cntry_names; cntry->name &&
+		stricmp(long_name, cntry->name); cntry++);
+	return (!cntry->name ? NULL : cntry);
+}
+
+static cntry_name_t *
+wlc_cntry_abbrev_to_country(const char *abbrev)
+{
+	cntry_name_t *cntry;
+	if (!*abbrev || strlen(abbrev) > 3 || strlen(abbrev) < 2)
+		return (NULL);
+	for (cntry = cntry_names; cntry->name &&
+		strnicmp(abbrev, cntry->abbrev, strlen(abbrev)); cntry++);
+	return (!cntry->name ? NULL : cntry);
+}
+
+static int
+wl_parse_country_spec(const char *spec, char *ccode, int *regrev)
+{
+	char *revstr;
+	char *endptr = NULL;
+	int ccode_len;
+	int rev = -1;
+
+	revstr = strchr(spec, '/');
+
+	if (revstr) {
+		rev = strtol(revstr + 1, &endptr, 10);
+		if (*endptr != '\0') {
+			/* not all the value string was parsed by strtol */
+			fprintf(stderr,
+				"Could not parse \"%s\" as a regulatory revision "
+				"in the country string \"%s\"\n",
+				revstr + 1, spec);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	if (revstr)
+		ccode_len = (int)(uintptr)(revstr - spec);
+	else
+		ccode_len = (int)strlen(spec);
+
+	if (ccode_len > 3) {
+		fprintf(stderr,
+			"Could not parse a 2-3 char country code "
+			"in the country string \"%s\"\n",
+			spec);
+		return BCME_USAGE_ERROR;
+	}
+
+	memcpy(ccode, spec, ccode_len);
+	ccode[ccode_len] = '\0';
+	*regrev = rev;
+
+	return 0;
+}
+
+int
+wl_country(void *wl, cmd_t *cmd, char **argv)
+{
+	cntry_name_t *cntry;
+	wl_country_t cspec = {{0}, 0, {0}};
+	int argc = 0;
+	int err;
+	int bcmerr = 1;
+	int interr = 1;
+
+	/* skip the command name */
+	argv++;
+
+	/* find the arg count */
+	while (argv[argc])
+		argc++;
+
+	/* check arg list count */
+	if (argc > 2) {
+		fprintf(stderr, "Too many arguments (%d) for command %s\n", argc, cmd->name);
+		return BCME_USAGE_ERROR;
+	}
+
+	buf[0] = 0;
+	if (argc == 0) {
+		const char* name = "<unknown>";
+
+		/* first try the country iovar */
+		err = wlu_iovar_get(wl, "country", &cspec, sizeof(cspec));
+
+		if (!err) {
+			cntry = wlc_cntry_abbrev_to_country(cspec.country_abbrev);
+			if (cntry)
+				name = cntry->name;
+			cspec.rev = dtoh32(cspec.rev);
+
+			printf("%s (%s/%d) %s\n",
+			       cspec.country_abbrev, cspec.ccode, cspec.rev, name);
+
+			return 0;
+		}
+
+		/* if there was an error other than BCME_UNSUPPORTED, fail now */
+		interr = wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+		if (!interr && (bcmerr != BCME_UNSUPPORTED))
+			return err;
+
+		/* if the "country" iovar is unsupported, try the WLC_SET_COUNTRY ioctl */
+		if ((err = wlu_get(wl, cmd->get, &buf[0], WLC_IOCTL_SMLEN)) < 0)
+			return err;
+		if (strlen(buf) == 0) {
+			printf("No country set\n");
+			return 0;
+
+		}
+		cntry = wlc_cntry_abbrev_to_country(buf);
+		if (cntry != NULL)
+			name = cntry->name;
+
+		printf("%s () %s\n", buf, name);
+		return 0;
+	}
+
+	if (!stricmp(*argv, "list")) {
+		uint i;
+		const char* abbrev;
+		wl_country_list_t *cl = (wl_country_list_t *)buf;
+
+		cl->buflen = WLC_IOCTL_MAXLEN;
+		cl->count = 0;
+
+		/* band may follow */
+		if (*++argv) {
+			cl->band_set = TRUE;
+			if (!stricmp(*argv, "a"))
+				cl->band = WLC_BAND_5G;
+			else if (!stricmp(*argv, "b") || !stricmp(*argv, "g"))
+				cl->band = WLC_BAND_2G;
+			else {
+				printf("unsupported band: %s\n", *argv);
+				return BCME_UNSUPPORTED;
+			}
+		} else {
+			cl->band_set = FALSE;
+		}
+
+		cl->buflen = htod32(cl->buflen);
+		cl->band_set = htod32(cl->band_set);
+		cl->band = htod32(cl->band);
+		cl->count = htod32(cl->count);
+		err = wlu_get(wl, WLC_GET_COUNTRY_LIST, buf, WLC_IOCTL_MAXLEN);
+		if (err < 0)
+			return err;
+
+		printf("Supported countries: country code and long name\n");
+		for (i = 0; i < dtoh32(cl->count); i++) {
+			abbrev = &cl->country_abbrev[i*WLC_CNTRY_BUF_SZ];
+			cntry = wlc_cntry_abbrev_to_country(abbrev);
+			printf("%s\t%s\n", abbrev, cntry ? cntry->name : "");
+		}
+		return 0;
+	}
+
+	memset(&cspec, 0, sizeof(cspec));
+	cspec.rev = -1;
+
+	if (argc == 1) {
+		/* check for the first arg being a country name, e.g. "United States",
+		 * or country spec, "US/1", or just a country code, "US"
+		 */
+		if ((cntry = wlc_cntry_name_to_country(argv[0])) != NULL) {
+			/* arg matched a country name */
+			memcpy(cspec.country_abbrev, cntry->abbrev, WLC_CNTRY_BUF_SZ);
+			err = 0;
+		} else {
+			/* parse a country spec, e.g. "US/1", or a country code.
+			 * cspec.rev will be -1 if not specified.
+			 */
+			err = wl_parse_country_spec(argv[0], cspec.country_abbrev, &cspec.rev);
+		}
+
+		if (err) {
+			fprintf(stderr,
+				"Argument \"%s\" could not be parsed as a country name, "
+				"country code, or country code and regulatory revision.\n",
+				argv[0]);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* if the arg was a country spec, then fill out ccdoe and rev,
+		 * and leave country_abbrev defaulted to the ccode
+		 */
+		if (cspec.rev != -1)
+			memcpy(cspec.ccode, cspec.country_abbrev, WLC_CNTRY_BUF_SZ);
+	} else {
+		/* for two args, the first needs to be a country code or country spec */
+		err = wl_parse_country_spec(argv[0], cspec.ccode, &cspec.rev);
+		if (err) {
+			fprintf(stderr,
+				"Argument 1 \"%s\" could not be parsed as a country code, or "
+				"country code and regulatory revision.\n",
+				argv[0]);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* the second arg needs to be a country name or country code */
+		if ((cntry = wlc_cntry_name_to_country(argv[1])) != NULL) {
+			/* arg matched a country name */
+			memcpy(cspec.country_abbrev, cntry->abbrev, WLC_CNTRY_BUF_SZ);
+		} else {
+			int rev;
+			err = wl_parse_country_spec(argv[1], cspec.country_abbrev, &rev);
+			if (rev != -1) {
+				fprintf(stderr,
+					"Argument \"%s\" had a revision. Arg 2 must be "
+					"a country name or country code without a revision\n",
+					argv[1]);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		if (err) {
+			fprintf(stderr,
+				"Argument 2 \"%s\" could not be parsed as "
+				"a country name or country code\n",
+				argv[1]);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	/* first try the country iovar */
+	if (cspec.rev == -1 && cspec.ccode[0] == '\0')
+		err = wlu_iovar_set(wl, "country", &cspec, WLC_CNTRY_BUF_SZ);
+	else {
+		cspec.rev = htod32(cspec.rev);
+		err = wlu_iovar_set(wl, "country", &cspec, sizeof(cspec));
+	}
+
+	if (err == 0)
+		return 0;
+
+	/* if there was an error other than BCME_UNSUPPORTED, fail now */
+	interr = wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+	if (!interr && (bcmerr != BCME_UNSUPPORTED))
+		return err;
+
+	/* if the "country" iovar is unsupported, try the WLC_SET_COUNTRY ioctl if possible */
+
+	if (cspec.rev != -1 || cspec.ccode[0] != '\0') {
+		fprintf(stderr,
+			"Driver does not support full country spec interface, "
+			"only a country name or code may be sepcified\n");
+		return err;
+	}
+
+	/* use the legacy ioctl */
+	err = wlu_set(wl, WLC_SET_COUNTRY, cspec.country_abbrev, WLC_CNTRY_BUF_SZ);
+
+	return err;
+}
+
+int
+wl_country_ie_override(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc = 0;
+	int error, i;
+
+	/* skip the command name */
+	argv++;
+
+	/* find the arg count */
+	while (argv[argc])
+		argc++;
+
+	if (argc == 0) {
+		void *ptr;
+		bcm_tlv_t *ie;
+
+		if ((error = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return (error);
+
+		ie = (bcm_tlv_t *)ptr;
+
+		printf("ie tag:0x%x ie len:0x%x ie data:", ie->id, ie->len);
+
+		for (i = 0; i < ie->len; i++)
+			printf("0x%x ", ie->data[i]);
+
+		printf("\n");
+
+		return error;
+
+	} else {
+		/* Set */
+		char *endptr = NULL;
+		uchar *valsp;
+		int8 ie_len, pad = 0;
+
+		/* retrieve the ie len in advance to check for padding */
+		ie_len = (int8)strtol(*(argv + 1), NULL, 0);
+		if (ie_len & 1) {
+			fprintf(stderr, "country ie len is odd(%d), padding by 1 octet\n", ie_len);
+			pad = 1;
+		}
+
+		valsp = (uchar*)malloc(argc + pad);
+		if (valsp == NULL) {
+			fprintf(stderr, "Error allocating %d bytes country ie\n", argc);
+			return BCME_NOMEM;
+		}
+		memset(valsp, 0, argc + pad);
+
+		for (i = 0; i < argc; i++, argv++) {
+
+			valsp[i] = (uchar)strtol(*argv, &endptr, 0);
+
+			/* make sure all the value string was parsed by strtol */
+			if (*endptr != '\0') {
+				free(valsp);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		/* update ie len if padded */
+		if (pad) {
+			valsp[1] += 1;
+			valsp[ie_len + TLV_HDR_LEN] = 0;
+		}
+
+		error = wlu_var_setbuf(wl, cmd->name, valsp, argc + pad);
+
+		free(valsp);
+
+		return error;
+	}
+}
+
+static int
+wl_actframe(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_action_frame_t * action_frame;
+	wl_af_params_t * af_params;
+	struct ether_addr ea;
+	int argc;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1] || !argv[2]) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if ((af_params = (wl_af_params_t *) malloc(WL_WIFI_AF_PARAMS_SIZE)) == NULL) {
+		printf("wl_actframe: unable to allocate frame \n");
+		return BCME_NOMEM;
+	}
+	af_params->channel = 0;
+	af_params->dwell_time = -1;
+	action_frame = &af_params->action_frame;
+
+	/* Add the packet Id */
+	action_frame->packetId = (uint32)(uintptr)action_frame;
+
+	/* convert the ea string into an ea struct */
+	if (!wl_ether_atoe(argv[1], &ea)) {
+		free(af_params);
+		printf(" ERROR: no valid ether addr provided\n");
+		return BCME_USAGE_ERROR;
+	}
+	memcpy(&action_frame->da, (char*)&ea, ETHER_ADDR_LEN);
+	/* set default BSSID */
+	memcpy(&af_params->BSSID, (char*)&ea, ETHER_ADDR_LEN);
+
+	/* add the length */
+	if (argv[2]) {
+		action_frame->len  = htod16(strlen(argv[2])) / 2;
+	}
+
+	/* add the channel */
+	if (argc > 3 && argv[3]) {
+		af_params->channel = htod32(atoi(argv[3]));
+	}
+
+	/* add the dwell_time */
+	if (argc > 4 && argv[4]) {
+		af_params->dwell_time = htod32(atoi(argv[4]));
+	}
+
+	/* add the BSSID */
+	if (argc > 5 && argv[5]) {
+		if (!wl_ether_atoe(argv[5], &ea)) {
+			free(af_params);
+			printf(" ERROR: no valid ether addr provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		memcpy(&af_params->BSSID, (char*)&ea, ETHER_ADDR_LEN);
+	}
+
+	if ((err = get_ie_data ((uchar *)argv[2],
+		&action_frame->data[0],
+		action_frame->len))) {
+		free(af_params);
+		fprintf(stderr, "Error parsing data arg\n");
+		return err;
+	}
+	err = wlu_var_setbuf(wl, "actframe", af_params, WL_WIFI_AF_PARAMS_SIZE);
+
+	free(af_params);
+
+	return (err);
+
+}
+
+static int
+wl_dfs_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+
+	void *ptr;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return ret;
+
+	ret = wl_print_dfs_status(ptr);
+
+	return ret;
+}
+
+static int
+wl_print_dfs_status(wl_dfs_status_t *dfs_status)
+{
+	char chanspec_str[CHANSPEC_STR_LEN];
+
+	dfs_status->state = dtoh32(dfs_status->state);
+	dfs_status->duration = dtoh32(dfs_status->duration);
+	dfs_status->chanspec_cleared = wl_chspec_from_driver(dfs_status->chanspec_cleared);
+
+	if (dfs_status->state >= WL_DFS_CACSTATES) {
+		printf("Unknown dfs state %d.\n", dfs_status->state);
+		return -1;
+	}
+
+	printf("state %s time elapsed %dms radar channel cleared by dfs ",
+		dfs_cacstate_str[dfs_status->state], dfs_status->duration);
+
+	if (dfs_status->chanspec_cleared) {
+		printf("channel %s (0x%04X)\n",
+		       wf_chspec_ntoa(dfs_status->chanspec_cleared, chanspec_str),
+		       dfs_status->chanspec_cleared);
+	}
+	else {
+		printf("none\n");
+	}
+	return 0;
+}
+
+static int
+wl_dfs_status_all(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+
+	void *ptr;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return ret;
+
+	ret = wl_print_dfs_status_all(ptr);
+
+	return ret;
+}
+
+/* prints dfs status from one subset */
+static int
+wl_print_dfs_sub_status(wl_dfs_sub_status_t *sub)
+{
+	char chanspec_str[CHANSPEC_STR_LEN];
+
+	sub->state = dtoh32(sub->state);
+	sub->duration = dtoh32(sub->duration);
+	sub->chanspec = wl_chspec_from_driver(sub->chanspec);
+	sub->chanspec_last_cleared = wl_chspec_from_driver(sub->chanspec_last_cleared);
+	sub->sub_type = dtoh16(sub->sub_type);
+
+	// state
+	if (sub->state >= WL_DFS_CACSTATES) {
+		printf("Unknown dfs state %d.\n", sub->state);
+		return -1;
+	}
+	printf("state: %s, time elapsed: %dms, chanspec: ",
+			dfs_cacstate_str[sub->state], sub->duration);
+	// chanspec
+	if (sub->chanspec) {
+		printf("%s (0x%04X), chanspec last cleared: ",
+				wf_chspec_ntoa(sub->chanspec, chanspec_str),
+				sub->chanspec);
+	} else {
+		printf("none, chanspec last cleared: ");
+	}
+	// chanspec last cleared
+	if (sub->chanspec_last_cleared) {
+		printf("%s (0x%04X), ",
+				wf_chspec_ntoa(sub->chanspec_last_cleared, chanspec_str),
+				sub->chanspec_last_cleared);
+	} else {
+		printf("none, ");
+	}
+	// sub type
+	printf("sub type: 0x%02x\n", sub->sub_type);
+
+	return 0;
+}
+
+/* prints dfs status of all subsets received */
+static int
+wl_print_dfs_status_all(wl_dfs_status_all_t *dfs_status_all)
+{
+	int count;
+	int err;
+	if (dfs_status_all == NULL) {
+		return BCME_ERROR;
+	}
+
+	dfs_status_all->version = dtoh32(dfs_status_all->version);
+	dfs_status_all->num_sub_status = dtoh32(dfs_status_all->num_sub_status);
+
+	if (dfs_status_all->version != WL_DFS_STATUS_ALL_VERSION) {
+		err = BCME_UNSUPPORTED;
+		printf("err=%d version=%d\n", err, dfs_status_all->version);
+		return err;
+	}
+
+	printf("version: %d, num_sub_status: %d\n",
+			dfs_status_all->version, dfs_status_all->num_sub_status);
+
+	for (count = 0; count < dfs_status_all->num_sub_status; ++count) {
+		printf("@%d: ", count);
+		if ((err = wl_print_dfs_sub_status(&dfs_status_all->dfs_sub_status[count]))
+				!= BCME_OK) {
+			return err;
+		}
+	}
+
+	return BCME_OK;
+}
+
+static int
+wl_radar_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	uint i;
+	wl_radar_status_t ra;
+	char chanspec_str[CHANSPEC_STR_LEN];
+	static const struct {
+		uint32 radar_type;
+		const char *radar_type_name;
+	} radar_names[] = {
+		{0, "NONE"},
+		{1, "ETSI_1"},
+		{2, "ETSI_2"},
+		{3, "ETSI_3"},
+		{4, "ETSI_4"},
+		{5, "S2"},
+		{6, "S3"},
+		{7, "UNCLASSIFIED"},
+		{8, "FCC-5"},
+		{9, "JP1-2/JP2-3"},
+		{10, "JP2-1"},
+		{11, "JP4"},
+		{12, "FCC_1"},
+	};
+
+	char radar_type_str[24];
+
+	UNUSED_PARAMETER(argv);
+	if ((ret = wlu_iovar_get(wl, cmd->name, &ra, sizeof(ra))) < 0)
+		return ret;
+	ra.ch = wl_chspec_from_driver(ra.ch);
+
+	if (ra.detected == FALSE) {
+		printf("NO RADAR DETECTED \n");
+	} else {
+		  for (i = 0; i < ARRAYSIZE(radar_names); i++) {
+			if (radar_names[i].radar_type == ra.radartype)
+				snprintf(radar_type_str, sizeof(radar_type_str),
+					"%s", radar_names[i].radar_type_name);
+		}
+
+		  if (ra.pretended == TRUE) {
+		    printf("DFS: NONE ########## RADAR DETECTED  ON CHAN  %s \n",
+		    wf_chspec_ntoa(ra.ch, chanspec_str));
+		  } else {
+		    if (ra.radartype == 8) {
+		      printf("DFS: FCC-5 ########## RADAR DETECTED  ON CHAN %s \n",
+		      wf_chspec_ntoa(ra.ch, chanspec_str));
+		      printf(" ########## lp_csect_single = %d, Time from last detection = %u, ",
+		      ra.lp_csect_single, ra.timefromL);
+		      printf(" = %dmin %dsec AT %dMS \n ",
+		      ra.timefromL/60, ra.timefromL%60, ra.timenow);
+		    } else {
+		      printf("DFS: %s ########## RADAR DETECTED  ON CHAN %s \n",
+		      radar_type_str, wf_chspec_ntoa(ra.ch, chanspec_str));
+		      printf(" ########## detected_pulse_index= %d, nconseq_pulses = %d, ",
+		      ra.detected_pulse_index, ra.nconsecq_pulses);
+		      printf(" Time from last detection = %u, = %dmin %dsec AT %dMS \n",
+		      ra.timefromL, ra.timefromL/60, ra.timefromL%60, ra.timenow);
+		      printf("Pruned Intv: ");
+		      for (i = 0; i < 10; i++) {
+			printf("%d-%d ", ra.intv[i], i);
+		      }
+		      printf("\n");
+
+		      printf("Pruned PW:  ");
+		      for (i = 0; i < 10; i++) {
+			printf("%i-%d ", ra.pw[i], i);
+		      }
+		      printf("\n");
+
+		      printf("Pruned FM:  ");
+		      for (i = 0; i < 10; i++) {
+			printf("%i-%d ", ra.fm[i], i);
+		      }
+		      printf("\n");
+		    }
+		  }
+	}
+		return ret;
+}
+
+static int
+wl_radar_sc_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	uint i;
+	wl_radar_status_t ra;
+	static const struct {
+		uint32 radar_type;
+		const char *radar_type_name;
+	} radar_names[] = {
+		{0, "NONE"},
+		{1, "ETSI_1"},
+		{2, "ETSI_2"},
+		{3, "ETSI_3"},
+		{4, "ETSI_4"},
+		{5, "S2"},
+		{6, "S3"},
+		{7, "UNCLASSIFIED"},
+		{8, "FCC-5"},
+		{9, "JP1-2/JP2-3"},
+		{10, "JP2-1"},
+		{11, "JP4"},
+		{12, "FCC_1"},
+	};
+
+	char radar_type_str[24];
+
+	/* Skip the command name */
+	argv++;
+
+	if (*argv == NULL) {
+		if ((ret = wlu_iovar_get(wl, cmd->name, &ra, sizeof(ra))) < 0)
+			return ret;
+
+		if (ra.detected == FALSE) {
+			printf("NO RADAR_SC DETECTED \n");
+		} else {
+			  for (i = 0; i < ARRAYSIZE(radar_names); i++) {
+				if (radar_names[i].radar_type == ra.radartype)
+					snprintf(radar_type_str, sizeof(radar_type_str),
+						"%s", radar_names[i].radar_type_name);
+			}
+
+			  if (ra.pretended == TRUE) {
+			    printf("DFS: NONE ########## RADAR_SC DETECTED  ON SC CHAN \n");
+			  } else {
+			    if (ra.radartype == 8) {
+			      printf("DFS: FCC-5 ########## RADAR_SC DETECTED  ON SC CHAN \n");
+			      printf(" ########## lp_csect_single");
+					printf("= %d, Time from last detection = %u, ",
+						ra.lp_csect_single, ra.timefromL);
+			      printf(" = %dmin %dsec AT %dMS \n ",
+			      ra.timefromL/60, ra.timefromL%60, ra.timenow);
+			    } else {
+			      printf("DFS: %s ########## RADAR_SC DETECTED  ON SC CHAN \n",
+			      radar_type_str);
+			      printf(" ########## detected_pulse_index= %d, nconseq_pulses = %d, ",
+			      ra.detected_pulse_index, ra.nconsecq_pulses);
+			      printf(" Time from last detection = %u, = %dmin %dsec AT %dMS \n",
+			      ra.timefromL, ra.timefromL/60, ra.timefromL%60, ra.timenow);
+			      printf("Pruned Intv: ");
+			      for (i = 0; i < 10; i++) {
+				printf("%d-%d ", ra.intv[i], i);
+			      }
+			      printf("\n");
+
+			      printf("Pruned PW:  ");
+			      for (i = 0; i < 10; i++) {
+				printf("%i-%d ", ra.pw[i], i);
+			      }
+			      printf("\n");
+
+			      printf("Pruned FM:  ");
+			      for (i = 0; i < 10; i++) {
+				printf("%i-%d ", ra.fm[i], i);
+			      }
+			      printf("\n");
+			    }
+			  }
+		}
+
+	} else {
+		ret = atoi(*argv);
+		if (ret == 0) {
+			printf("Clear SC Radar Status \n");
+			ra.detected = FALSE;
+			return wlu_var_setbuf(wl, "clear_radar_sc_status",
+				&ra, sizeof(wl_radar_status_t));
+		}
+	}
+
+	return ret;
+}
+
+
+static int
+wl_clear_radar_status(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_radar_status_t ra;
+
+	UNUSED_PARAMETER(argv);
+	printf("Clear Radar Status \n");
+
+		ra.detected = FALSE;
+		return wlu_var_setbuf(wl, cmd->name, &ra, sizeof(wl_radar_status_t));
+}
+
+/*
+ * wlu_reg2args is a generic function that is used for setting/getting
+ * WL_IOVAR variables that require address for read, and
+ * address + data for write.
+ */
+int
+wlu_reg2args(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	uint32 int_val;
+	bool get = TRUE;
+	uint32 len;
+	void *ptr = NULL;
+	char *endptr;
+	int ret = 0;
+
+	if (argv[1]) {
+		len = sizeof(int_val);
+		int_val = htod32(strtoul(argv[1], &endptr, 0));
+		memcpy(var, (char *)&int_val, sizeof(int_val));
+	}
+	else
+		return BCME_USAGE_ERROR;
+
+	if (argv[2]) {
+		get = FALSE;
+		int_val = htod32(strtoul(argv[2], &endptr, 0));
+		memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+		len += sizeof(int_val);
+	}
+	if (get) {
+		if ((ret = wlu_var_getbuf(wl, cmd->name, var, sizeof(var), &ptr)) < 0)
+			return ret;
+
+		printf("0x%x\n", dtoh32(*(int *)ptr));
+	}
+	else
+		ret = wlu_var_setbuf(wl, cmd->name, &var, sizeof(var));
+	return ret;
+}
+
+static int
+wl_measure_req(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+	struct ether_addr ea;
+
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!stricmp(*argv, "tpc"))
+		val = WLC_MEASURE_TPC;
+	else if (!stricmp(*argv, "basic"))
+		val = WLC_MEASURE_CHANNEL_BASIC;
+	else if (!stricmp(*argv, "cca"))
+		val = WLC_MEASURE_CHANNEL_CCA;
+	else if (!stricmp(*argv, "rpi"))
+		val = WLC_MEASURE_CHANNEL_RPI;
+	else {
+		printf("error: unknown measurement type %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+	argv++;
+
+	if (!*argv) {
+		printf("error: missing target address\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!wl_ether_atoe(*argv, &ea)) {
+		printf("error: could not parse MAC address %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	val = htod32(val);
+	memcpy(&buf[0], &val, sizeof(uint32));
+	memcpy(&buf[4], ea.octet, ETHER_ADDR_LEN);
+
+	return wlu_set(wl, cmd->set, buf, sizeof(uint32) + ETHER_ADDR_LEN);
+}
+
+static int
+wl_send_quiet(void *wl, cmd_t *cmd, char **argv)
+{
+	dot11_quiet_t quiet;
+
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+	/* Order is count, duration, offset */
+	quiet.count = atoi(*argv);
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+	quiet.duration = atoi(*argv);
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+	quiet.offset = atoi(*argv);
+	quiet.period = 0;
+
+	quiet.duration = htod16(quiet.duration);
+	quiet.offset = htod16(quiet.offset);
+	return (wlu_set(wl, cmd->set, &quiet, sizeof(quiet)));
+}
+
+static int
+wl_pm_mute_tx(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pm_mute_tx_t var;
+
+	var.version = htod16(WL_PM_MUTE_TX_VER);
+	var.len = htod16(sizeof(wl_pm_mute_tx_t));
+
+	if (!*++argv) {
+		goto missing_args;
+	}
+
+	var.enable = atoi(*argv);
+
+	if (var.enable) {
+		if (!*++argv) {
+			goto missing_args;
+		}
+		var.deadline = htod16(atoi(*argv));
+	}
+
+	return (wlu_var_setbuf(wl, cmd->name, &var, var.len));
+
+missing_args:
+	return -1;
+}
+
+static int
+wl_send_csa(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_chan_switch_t csa_arg;
+
+	/* Order is mode, count channel */
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+	csa_arg.mode = atoi(*argv) ? 1 : 0;
+	if (!*++argv) {
+		printf("error: missing count\n");
+		return BCME_USAGE_ERROR;
+	}
+	csa_arg.count = atoi(*argv);
+	if (!*++argv) {
+		printf("error: missing channel\n");
+		return BCME_USAGE_ERROR;
+	}
+	csa_arg.reg = 0;
+
+	if ((csa_arg.chspec = wf_chspec_aton(*argv))) {
+		csa_arg.chspec = wl_chspec_to_driver(csa_arg.chspec);
+		if (csa_arg.chspec == INVCHANSPEC) {
+			return BCME_USAGE_ERROR;
+		}
+		/* csa action frame type */
+		if (*++argv) {
+			if (strcmp(*argv, "u") == 0)
+				csa_arg.frame_type = CSA_UNICAST_ACTION_FRAME;
+			else {
+				printf("error: invalid frame type: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+		} else
+			csa_arg.frame_type = CSA_BROADCAST_ACTION_FRAME;
+
+		err = wlu_var_setbuf(wl, cmd->name, &csa_arg, sizeof(csa_arg));
+	} else {
+		printf("Error: bad parameters \"%s\"\n", *argv);
+		return BCME_BADARG;
+	}
+
+	return err;
+}
+
+int
+wl_var_setint(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+	char *varname;
+	char *endptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*argv) {
+		printf("set: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (!*argv) {
+		printf("set: missing value argument for set of \"%s\"\n", varname);
+		return BCME_USAGE_ERROR;
+	}
+
+	val = strtoul(*argv, &endptr, 0);
+	if (*endptr != '\0') {
+		/* not all the value string was parsed by strtol */
+		printf("set: error parsing value \"%s\" as an integer for set of \"%s\"\n",
+			*argv, varname);
+		return BCME_USAGE_ERROR;
+	}
+
+	return wlu_iovar_setint(wl, varname, val);
+}
+
+int
+wl_var_get(void *wl, cmd_t *cmd, char **argv)
+{
+	char *varname;
+	char *p;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*argv) {
+		printf("get: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (*argv) {
+		printf("get: error, extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	strcpy(buf, varname);
+	p = buf;
+	while (*p != '\0') {
+		*p = tolower((int)*p);
+		p++;
+	}
+	return (wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_MAXLEN));
+}
+static int
+wl_var_getint(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int32 val;
+	char *varname;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*argv) {
+		printf("get: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if ((err = wlu_iovar_getint(wl, varname, &val)))
+		return (err);
+
+	if (val < 10)
+		printf("%d\n", val);
+	else
+		printf("%d (0x%x)\n", val, val);
+
+	return (0);
+}
+
+int
+wl_var_getandprintstr(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+
+	if ((err = wl_var_get(wl, cmd, argv)))
+		return (err);
+
+	printf("%s\n", buf);
+	return (0);
+}
+
+/* just issue a wl_var_setint() or a wl_var_getint() if there is a 2nd arg */
+int
+wl_varint(void *wl, cmd_t *cmd, char *argv[])
+{
+	if (argv[1])
+		return (wl_var_setint(wl, cmd, argv));
+	else
+		return (wl_var_getint(wl, cmd, argv));
+}
+
+int
+wlu_var_getbuf(void *wl, const char *iovar, void *param, int param_len, void **bufptr)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	*bufptr = buf;
+
+	return wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_MAXLEN);
+}
+
+/* get buffer for smaller sizes upto 256 bytes */
+int
+wlu_var_getbuf_sm(void *wl, const char *iovar, void *param, int param_len, void **bufptr)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_SMLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	*bufptr = buf;
+
+	return wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_SMLEN);
+}
+
+/* Get buffer of minimal size equal to the sizeof iovar name + param_len */
+int
+wlu_var_getbuf_minimal(void *wl, const char *iovar, void *param, int param_len, void **bufptr)
+{
+	int len;
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	memset(buf, 0, (len + param_len));
+	strcpy(buf, iovar);
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	*bufptr = buf;
+
+	return wlu_get(wl, WLC_GET_VAR, &buf[0], (len + param_len));
+}
+
+/* Get buffer for medium sizes upto 1500 bytes */
+int
+wlu_var_getbuf_med(void *wl, const char *iovar, void *param, int param_len, void **bufptr)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_MEDLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	*bufptr = buf;
+
+	return wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_MEDLEN);
+}
+
+
+int
+wlu_var_setbuf(void *wl, const char *iovar, void *param, int param_len)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	len += param_len;
+
+	return wlu_set(wl, WLC_SET_VAR, &buf[0], len);
+}
+
+int
+wlu_var_setbuf_sm(void *wl, const char *iovar, void *param, int param_len)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_SMLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	len += param_len;
+
+	return wlu_set(wl, WLC_SET_VAR, &buf[0], WLC_IOCTL_SMLEN);
+}
+
+int
+wlu_var_setbuf_med(void *wl, const char *iovar, void *param, int param_len)
+{
+	int len;
+
+	memset(buf, 0, WLC_IOCTL_MEDLEN);
+	strcpy(buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&buf[len], param, param_len);
+
+	len += param_len;
+
+	return wlu_set(wl, WLC_SET_VAR, &buf[0], WLC_IOCTL_MEDLEN);
+}
+
+int
+wl_var_void(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(argv);
+
+	if (cmd->set < 0)
+		return -1;
+
+	return wlu_var_setbuf(wl, cmd->name, NULL, 0);
+}
+
+/*
+ * format a "prefix" indexed iovar buffer
+ */
+static int
+wl_prefixiovar_mkbuf(const char *iovar, const char *prefix, int prefix_index, void *param,
+	int paramlen, void *bufptr, int buflen, int *perr)
+{
+	int8* p;
+	uint prefixlen;
+	uint namelen;
+	uint iolen;
+
+	prefixlen = strlen(prefix);	/* length of iovar prefix "bsscfg:ssid %d wlc:counter %d" */
+	namelen = strlen(iovar) + 1;	/* length of iovar name + null */
+	iolen = prefixlen + namelen + sizeof(int) + paramlen;
+
+	/* check for overflow */
+	if (buflen < 0 || iolen > (uint)buflen) {
+		*perr = BCME_BUFTOOSHORT;
+		return 0;
+	}
+
+	p = (int8*)bufptr;
+
+	/* copy prefix, no null */
+	memcpy(p, prefix, prefixlen);
+	p += prefixlen;
+
+	/* copy iovar name including null */
+	memcpy(p, iovar, namelen);
+	p += namelen;
+
+	/* send index as first param */
+	prefix_index = htod32(prefix_index);
+	memcpy(p, &prefix_index, sizeof(int32));
+	p += sizeof(int32);
+
+	/* parameter buffer follows */
+	if (paramlen)
+		memcpy(p, param, paramlen);
+
+	*perr = 0;
+	return iolen;
+}
+
+static int
+wl_bssiovar_mkbuf(const char *iovar, int bssidx, void *param,
+	int paramlen, void *bufptr, int buflen, int *perr)
+{
+	const char *prefix = "bsscfg:";
+	return wl_prefixiovar_mkbuf(iovar, prefix, bssidx,  param, paramlen, bufptr, buflen, perr);
+}
+#ifdef NOTYET
+static int
+wl_wlciovar_mkbuf(const char *iovar, int wlcidx, void *param,
+	int paramlen, void *bufptr, int buflen, int *perr)
+{
+	const char *prefix = "wlc:";
+	return wl_prefixiovar_mkbuf(iovar, prefix, wlcidx,  param, paramlen, bufptr, buflen, perr);
+}
+#endif
+/*
+ * set named & bss indexed driver iovar providing both parameter and i/o buffers
+ */
+int
+wlu_bssiovar_setbuf(void* wl, const char *iovar, int bssidx,
+	void *param, int paramlen, void *bufptr, int buflen)
+{
+	int err;
+	int iolen;
+
+	iolen = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &err);
+	if (err)
+		return err;
+
+	return wlu_set(wl, WLC_SET_VAR, bufptr, iolen);
+}
+
+/*
+ * get named & bss indexed driver iovar providing both parameter and i/o buffers
+ */
+static int
+wl_bssiovar_getbuf(void* wl, const char *iovar, int bssidx,
+	void *param, int paramlen, void *bufptr, int buflen)
+{
+	int err;
+
+	wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &err);
+	if (err)
+		return err;
+
+	return wlu_get(wl, WLC_GET_VAR, bufptr, buflen);
+}
+
+/*
+ * get named & bss indexed driver variable to buffer value
+ */
+int
+wlu_bssiovar_get(void *wl, const char *iovar, int bssidx, void *outbuf, int len)
+{
+	char smbuf[WLC_IOCTL_SMLEN];
+	int err;
+
+	/* use the return buffer if it is bigger than what we have on the stack */
+	if (len > (int)sizeof(smbuf)) {
+		err = wl_bssiovar_getbuf(wl, iovar, bssidx, NULL, 0, outbuf, len);
+	} else {
+		memset(smbuf, 0, sizeof(smbuf));
+		err = wl_bssiovar_getbuf(wl, iovar, bssidx, NULL, 0, smbuf, sizeof(smbuf));
+		if (err == 0)
+			memcpy(outbuf, smbuf, len);
+	}
+
+	return err;
+}
+
+/*
+ * set named & bss indexed driver variable to buffer value
+ */
+static int
+wl_bssiovar_set(void *wl, const char *iovar, int bssidx, void *param, int paramlen)
+{
+	char smbuf[WLC_IOCTL_SMLEN];
+
+	memset(smbuf, 0, sizeof(smbuf));
+
+	return wlu_bssiovar_setbuf(wl, iovar, bssidx, param, paramlen, smbuf, sizeof(smbuf));
+}
+
+/*
+ * get named & bsscfg indexed driver variable as an int value
+ */
+static int
+wl_bssiovar_getint(void *wl, const char *iovar, int bssidx, int *pval)
+{
+	int ret;
+
+	ret = wlu_bssiovar_get(wl, iovar, bssidx, pval, sizeof(int));
+	if (ret == 0)
+	{
+		*pval = dtoh32(*pval);
+	}
+	return ret;
+}
+
+/*
+ * set named & bsscfg indexed driver variable to int value
+ */
+static int
+wl_bssiovar_setint(void *wl, const char *iovar, int bssidx, int val)
+{
+	val = htod32(val);
+	return wl_bssiovar_set(wl, iovar, bssidx, &val, sizeof(int));
+}
+
+static int
+wl_nvdump(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	const char *iovar = "nvram_dump";
+	void *p = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* skip the "nvdump/nvram_dump" command name */
+	argv++;
+
+	if (*argv) {
+		printf("nvdump error: extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((err = wlu_var_getbuf(wl, iovar, NULL, 0, &p)) < 0) {
+		if ((err = wlu_get(wl, WLC_NVRAM_DUMP, &buf[0], WLC_IOCTL_MAXLEN)) < 0)
+		    return err;
+		p = (void *)buf;
+	}
+	fputs((char *)p, stdout);
+
+	return err;
+}
+
+/** Queries the driver for the value of a caller supplied nvram variable */
+static int
+wl_nvget(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	char *varname;
+	const char *iovar = "nvram_get";
+	void *p;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* skip the "nvget/nvram_get" command name */
+	argv++;
+
+	if (!*argv) {
+		printf("nvget: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (*argv) {
+		printf("nvget error: extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((err = wlu_var_getbuf(wl, iovar, varname, strlen(varname) + 1, &p)) < 0) {
+
+		strcpy(buf, varname);
+		if ((err = wlu_get(wl, WLC_NVRAM_GET, &buf[0], WLC_IOCTL_MAXLEN)) < 0)
+		    return err;
+	}
+
+	printf("%s\n", buf);
+
+	return err;
+}
+
+static int
+wl_nvset(void *wl, cmd_t *cmd, char **argv)
+{
+	char *varname;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* skip the "nvset" command name if present */
+	if (!strcmp("nvset", *argv))
+		argv++;
+
+	if (!*argv) {
+		printf("nvset: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (*argv) {
+		fprintf(stderr,
+		"nvset error: extra arg \"%s\"; format is name=value (no spaces around '=')\n",
+			*argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!strchr(varname, '=')) {
+		fprintf(stderr,
+		"nvset error: no '=' in \"%s\", format is name=value (no spaces around '=')\n",
+			*argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	strcpy(buf, varname);
+
+	return (wlu_set(wl, WLC_NVRAM_SET, &buf[0], strlen(buf) + 1));
+}
+
+static int
+wl_chan_info(void *wl, cmd_t *cmd, char **argv)
+{
+	uint bitmap;
+	uint channel;
+	uint32 chanspec_arg;
+	int buflen, err, first, last, minutes;
+	char *param;
+	bool all;
+
+	if (!*++argv) {
+		first = 0;
+		last = MAXCHANNEL;
+		all = TRUE;
+	} else {
+		last = first = atoi(*argv);
+		if (last <= 0) {
+			printf(" Usage: %s [channel | All ]\n", cmd->name);
+			return BCME_USAGE_ERROR;
+		}
+		all = FALSE;
+	}
+
+	for (; first <= last; first++) {
+		channel = first;
+		chanspec_arg = CH20MHZ_CHSPEC(channel);
+
+		strcpy(buf, "per_chan_info");
+		buflen = strlen(buf) + 1;
+		param = (char *)(buf + buflen);
+		/* there should be no problem if converting to a legacy chanspec
+		 * since chanspec_arg is created as 20MHz
+		 */
+		chanspec_arg = wl_chspec32_to_driver(chanspec_arg);
+		memcpy(param, (char*)&chanspec_arg, sizeof(chanspec_arg));
+
+		if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+			return err;
+
+		bitmap = dtoh32(*(uint *)buf);
+		minutes = (bitmap >> 24) & 0xff;
+
+		if (!(bitmap & WL_CHAN_VALID_HW)) {
+			if (!all)
+				printf("Invalid Channel\n");
+			continue;
+		}
+
+		if (!(bitmap & WL_CHAN_VALID_SW)) {
+			if (!all)
+				printf("Not supported in current locale\n");
+			continue;
+		}
+
+		printf("Channel %d\t", channel);
+
+		if (bitmap & WL_CHAN_BAND_5G)
+			printf("A Band");
+		else
+			printf("B Band");
+
+		if (bitmap & WL_CHAN_RADAR) {
+			printf(", RADAR Sensitive");
+		}
+		if (bitmap & WL_CHAN_RESTRICTED) {
+			printf(", Restricted");
+		}
+		if (bitmap & WL_CHAN_PASSIVE) {
+			printf(", Passive");
+		}
+		if (bitmap & WL_CHAN_INACTIVE) {
+			printf(", Temporarily Out of Service for %d minutes", minutes);
+		}
+		printf("\n");
+	}
+
+	return (0);
+}
+
+
+int
+wl_sta_info(void *wl, cmd_t *cmd, char **argv)
+{
+	sta_info_v4_t *sta;
+	sta_info_v5_t *sta_v5;
+	struct ether_addr ea;
+	char *param;
+	int buflen, err;
+	int i;
+	char buf_chanspec[20];
+	uint32 rxdur_total = 0;
+	bool have_rxdurtotal = FALSE;
+	chanspec_t chanspec;
+	bool have_chanspec = FALSE;
+	wl_rateset_args_t *rateset_adv;
+	bool have_rateset_adv = FALSE;
+
+
+	strcpy(buf, *argv);
+
+	/* convert the ea string into an ea struct */
+	if (!*++argv || !wl_ether_atoe(*argv, &ea)) {
+		printf(" ERROR: no valid ether addr provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	buflen = strlen(buf) + 1;
+	param = (char *)(buf + buflen);
+	memcpy(param, (char*)&ea, ETHER_ADDR_LEN);
+
+	if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MEDLEN)) < 0)
+		return err;
+
+	/* display the sta info */
+	sta = (sta_info_v4_t *)buf;
+	sta->ver = dtoh16(sta->ver);
+	sta->len = dtoh16(sta->len);
+
+	/* Report unrecognized version */
+	if (sta->ver < WL_STA_VER_4) {
+		printf(" ERROR: unsupported driver station info version %d\n", sta->ver);
+		return BCME_ERROR;
+	}
+	else if (sta->ver == WL_STA_VER_4) {
+		rxdur_total = dtoh32(sta->rx_dur_total);
+		have_rxdurtotal = TRUE;
+		if (sta->len >= STRUCT_SIZE_THROUGH(sta, rateset_adv)) {
+			chanspec = dtoh16(sta->chanspec);
+			wf_chspec_ntoa(chanspec, buf_chanspec);
+			have_chanspec = TRUE;
+
+			rateset_adv = &sta->rateset_adv;
+			have_rateset_adv = TRUE;
+		}
+	}
+	else if (sta->ver == WL_STA_VER_5) {
+		sta_v5 = (sta_info_v5_t *)buf;
+		chanspec = dtoh16(sta_v5->chanspec);
+		wf_chspec_ntoa(chanspec, buf_chanspec);
+		have_chanspec = TRUE;
+
+		rateset_adv = &sta_v5->rateset_adv;
+		have_rateset_adv = TRUE;
+	}
+	else {
+		printf(" ERROR: unknown driver station info version %d\n", sta->ver);
+		return BCME_ERROR;
+	}
+
+	sta->cap = dtoh16(sta->cap);
+	sta->aid = dtoh16(sta->aid);
+	sta->flags = dtoh32(sta->flags);
+	sta->idle = dtoh32(sta->idle);
+	sta->rateset.count = dtoh32(sta->rateset.count);
+	sta->in = dtoh32(sta->in);
+	sta->listen_interval_inms = dtoh32(sta->listen_interval_inms);
+	sta->ht_capabilities = dtoh16(sta->ht_capabilities);
+	sta->vht_flags = dtoh16(sta->vht_flags);
+
+	printf("[VER %d] STA %s:\n", sta->ver, *argv);
+	if (have_chanspec) {
+		printf("\t chanspec %s (0x%x)\n", buf_chanspec, chanspec);
+	}
+	printf("\t aid:%d ", WL_STA_AID(sta->aid));
+	printf("\n\t rateset ");
+	dump_rateset(sta->rateset.rates, sta->rateset.count);
+	printf("\n\t idle %d seconds\n", sta->idle);
+	printf("\t in network %d seconds\n", sta->in);
+	printf("\t state:%s%s%s\n",
+	       (sta->flags & WL_STA_AUTHE) ? " AUTHENTICATED" : "",
+	       (sta->flags & WL_STA_ASSOC) ? " ASSOCIATED" : "",
+	       (sta->flags & WL_STA_AUTHO) ? " AUTHORIZED" : "");
+
+	printf("\t flags 0x%x:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+	       sta->flags,
+	       (sta->flags & WL_STA_BRCM) ? " BRCM" : "",
+	       (sta->flags & WL_STA_WME) ? " WME" : "",
+	       (sta->flags & WL_STA_PS) ? " PS" : "",
+	       (sta->flags & WL_STA_NONERP) ? " No-ERP" : "",
+	       (sta->flags & WL_STA_APSD_BE) ? " APSD_BE" : "",
+	       (sta->flags & WL_STA_APSD_BK) ? " APSD_BK" : "",
+	       (sta->flags & WL_STA_APSD_VI) ? " APSD_VI" : "",
+	       (sta->flags & WL_STA_APSD_VO) ? " APSD_VO" : "",
+	       (sta->flags & WL_STA_N_CAP) ? " N_CAP" : "",
+	       (sta->flags & WL_STA_VHT_CAP) ? " VHT_CAP" : "",
+	       (sta->flags & WL_STA_AMPDU_CAP) ? " AMPDU" : "",
+	       (sta->flags & WL_STA_AMSDU_CAP) ? " AMSDU" : "",
+	       (sta->flags & WL_STA_MIMO_PS) ? " MIMO-PS" : "",
+	       (sta->flags & WL_STA_MIMO_RTS) ? " MIMO-PS-RTS" : "",
+	       (sta->flags & WL_STA_RIFS_CAP) ? " RIFS" : "");
+
+	printf("\t HT caps 0x%x:%s%s%s%s%s%s%s%s%s\n",
+		sta->ht_capabilities,
+	       (sta->ht_capabilities & WL_STA_CAP_LDPC_CODING) ? " LDPC" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_40MHZ) ? " 40MHz" : " ",
+	       (sta->ht_capabilities & WL_STA_CAP_GF) ? " GF" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_SHORT_GI_20) ? " SGI20" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_SHORT_GI_40) ? " SGI40" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_TX_STBC) ? " STBC-Tx" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_RX_STBC_MASK) ? " STBC-Rx" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_DELAYED_BA) ? " D-BlockAck" : "",
+	       (sta->ht_capabilities & WL_STA_CAP_40MHZ_INTOLERANT) ? " 40-Intl" : "");
+
+	if (sta->flags & WL_STA_VHT_CAP) {
+		printf("\t VHT caps 0x%x:%s%s%s%s%s%s%s%s%s%s%s\n",
+			sta->vht_flags,
+			(sta->vht_flags & WL_STA_VHT_LDPCCAP) ? " LDPC" : "",
+			(sta->vht_flags & WL_STA_SGI80) ? " SGI80" : "",
+			(sta->vht_flags & WL_STA_SGI160) ? " SGI160" : "",
+			(sta->vht_flags & WL_STA_VHT_TX_STBCCAP) ? " STBC-Tx" : "",
+			(sta->vht_flags & WL_STA_VHT_RX_STBCCAP) ? " STBC-Rx" : "",
+			(sta->vht_flags & WL_STA_SU_BEAMFORMER) ? " SU-BFR" : "",
+			(sta->vht_flags & WL_STA_SU_BEAMFORMEE) ? " SU-BFE" : "",
+			(sta->vht_flags & WL_STA_MU_BEAMFORMER) ? " MU-BFR" : "",
+			(sta->vht_flags & WL_STA_MU_BEAMFORMEE) ? " MU-BFE" : "",
+			(sta->vht_flags & WL_STA_VHT_TXOP_PS) ? " TXOPPS" : "",
+			(sta->vht_flags & WL_STA_HTC_VHT_CAP) ? " VHT-HTC" : "");
+	}
+
+	if (sta->flags & WL_STA_SCBSTATS)
+	{
+		printf("\t tx total pkts: %d\n", dtoh32(sta->tx_tot_pkts));
+		printf("\t tx total bytes: %llu\n", dtoh64(sta->tx_tot_bytes));
+		printf("\t tx ucast pkts: %d\n", dtoh32(sta->tx_pkts));
+		printf("\t tx ucast bytes: %llu\n", dtoh64(sta->tx_ucast_bytes));
+		printf("\t tx mcast/bcast pkts: %d\n", dtoh32(sta->tx_mcast_pkts));
+		printf("\t tx mcast/bcast bytes: %llu\n", dtoh64(sta->tx_mcast_bytes));
+		printf("\t tx failures: %d\n", dtoh32(sta->tx_failures));
+		printf("\t rx data pkts: %d\n", dtoh32(sta->rx_tot_pkts));
+		printf("\t rx data bytes: %llu\n", dtoh64(sta->rx_tot_bytes));
+		if (have_rxdurtotal) {
+			printf("\t rx data dur: %u\n", rxdur_total);
+		}
+		printf("\t rx ucast pkts: %d\n", dtoh32(sta->rx_ucast_pkts));
+		printf("\t rx ucast bytes: %llu\n", dtoh64(sta->rx_ucast_bytes));
+		printf("\t rx mcast/bcast pkts: %d\n", dtoh32(sta->rx_mcast_pkts));
+		printf("\t rx mcast/bcast bytes: %llu\n", dtoh64(sta->rx_mcast_bytes));
+		printf("\t rate of last tx pkt: %d kbps - %d kbps\n",
+			dtoh32(sta->tx_rate), dtoh32(sta->tx_rate_fallback));
+		printf("\t rate of last rx pkt: %d kbps\n", dtoh32(sta->rx_rate));
+		printf("\t rx decrypt succeeds: %d\n", dtoh32(sta->rx_decrypt_succeeds));
+		printf("\t rx decrypt failures: %d\n", dtoh32(sta->rx_decrypt_failures));
+		printf("\t tx data pkts retried: %d\n", dtoh32(sta->tx_pkts_retried));
+
+		for (i = WL_ANT_IDX_1; i < WL_RSSI_ANT_MAX; i++) {
+			if (i == WL_ANT_IDX_1)
+				printf("\t per antenna rssi of last rx data frame:");
+			printf(" %d", dtoh32(sta->rx_lastpkt_rssi[i]));
+			if (i == WL_RSSI_ANT_MAX-1)
+				printf("\n");
+		}
+		for (i = WL_ANT_IDX_1; i < WL_RSSI_ANT_MAX; i++) {
+			if (i == WL_ANT_IDX_1)
+				printf("\t per antenna average rssi of rx data frames:");
+			printf(" %d", dtoh32(sta->rssi[i]));
+			if (i == WL_RSSI_ANT_MAX-1)
+				printf("\n");
+		}
+		for (i = WL_ANT_IDX_1; i < WL_RSSI_ANT_MAX; i++) {
+			if (i == WL_ANT_IDX_1)
+				printf("\t per antenna noise floor:");
+			printf(" %d", dtoh32(sta->nf[i]));
+			if (i == WL_RSSI_ANT_MAX-1)
+				printf("\n");
+		}
+
+		printf("\t tx total pkts sent: %d\n", dtoh32(sta->tx_pkts_total));
+		printf("\t tx pkts retries: %d\n", dtoh32(sta->tx_pkts_retries));
+		printf("\t tx pkts retry exhausted: %d\n", dtoh32(sta->tx_pkts_retry_exhausted));
+		printf("\t tx FW total pkts sent: %d\n", dtoh32(sta->tx_pkts_fw_total));
+		printf("\t tx FW pkts retries: %d\n", dtoh32(sta->tx_pkts_fw_retries));
+		printf("\t tx FW pkts retry exhausted: %d\n",
+			dtoh32(sta->tx_pkts_fw_retry_exhausted));
+		printf("\t rx total pkts retried: %d\n", dtoh32(sta->rx_pkts_retried));
+	}
+	/* Driver didn't return extended station info */
+	if (sta->len < sizeof(sta_info_v5_t)) {
+		return 0;
+	}
+
+	if (have_rateset_adv) {
+		wl_print_mcsset((char *)rateset_adv->mcs);
+		wl_print_vhtmcsset((uint16 *)rateset_adv->vht_mcs);
+	}
+
+	return (0);
+}
+
+static int
+wl_revinfo(void *wl, cmd_t *cmd, char **argv)
+{
+	char b[8];
+	int err;
+	wlc_rev_info_t revinfo;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(&revinfo, 0, sizeof(revinfo));
+
+	if ((err = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+		return err;
+
+	printf("vendorid 0x%x\n", dtoh32(revinfo.vendorid));
+	printf("deviceid 0x%x\n", dtoh32(revinfo.deviceid));
+	printf("radiorev 0x%x\n", dtoh32(revinfo.radiorev));
+	printf("chipnum 0x%x\n", dtoh32(revinfo.chipnum));
+	printf("chiprev 0x%x\n", dtoh32(revinfo.chiprev));
+	printf("chippackage 0x%x\n", dtoh32(revinfo.chippkg));
+	printf("corerev %d.%d\n", dtoh32(revinfo.corerev), dtoh32(revinfo.coreminorrev));
+	printf("boardid 0x%x\n", dtoh32(revinfo.boardid));
+	printf("boardvendor 0x%x\n", dtoh32(revinfo.boardvendor));
+	printf("boardrev %s\n", bcm_brev_str(dtoh32(revinfo.boardrev), b));
+	if (revinfo.driverrev) {
+		uint32 rev = dtoh32(revinfo.driverrev);
+		printf("driverrev %d.%d.%d.%d\n",
+			(rev >> 24) & 0xFF,
+			(rev >> 16) & 0xFF,
+			(rev >> 8) & 0xFF,
+			rev & 0xFF);
+	} else {
+		printf("driverrev %d.%d.%d.%d\n",
+			dtoh32(revinfo.drvrev_major),
+			dtoh32(revinfo.drvrev_minor),
+			dtoh32(revinfo.drvrev_rc),
+			dtoh32(revinfo.drvrev_rc_inc));
+	}
+	printf("ucoderev 0x%x\n", dtoh32(revinfo.ucoderev));
+	printf("bus 0x%x\n", dtoh32(revinfo.bus));
+	printf("phytype 0x%x\n", dtoh32(revinfo.phytype));
+	printf("phyrev %d.%d\n", dtoh32(revinfo.phyrev), dtoh32(revinfo.phyminorrev));
+	printf("anarev 0x%x\n", dtoh32(revinfo.anarev));
+	printf("nvramrev %d\n", dtoh32(revinfo.nvramrev));
+
+	return 0;
+}
+
+static int
+wl_rm_request(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_rm_request";
+	wl_rm_req_t *rm_ptr;
+	wl_rm_req_t rm;
+	wl_rm_req_elt_t req;
+	int buflen = 0;
+	int err, opt_err;
+	int type;
+	bool in_measure = FALSE;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	memset(&rm, 0, WL_RM_REQ_FIXED_LEN);
+	memset(&req, 0, sizeof(wl_rm_req_elt_t));
+
+	strcpy(buf, "rm_req");
+	buflen = strlen(buf) + 1;
+
+	rm_ptr = (wl_rm_req_t*)(buf + buflen);
+	buflen += WL_RM_REQ_FIXED_LEN;
+
+	/* toss the command name */
+	argv++;
+
+	miniopt_init(&to, fn_name, "p", FALSE);
+	while ((opt_err = miniopt(&to, argv)) != -1) {
+		if (opt_err == 1) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv += to.consumed;
+
+		if (to.opt == 't') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for the token\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+
+			if (!in_measure)
+				rm.token = to.val;
+			else
+				req.token = to.val;
+		}
+		if (to.opt == 'c') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for channel\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+
+			req.chanspec = CH20MHZ_CHSPEC(to.val);
+		}
+		if (to.opt == 'd') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for duration\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			req.dur = to.val;
+		}
+
+		if (to.opt == 'p') {
+			req.flags = WL_RM_FLAG_PARALLEL;
+		}
+
+		if (to.positional) {
+			if (!strcmp(to.valstr, "basic")) {
+				type = WL_RM_TYPE_BASIC;
+			} else if (!strcmp(to.valstr, "cca")) {
+				type = WL_RM_TYPE_CCA;
+			} else if (!strcmp(to.valstr, "rpi")) {
+				type = WL_RM_TYPE_RPI;
+			} else {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as a measurement type\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			/* complete the previous measurement */
+			if (in_measure) {
+				req.chanspec = wl_chspec_to_driver(req.chanspec);
+				req.token = htod32(req.token);
+				req.tsf_h = htod32(req.tsf_h);
+				req.tsf_l = htod32(req.tsf_l);
+				req.dur = htod32(req.dur);
+				memcpy(buf + buflen, &req, sizeof(wl_rm_req_elt_t));
+				buflen += sizeof(wl_rm_req_elt_t);
+				rm.count++;
+				req.chanspec = wl_chspec_from_driver(req.chanspec);
+				req.token = dtoh32(req.token);
+				req.tsf_h = dtoh32(req.tsf_h);
+				req.tsf_l = dtoh32(req.tsf_l);
+				req.dur = dtoh32(req.dur);
+				/* measure to measure default param update */
+				req.token++;	/* each measure gets a new token */
+				req.flags = 0;	/* measure flags are cleared between measures */
+			}
+			in_measure = TRUE;
+			req.type = (int8)type;
+		}
+	}
+
+	/* complete the last measurement */
+	if (in_measure) {
+		req.chanspec = wl_chspec_to_driver(req.chanspec);
+		req.token = htod32(req.token);
+		req.tsf_h = htod32(req.tsf_h);
+		req.tsf_l = htod32(req.tsf_l);
+		req.dur = htod32(req.dur);
+		memcpy(buf + buflen, &req, sizeof(wl_rm_req_elt_t));
+		buflen += sizeof(wl_rm_req_elt_t);
+		rm.count++;
+	}
+
+	if (rm.count == 0) {
+		fprintf(stderr, "%s: no measurement requests specified\n",
+			fn_name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	rm.token = htod32(rm.token);
+	rm.count = htod32(rm.count);
+	memcpy(rm_ptr, &rm, WL_RM_REQ_FIXED_LEN);
+
+	err = wlu_set(wl, WLC_SET_VAR, &buf[0], buflen);
+
+exit:
+	return err;
+}
+
+static int
+wl_rm_report(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_rm_rep_t *rep_set;
+	wl_rm_rep_elt_t rep;
+	char extra[128];
+	char* p;
+	const char* name;
+	uint8* data;
+	int err, bin;
+	uint32 val;
+	uint16 channel;
+	bool aband;
+	int len;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	strcpy(buf, "rm_rep");
+
+	if ((err = wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	rep_set = (wl_rm_rep_t *)buf;
+	rep_set->token = dtoh32(rep_set->token);
+	rep_set->len = dtoh32(rep_set->len);
+
+	printf("Measurement Report: token %d, length %d\n", rep_set->token, rep_set->len);
+
+	len = rep_set->len;
+	data = (uint8*)rep_set->rep;
+	for (; len > 0; (len -= rep.len), (data += rep.len)) {
+		if (len >= WL_RM_REP_ELT_FIXED_LEN)
+			memcpy(&rep, data, WL_RM_REP_ELT_FIXED_LEN);
+		else
+			break;
+
+		rep.chanspec = wl_chspec_from_driver(rep.chanspec);
+		rep.token = dtoh32(rep.token);
+		rep.tsf_h = dtoh32(rep.tsf_h);
+		rep.tsf_l = dtoh32(rep.tsf_l);
+		rep.dur = dtoh32(rep.dur);
+		rep.len = dtoh32(rep.len);
+
+		data += WL_RM_REP_ELT_FIXED_LEN;
+		len -= WL_RM_REP_ELT_FIXED_LEN;
+
+		if (rep.type == WL_RM_TYPE_BASIC)
+			name = "Basic";
+		else if (rep.type == WL_RM_TYPE_CCA)
+			name = "CCA";
+		else if (rep.type == WL_RM_TYPE_RPI)
+			name = "RPI";
+		else
+			name = NULL;
+
+		if (name)
+			printf("\nReport   : %s\n", name);
+		else
+			printf("\nReport   : %d <unknown>\n", rep.type);
+
+		p = extra;
+		if (rep.flags & WL_RM_FLAG_PARALLEL) {
+			if (p != extra)
+				p += sprintf(p, " | ");
+			p += sprintf(p, "Parallel");
+		}
+		if (rep.flags & WL_RM_FLAG_LATE) {
+			if (p != extra)
+				p += sprintf(p, " | ");
+			p += sprintf(p, "Late");
+		}
+		if (rep.flags & WL_RM_FLAG_INCAPABLE) {
+			if (p != extra)
+				p += sprintf(p, " | ");
+			p += sprintf(p, "Incapable");
+		}
+		if (rep.flags & WL_RM_FLAG_REFUSED) {
+			if (p != extra)
+				p += sprintf(p, " | ");
+			p += sprintf(p, "Refused");
+		}
+
+		if (p != extra) {
+			printf("flags    : 0x%02x (%s)\n", rep.flags, extra);
+		} else {
+			printf("flags    : 0x%02x\n", rep.flags);
+		}
+		printf("token    : %4d\n", rep.token);
+
+		if (rep.flags & (WL_RM_FLAG_LATE |
+			WL_RM_FLAG_INCAPABLE |
+			WL_RM_FLAG_REFUSED)) {
+			continue;
+		}
+
+		channel = CHSPEC_CHANNEL(rep.chanspec);
+		aband = CHSPEC_IS5G(rep.chanspec);
+
+		printf("channel  : %4d %s\n", channel,
+		       aband ? "(a)":"(b)");
+		printf("start tsf: 0x%x:%08x\n", rep.tsf_h, rep.tsf_l);
+		printf("duration : %4d TU\n", rep.dur);
+
+		if (len < (int)rep.len) {
+			printf("Error: partial report element, %d report bytes "
+			       "remain, element claims %d\n",
+			       len, rep.len);
+			break;
+		}
+
+		if (rep.type == WL_RM_TYPE_BASIC) {
+			if (rep.len >= 4) {
+				memcpy(&val, data, sizeof(uint32));
+				val = dtoh32(val);
+				printf("Basic bits: 0x%08x\n", val);
+			}
+		} else if (rep.type == WL_RM_TYPE_CCA) {
+			if (rep.len >= 4) {
+				memcpy(&val, data, sizeof(uint32));
+				val = dtoh32(val);
+				printf("Carrier Fraction: %d / 255\n", val);
+			}
+		} else if (rep.type == WL_RM_TYPE_RPI) {
+			if (rep.len >= sizeof(wl_rm_rpi_rep_t)) {
+				wl_rm_rpi_rep_t rpi_rep;
+				int8 min = -128;
+				int8 max;
+
+				memcpy(&rpi_rep, data, sizeof(wl_rm_rpi_rep_t));
+
+				for (bin = 0; bin < 8; bin++) {
+					max = rpi_rep.rpi_max[bin];
+					if (bin == 0)
+						printf("       Power <= %3d: ",
+						       max);
+					else if (bin < 7)
+						printf(" %3d < Power <= %3d: ",
+						       min, max);
+					else
+						printf(" %3d < Power       : ",
+						       min);
+					min = max;
+					printf("%3d\n", rpi_rep.rpi[bin]);
+				}
+			}
+		}
+	}
+
+	return err;
+}
+
+static int
+wl_join_pref(void *wl, cmd_t *cmd, char **argv)
+{
+	char* data;
+	int err;
+	int len;
+	int remaining_bytes;
+	int i;
+	bcm_tlv_t *ie;
+
+	UNUSED_PARAMETER(cmd);
+
+	strcpy(buf, "join_pref");
+
+	/* set */
+	if (argv[1]) {
+		len = strlen(buf);
+		data = argv[1];
+		for (i = len + 1, len += 1 + strlen(data) / 2;
+		    (i < len) && (i < (int)WLC_IOCTL_MAXLEN); i ++) {
+			char hex[] = "XX";
+			hex[0] = *data++;
+			hex[1] = *data++;
+			buf[i] = (uint8)strtoul(hex, NULL, 16);
+		}
+		err = wlu_set(wl, WLC_SET_VAR, buf, i);
+	}
+	/* get */
+	else if (!(err = wlu_get(wl, WLC_GET_VAR, buf, WLC_IOCTL_MAXLEN))) {
+		len = dtoh32(*(int *)buf);
+		data = buf + sizeof(int);
+		for (i = 0; i < len; i ++)
+			printf("%02x", (uint8)(data[i]));
+		printf("\n");
+		/* pretty print the join pref elements */
+		remaining_bytes = len;
+		ie = (bcm_tlv_t*)data;
+		if (!bcm_valid_tlv(ie, remaining_bytes))
+		    ie = NULL;
+		while (ie) {
+			wl_join_pref_print_ie(ie);
+			ie = bcm_next_tlv(ie, &remaining_bytes);
+		}
+	}
+	return err;
+}
+
+static void
+wl_join_pref_print_ie(bcm_tlv_t *ie)
+{
+	int i;
+	uint8 band;
+	uint8 count;
+	int suite_len;
+	uint8 *suite;
+	int data_bytes;
+
+
+	switch (ie->id) {
+	case WL_JOIN_PREF_RSSI:
+		printf("Pref RSSI\n");
+		if (ie->len > 2)
+			printf("\t<%d extra bytes in pref data>\n", ie->len);
+		break;
+	case WL_JOIN_PREF_BAND:
+		printf("Pref BAND: ");
+		if (ie->len < 2) {
+			printf("len = %d <band pref data truncated>\n", ie->len);
+			break;
+		}
+
+		band = ie->data[1];
+		if (band == WLC_BAND_AUTO)
+			printf("0x%x AUTO (no preference)\n", band);
+		else if (band == WLC_BAND_5G)
+			printf("0x%x 5 GHz\n", band);
+		else if (band == WLC_BAND_2G)
+			printf("0x%x 2.4 GHz\n", band);
+		else if (band == WLJP_BAND_ASSOC_PREF)
+			printf("0x%x Use ASSOC_PREFER value\n", band);
+		else
+			printf("0x%x\n", band);
+
+		if (ie->len > 2)
+			printf("\t<%d extra bytes in pref data>\n", ie->len - 1);
+
+		break;
+	case WL_JOIN_PREF_WPA:
+		printf("Pref WPA: ");
+		if (ie->len < 2) {
+			printf("len = %d <WPA pref data truncated>\n", ie->len);
+			break;
+		}
+		count = ie->data[1];
+		printf("%d ACP Specs\n", count);
+
+		data_bytes = ie->len - 2;
+		suite_len = 4; /* WPA Suite Selector length, OUI + type */
+		suite = ie->data + 2;
+
+		for (i = 0; i < (int)count; i++) {
+			if (data_bytes < 3 * suite_len)
+				break;
+			printf("\t");
+			/* AKM Suite */
+			wl_join_pref_print_akm(suite);
+			printf(",");
+
+			suite = suite + suite_len;
+			/* Unicast Cipher Suite */
+			printf("U:");
+			wl_join_pref_print_cipher_suite(suite);
+			printf(",");
+
+			suite = suite + suite_len;
+			/* Multicast Cipher Suite */
+			printf("M:");
+			if (!memcmp(suite, WL_WPA_ACP_MCS_ANY, suite_len))
+				printf("Any");
+			else
+				wl_join_pref_print_cipher_suite(suite);
+			printf("\n");
+
+			suite = suite + suite_len;
+			data_bytes -= 3 * suite_len;
+		}
+
+		if (i != count)
+			printf("\t<expected %d more specs, %d bytes>\n",
+			count - i, suite_len * (count - i));
+		if (data_bytes > 0)
+			printf("\t<%d extra bytes>\n", data_bytes);
+		break;
+	case WL_JOIN_PREF_RSSI_DELTA:
+		printf("RSSI Delta for Pref BAND: ");
+		if (ie->len < 2) {
+			printf("len = %d <rssi delta pref data truncated>\n", ie->len);
+			break;
+		}
+
+		band = ie->data[1];
+		if (band == WLC_BAND_AUTO)
+			printf("0x%x AUTO (no preference)\n", band);
+		else if (band == WLC_BAND_5G)
+			printf("0x%x 5 GHz\n", band);
+		else if (band == WLC_BAND_2G)
+			printf("0x%x 2.4 GHz\n", band);
+		else
+			printf("0x%x\n", band);
+
+		printf("RSSI boost %ddb\n", ie->data[0]);
+
+		break;
+	default:
+		printf("Pref 0x%x: len = %d\n", ie->id, ie->len);
+		for (i = 0; i < ie->len; i++)
+			printf("%02x", ie->data[i]);
+		printf("\n");
+		break;
+
+	}
+
+}
+
+static void
+wl_join_pref_print_akm(uint8* suite)
+{
+	uint8 type = suite[3];
+	const char *oui_name;
+
+	if (!memcmp(suite, WPA_OUI, 3))
+		oui_name = "WPA";
+	else if (!memcmp(suite, WPA2_OUI, 3))
+		oui_name = "WPA2";
+	else
+		oui_name = NULL;
+
+	if (oui_name) {
+		if (type == RSN_AKM_NONE)
+			printf("%s-NONE", oui_name);
+		else if (type == RSN_AKM_UNSPECIFIED)
+			printf("%s", oui_name);
+		else if (type == RSN_AKM_UNSPECIFIED)
+			printf("%s-PSK", oui_name);
+		else
+			printf("%s/0x%x", oui_name, type);
+	} else {
+		printf("0x%02x%02x%02x/0x%02x", suite[0], suite[1], suite[2], suite[3]);
+	}
+}
+
+static void
+wl_join_pref_print_cipher_suite(uint8* suite)
+{
+	uint8 type = suite[3];
+	const char *oui_name;
+
+	if (!memcmp(suite, WPA_OUI, 3))
+		oui_name = "WPA";
+	else if (!memcmp(suite, WPA2_OUI, 3))
+		oui_name = "WPA2";
+	else
+		oui_name = NULL;
+
+	if (oui_name) {
+		if (type == WPA_CIPHER_NONE)
+			printf("%s/NONE", oui_name);
+		else if (type == WPA_CIPHER_WEP_40)
+			printf("%s/WEP40", oui_name);
+		else if (type == WPA_CIPHER_TKIP)
+			printf("%s/TKIP", oui_name);
+		else if (type == WPA_CIPHER_AES_CCM)
+			printf("%s/AES", oui_name);
+		else if (type == WPA_CIPHER_WEP_104)
+			printf("%s/WEP104", oui_name);
+		else
+			printf("%s/0x%x", oui_name, type);
+	} else {
+		printf("0x%02x%02x%02x/0x%02x", suite[0], suite[1], suite[2], suite[3]);
+	}
+}
+
+static int
+wl_assoc_pref(void *wl, cmd_t *cmd, char **argv)
+{
+	uint assoc_pref;
+	int err;
+
+	/* set */
+	if (argv[1]) {
+		if (!strcmp(argv[1], "auto") || !strcmp(argv[1], "0"))
+			assoc_pref = WLC_BAND_AUTO;
+		else if (!strcmp(argv[1], "a") || !strcmp(argv[1], "1"))
+			assoc_pref = WLC_BAND_5G;
+		else if (!strcmp(argv[1], "b") || !strcmp(argv[1], "g") || !strcmp(argv[1], "2"))
+			assoc_pref = WLC_BAND_2G;
+		else
+			return BCME_USAGE_ERROR;
+		assoc_pref = htod32(assoc_pref);
+		err = wlu_set(wl, cmd->set, &assoc_pref, sizeof(assoc_pref));
+	}
+	/* get */
+	else if (!(err = wlu_get(wl, cmd->get, &assoc_pref, sizeof(assoc_pref)))) {
+		assoc_pref = dtoh32(assoc_pref);
+		switch (assoc_pref) {
+		case WLC_BAND_AUTO:
+			printf("auto\n");
+			break;
+		case WLC_BAND_5G:
+			printf("a\n");
+			break;
+		case WLC_BAND_2G:
+			printf("b/g\n");
+			break;
+		}
+	}
+	return err;
+}
+
+static const char ac_names[AC_COUNT][6] = {"AC_BE", "AC_BK", "AC_VI", "AC_VO"};
+
+/*
+ * Get or set WME per-AC transmit parameters
+ */
+static int
+wme_tx_params(void *wl, cmd_t *cmd, char **argv)
+{
+	char *val_p, *ac_str, *param;
+	int buflen;
+	int aci;
+	wme_tx_params_t cur_params[AC_COUNT], new_params[AC_COUNT];
+	int err;
+	int val;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	buflen = WLC_IOCTL_MAXLEN;
+
+	/*
+	 * Get current acparams, using buf as an input buffer.
+	 * Return data is array of 4 ACs of wme params.
+	 */
+
+	strcpy(buf, "wme_tx_params");
+	if ((err = wlu_get(wl, WLC_GET_VAR, &buf[0], buflen)) < 0) {
+		return err;
+	}
+	memcpy(&cur_params, buf, WL_WME_TX_PARAMS_IO_BYTES);
+
+	if ((ac_str = *argv++) == NULL) {
+		printf("WME TX params: \n");
+		for (aci = 0; aci < AC_COUNT; aci++) {
+			printf("%s: short %d. sfb %d. long %d. lfb %d. max %d\n", ac_names[aci],
+				cur_params[aci].short_retry,
+				cur_params[aci].short_fallback,
+				cur_params[aci].long_retry,
+				cur_params[aci].long_fallback,
+				cur_params[aci].max_rate);
+		}
+	} else {
+		int chk_lim;
+		if (strcmp(ac_str, "be") == 0) {
+			aci = AC_BE;
+		} else if (strcmp(ac_str, "bk") == 0) {
+			aci = AC_BK;
+		} else if (strcmp(ac_str, "vi") == 0) {
+			aci = AC_VI;
+		} else if (strcmp(ac_str, "vo") == 0) {
+			aci = AC_VO;
+		} else {
+			printf("Unknown access class: %s\n", ac_str);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* Preload new values with current values */
+		memcpy(&new_params, &cur_params, sizeof(new_params));
+		while ((param = *argv++) != NULL) {
+			if ((val_p = *argv++) == NULL) {
+				printf("Need value following %s\n", param);
+				return BCME_USAGE_ERROR;
+			}
+			chk_lim = 15;
+			val = (int)strtoul(val_p, NULL, 0);
+			/* All values must fit in uint8 */
+			if (!strcmp(param, "short")) {
+				new_params[aci].short_retry = (uint8)val;
+			} else if (!strcmp(param, "sfb")) {
+				new_params[aci].short_fallback = (uint8)val;
+			} else if (!strcmp(param, "long")) {
+				new_params[aci].long_retry = (uint8)val;
+			} else if (!strcmp(param, "lfb")) {
+				new_params[aci].long_fallback = (uint8)val;
+			} else if ((!strcmp(param, "max_rate")) || (!strcmp(param, "max")) ||
+				(!strcmp(param, "rate"))) {
+				chk_lim = 255;
+				new_params[aci].max_rate = (uint8)val;
+			} else {
+				printf("Unknown parameter: %s\n", param);
+				return BCME_USAGE_ERROR;
+			}
+			if (val > chk_lim) {
+				printf("Value for %s must be < %d\n", param, chk_lim + 1);
+				return BCME_USAGE_ERROR;
+			}
+		}
+		strcpy(buf, "wme_tx_params");
+		memcpy(buf + strlen(buf) + 1, new_params, WL_WME_TX_PARAMS_IO_BYTES);
+		err = wlu_set(wl, WLC_SET_VAR, &buf[0], buflen);
+	}
+
+	return err;
+}
+
+/*
+ * Get or Set WME Access Class (AC) parameters
+ *	wl wme_ac ap|sta [be|bk|vi|vo [ecwmax|ecwmin|txop|aifsn|acm <value>] ...]
+ * Without args past ap|sta, print current values
+ */
+static int
+wl_wme_ac_req(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *iovar_name;
+	int err;
+	edcf_acparam_t acparam_cur[AC_COUNT], acparam_new[AC_COUNT], *acp;
+	char *ac_str, *param, *val;
+	bool acm;
+	int aci, aifsn, ecwmin, ecwmax, txop;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	if ((param = *argv++) == NULL)
+		return BCME_USAGE_ERROR;
+
+	if (!strcmp(param, "ap"))
+		iovar_name = "wme_ac_ap";
+	else if (!strcmp(param, "sta"))
+		iovar_name = "wme_ac_sta";
+	else
+		return BCME_USAGE_ERROR;
+
+	/*
+	 * Get current acparams into an array of 4 ACs of wme params.
+	 */
+	err = wlu_iovar_get(wl, iovar_name, &acparam_cur, sizeof(acparam_cur));
+	if (err < 0)
+		return err;
+
+	if ((ac_str = *argv++) == NULL) {
+		printf("AC Parameters\n");
+
+		for (aci = 0; aci < AC_COUNT; aci++) {
+			acp = &acparam_cur[aci];
+			acp->TXOP = dtoh16(acp->TXOP);
+			if (((acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT) != aci)
+				printf("Warning: AC params out of order\n");
+			acm = (acp->ACI & EDCF_ACM_MASK) ? 1 : 0;
+			aifsn = acp->ACI & EDCF_AIFSN_MASK;
+			ecwmin = acp->ECW & EDCF_ECWMIN_MASK;
+			ecwmax = (acp->ECW & EDCF_ECWMAX_MASK) >> EDCF_ECWMAX_SHIFT;
+			txop = acp->TXOP;
+			printf("%s: raw: ACI 0x%x ECW 0x%x TXOP 0x%x\n",
+			       ac_names[aci],
+			       acp->ACI, acp->ECW, acp->TXOP);
+			printf("       dec: aci %d acm %d aifsn %d "
+			       "ecwmin %d ecwmax %d txop 0x%x\n",
+			       aci, acm, aifsn, ecwmin, ecwmax, txop);
+			/* CWmin = 2^(ECWmin) - 1 */
+			/* CWmax = 2^(ECWmax) - 1 */
+			/* TXOP = number of 32 us units */
+			printf("       eff: CWmin %d CWmax %d TXop %dusec\n",
+			       EDCF_ECW2CW(ecwmin), EDCF_ECW2CW(ecwmax), EDCF_TXOP2USEC(txop));
+		}
+
+		err = 0;
+	} else {
+		if (strcmp(ac_str, "be") == 0)
+			aci = AC_BE;
+		else if (strcmp(ac_str, "bk") == 0)
+			aci = AC_BK;
+		else if (strcmp(ac_str, "vi") == 0)
+			aci = AC_VI;
+		else if (strcmp(ac_str, "vo") == 0)
+			aci = AC_VO;
+		else
+			return BCME_USAGE_ERROR;
+
+		/* Preload new values with current values */
+		memcpy(&acparam_new, &acparam_cur, sizeof(acparam_new));
+
+		acp = &acparam_new[aci];
+
+		while ((param = *argv++) != NULL) {
+			if ((val = *argv++) == NULL)
+				return BCME_USAGE_ERROR;
+
+			if (!strcmp(param, "acm")) {
+				if (!stricmp(val, "on") || !stricmp(val, "1"))
+					acp->ACI |= EDCF_ACM_MASK;
+				else if (!stricmp(val, "off") || !stricmp(val, "0"))
+					acp->ACI &= ~EDCF_ACM_MASK;
+				else {
+					fprintf(stderr, "acm value must be 1|0\n");
+					return BCME_USAGE_ERROR;
+				}
+			} else if (!strcmp(param, "aifsn")) {
+				aifsn = (int)strtol(val, NULL, 0);
+				if (aifsn >= EDCF_AIFSN_MIN && aifsn <= EDCF_AIFSN_MAX)
+					acp->ACI =
+					        (acp->ACI & ~EDCF_AIFSN_MASK) |
+					        (aifsn & EDCF_AIFSN_MASK);
+				else {
+					fprintf(stderr, "aifsn %d out of range (%d-%d)\n",
+					        aifsn, EDCF_AIFSN_MIN, EDCF_AIFSN_MAX);
+					return BCME_USAGE_ERROR;
+				}
+			} else if (!strcmp(param, "ecwmax")) {
+				ecwmax = (int)strtol(val, NULL, 0);
+				if (ecwmax >= EDCF_ECW_MIN && ecwmax <= EDCF_ECW_MAX)
+					acp->ECW =
+					        ((ecwmax << EDCF_ECWMAX_SHIFT) & EDCF_ECWMAX_MASK) |
+					        (acp->ECW & EDCF_ECWMIN_MASK);
+				else {
+					fprintf(stderr, "ecwmax %d out of range (%d-%d)\n",
+					        ecwmax, EDCF_ECW_MIN, EDCF_ECW_MAX);
+					return BCME_USAGE_ERROR;
+				}
+			} else if (!strcmp(param, "ecwmin")) {
+				ecwmin = (int)strtol(val, NULL, 0);
+				if (ecwmin >= EDCF_ECW_MIN && ecwmin <= EDCF_ECW_MAX)
+					acp->ECW =
+					        ((acp->ECW & EDCF_ECWMAX_MASK) |
+					         (ecwmin & EDCF_ECWMIN_MASK));
+				else {
+					fprintf(stderr, "ecwmin %d out of range (%d-%d)\n",
+					        ecwmin, EDCF_ECW_MIN, EDCF_ECW_MAX);
+					return BCME_USAGE_ERROR;
+				}
+			} else if (!strcmp(param, "txop")) {
+				txop = (int)strtol(val, NULL, 0);
+				if (txop >= EDCF_TXOP_MIN && txop <= EDCF_TXOP_MAX)
+					acp->TXOP = htod16(txop);
+				else {
+					fprintf(stderr, "txop %d out of range (%d-%d)\n",
+					        txop, EDCF_TXOP_MIN, EDCF_TXOP_MAX);
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				fprintf(stderr, "unexpected param %s\n", param);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		/*
+		 * Now set the new acparams
+		 * NOTE: only one of the four ACs can be set at a time.
+		 */
+		err = wlu_iovar_set(wl, iovar_name, acp, sizeof(edcf_acparam_t));
+	}
+
+	return err;
+}
+
+/*
+ * Get or Set WME APSD control parameters
+ *	wl wme_apsd_sta <max_sp_len> <be> <bk> <vi> <vo>
+ *	  <max_sp_len> is 0 (all), 2, 4, or 6
+ *        <be>, <bk>, <vi>, <vo> are each 0 or 1 for APSD enable
+ *  with no args, print current values
+ */
+static int
+wl_wme_apsd_sta(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int buflen;
+	char *param;
+	int qosinfo;
+	int msp, max_sp_len, be, bk, vi, vo;
+
+	/* Display current params if no args, else set params */
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "wme_qosinfo");
+	buflen = WLC_IOCTL_MAXLEN;
+
+	param = *++argv;
+
+	if (param == NULL) {
+		if ((err = wlu_get(wl, cmd->get, &buf[0], buflen)) < 0)
+			return err;
+
+		memcpy(&qosinfo, buf, sizeof(qosinfo));
+		qosinfo = dtoh32(qosinfo);
+
+		msp = (qosinfo & WME_QI_STA_MAXSPLEN_MASK) >> WME_QI_STA_MAXSPLEN_SHIFT;
+		be = (qosinfo & WME_QI_STA_APSD_BE_MASK) >> WME_QI_STA_APSD_BE_SHIFT;
+		bk = (qosinfo & WME_QI_STA_APSD_BK_MASK) >> WME_QI_STA_APSD_BK_SHIFT;
+		vi = (qosinfo & WME_QI_STA_APSD_VI_MASK) >> WME_QI_STA_APSD_VI_SHIFT;
+		vo = (qosinfo & WME_QI_STA_APSD_VO_MASK) >> WME_QI_STA_APSD_VO_SHIFT;
+
+		max_sp_len = msp * 2;
+
+		printf("Max SP Length = %d, APSD: BE=%d BK=%d VI=%d VO=%d\n",
+		       max_sp_len, be, bk, vi, vo);
+	} else {
+		max_sp_len = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		be = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		bk = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		vi = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		vo = (int)strtol(param, 0, 0);
+
+		if (((be | bk | vi | vo) & ~1) | (max_sp_len & ~6)) {
+			printf("%s: Invalid parameter\n", cmd->name);
+			return BCME_BADARG;
+		}
+
+		msp = max_sp_len / 2;
+
+		qosinfo = (msp << WME_QI_STA_MAXSPLEN_SHIFT) & WME_QI_STA_MAXSPLEN_MASK;
+		qosinfo |= (be << WME_QI_STA_APSD_BE_SHIFT) & WME_QI_STA_APSD_BE_MASK;
+		qosinfo |= (bk << WME_QI_STA_APSD_BK_SHIFT) & WME_QI_STA_APSD_BK_MASK;
+		qosinfo |= (vi << WME_QI_STA_APSD_VI_SHIFT) & WME_QI_STA_APSD_VI_MASK;
+		qosinfo |= (vo << WME_QI_STA_APSD_VO_SHIFT) & WME_QI_STA_APSD_VO_MASK;
+
+		qosinfo = htod32(qosinfo);
+		memcpy(&buf[strlen(buf) + 1], &qosinfo, sizeof(qosinfo));
+
+		err = wlu_set(wl, cmd->set, &buf[0], buflen);
+	}
+
+	return err;
+}
+
+/*
+ * Get or Set WME discard policy
+ *	wl wme_dp <be> <bk> <vi> <vo>
+ *        <be>, <bk>, <vi>, <vo> are each 0/1 for discard newest/oldest first
+ *  with no args, print current values
+ */
+static int
+wl_wme_dp(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int buflen;
+	char *param;
+	int dp;
+	int be, bk, vi, vo;
+
+	/* Display current params if no args, else set params */
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "wme_dp");
+	buflen = WLC_IOCTL_MAXLEN;
+
+	param = *++argv;
+
+	if (param == NULL) {
+		if ((err = wlu_get(wl, cmd->get, &buf[0], buflen)) < 0)
+			return err;
+
+		memcpy(&dp, buf, sizeof(dp));
+		dp = dtoh32(dp);
+
+		be = (dp >> AC_BE) & 1;
+		bk = (dp >> AC_BK) & 1;
+		vi = (dp >> AC_VI) & 1;
+		vo = (dp >> AC_VO) & 1;
+
+		printf("Discard oldest first: BE=%d BK=%d VI=%d VO=%d\n", be, bk, vi, vo);
+	} else {
+		be = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		bk = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		vi = (int)strtol(param, 0, 0);
+		if ((param = *++argv) == NULL)
+			return BCME_USAGE_ERROR;
+		vo = (int)strtol(param, 0, 0);
+
+		if ((be | bk | vi | vo) & ~1) {
+			printf("%s: Invalid parameter\n", cmd->name);
+			return BCME_BADARG;
+		}
+
+		dp = (be << AC_BE) | (bk << AC_BK) | (vi << AC_VI) | (vo << AC_VO);
+
+		dp = htod32(dp);
+		memcpy(&buf[strlen(buf) + 1], &dp, sizeof(dp));
+
+		err = wlu_set(wl, cmd->set, &buf[0], buflen);
+	}
+
+	return err;
+}
+
+/*
+ * Get or Set WME lifetime parameter
+ *	"wl lifetime be|bk|vi|vo [<value>]"},
+ *  with no args, print current values
+ */
+static int
+wl_lifetime(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint8 ac;
+	char *param, *val;
+	const char *cmdname = "lifetime";
+	wl_lifetime_t lifetime, *reply;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	if (strcmp(param, "be") == 0)
+		ac = AC_BE;
+	else if (strcmp(param, "bk") == 0)
+		ac = AC_BK;
+	else if (strcmp(param, "vi") == 0)
+		ac = AC_VI;
+	else if (strcmp(param, "vo") == 0)
+		ac = AC_VO;
+	else {
+		fprintf(stderr, "unexpected param %s\n", param);
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((val = *++argv) == NULL) {
+		lifetime.ac = htod32(ac);
+		if ((err = wlu_var_getbuf(wl, cmdname, &lifetime, sizeof(lifetime),
+		                         &ptr)) < 0)
+			return err;
+		reply = (wl_lifetime_t *) ptr;
+		reply->ac = dtoh32(reply->ac);
+		reply->lifetime = dtoh32(reply->lifetime);
+		printf("Lifetime for access class '%s' is %dms\n", param, reply->lifetime);
+	}
+	else {
+		lifetime.ac = htod32(ac);
+		lifetime.lifetime = htod32((uint)strtol(val, 0, 0));
+		err = wlu_var_setbuf(wl, cmdname, &lifetime, sizeof(lifetime));
+	}
+
+	return err;
+}
+
+#define VNDR_IE_OK_FLAGS \
+	(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG | VNDR_IE_ASSOCRSP_FLAG | \
+	 VNDR_IE_AUTHRSP_FLAG | VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG | \
+	 VNDR_IE_AUTHREQ_FLAG)
+
+static int
+wl_add_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(cmd);
+
+	return (wl_vndr_ie(wl, "add", VNDR_IE_OK_FLAGS, argv));
+}
+
+static int
+wl_del_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(cmd);
+
+	return (wl_vndr_ie(wl, "del", VNDR_IE_OK_FLAGS, argv));
+}
+
+int
+wl_mk_ie_setbuf(const char *command, uint32 pktflag_ok, char **argv,
+	vndr_ie_setbuf_t **buf, int *buf_len)
+{
+	vndr_ie_setbuf_t *ie_setbuf;
+	uint32 pktflag;
+	int ielen, datalen, buflen, iecount;
+	int err = 0;
+
+	if (!argv[1] || !argv[2] || !argv[3]) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	pktflag = (uint)strtol(argv[1], 0, 0);
+
+	if (pktflag & ~pktflag_ok) {
+		fprintf(stderr, "Invalid packet flag 0x%x (%d)\n", pktflag, pktflag);
+		return BCME_BADARG;
+	}
+
+	ielen = atoi(argv[2]);
+	if (ielen > VNDR_IE_MAX_LEN) {
+		fprintf(stderr, "IE length is %d, should be <= %d\n", ielen, VNDR_IE_MAX_LEN);
+		return BCME_BADARG;
+	}
+	else if (ielen < VNDR_IE_MIN_LEN) {
+		fprintf(stderr, "IE length is %d, should be >= %d\n", ielen, VNDR_IE_MIN_LEN);
+		return BCME_BADARG;
+	}
+
+	if (strlen(argv[3]) != OUI_STR_SIZE) {
+		fprintf(stderr, "Invalid OUI length %d\n", (int)strlen(argv[3]));
+		return BCME_BADARG;
+	}
+
+	datalen = ielen - VNDR_IE_MIN_LEN;
+	if (datalen > 0) {
+		if (!argv[4]) {
+			fprintf(stderr, "Data bytes should be specified for IE of length %d\n",
+			        ielen);
+			return BCME_USAGE_ERROR;
+		}
+		else {
+			/* Ensure each data byte is 2 characters long */
+			if ((int)strlen (argv[4]) < (datalen * 2)) {
+				fprintf(stderr, "Please specify all the data bytes for this IE\n");
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	if (datalen == 0 && (argv[4] != NULL))
+		fprintf(stderr, "Ignoring data bytes for IE of length %d", ielen);
+
+	buflen = sizeof(vndr_ie_setbuf_t) + datalen - 1;
+
+	ie_setbuf = (vndr_ie_setbuf_t *) malloc(buflen);
+
+	if (ie_setbuf == NULL) {
+		fprintf(stderr, "memory alloc failure\n");
+		return BCME_NOMEM;
+	}
+
+	/* Copy the vndr_ie SET command ("add"/"del") to the buffer */
+	strncpy(ie_setbuf->cmd, command, VNDR_IE_CMD_LEN - 1);
+	ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+
+	/* Buffer contains only 1 IE */
+	iecount = htod32(1);
+	memcpy((void *)&ie_setbuf->vndr_ie_buffer.iecount, &iecount, sizeof(int));
+
+	/*
+	 * The packet flag bit field indicates the packets that will
+	 * contain this IE
+	 */
+	pktflag = htod32(pktflag);
+	memcpy((void *)&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].pktflag,
+	       &pktflag, sizeof(uint32));
+
+	/* Now, add the IE to the buffer */
+	ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar)DOT11_MNG_VS_ID;
+	ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (uchar) ielen;
+
+	if ((err = get_oui_bytes ((uchar *)argv[3],
+		&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui[0]))) {
+		free(ie_setbuf);
+		fprintf(stderr, "Error parsing OUI arg\n");
+		return BCME_BADARG;
+	}
+
+	if (datalen > 0) {
+		if ((err = get_ie_data ((uchar *)argv[4],
+			&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data[0],
+			datalen))) {
+			free(ie_setbuf);
+			fprintf(stderr, "Error parsing data arg\n");
+			return BCME_BADARG;
+		}
+	}
+
+	/* Copy-out */
+	if (buf) {
+		*buf = ie_setbuf;
+		ie_setbuf = NULL;
+	}
+	if (buf_len)
+		*buf_len = buflen;
+
+	/* Clean-up */
+	if (ie_setbuf)
+		free(ie_setbuf);
+
+	return (err);
+}
+
+static int
+wl_vndr_ie(void *wl, const char *command, uint32 pktflag_ok, char **argv)
+{
+	vndr_ie_setbuf_t *ie_setbuf;
+	int buflen;
+	int err = 0;
+	int ret;
+	int bsscfg_idx = 0;
+	int consumed = 0;
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv + 1, argv[0], &bsscfg_idx, &consumed)) != 0)
+		return ret;
+	if (consumed)
+		argv = argv + consumed;
+	else
+		bsscfg_idx = -1;
+
+	if ((err = wl_mk_ie_setbuf(command, pktflag_ok, argv, &ie_setbuf, &buflen)) != 0)
+		return err;
+
+	if (bsscfg_idx == -1)
+		err = wlu_var_setbuf(wl, "vndr_ie", ie_setbuf, buflen);
+	else
+		err = wlu_bssiovar_setbuf(wl, "vndr_ie", bsscfg_idx,
+			ie_setbuf, buflen, buf, WLC_IOCTL_MAXLEN);
+
+	free(ie_setbuf);
+
+	return (err);
+}
+
+int
+wl_list_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	void *ptr;
+	ie_getbuf_t param;
+
+	BCM_REFERENCE(argv);
+
+	param.pktflag = (uint32) -1;
+	param.id = (uint8)DOT11_MNG_VS_ID;
+	err = wlu_var_getbuf(wl, cmd->name, &param, sizeof(param), &ptr);
+	if (err == 0) {
+		wl_dump_ie_buf((vndr_ie_buf_t *)ptr);
+	} else {
+		fprintf(stderr, "Error %d getting IOVar\n", err);
+	}
+
+	return err;
+}
+
+static int
+_wl_list_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	const char *old = cmd->name;
+
+	cmd->name = "vndr_ie";
+	err = wl_list_ie(wl, cmd, argv);
+	cmd->name = old;
+
+	return err;
+}
+
+static void
+wl_dump_ie_buf(vndr_ie_buf_t *ie_getbuf)
+{
+	uchar *iebuf;
+	uchar *data;
+	int tot_ie, pktflag, iecount, count, datalen, col;
+	vndr_ie_info_t *ie_info;
+	vndr_ie_t *ie;
+
+	memcpy(&tot_ie, (void *)&ie_getbuf->iecount, sizeof(int));
+	tot_ie = dtoh32(tot_ie);
+	printf("Total IEs %d\n", tot_ie);
+
+	iebuf = (uchar *)&ie_getbuf->vndr_ie_list[0];
+
+	for (iecount = 0; iecount < tot_ie; iecount++) {
+		ie_info = (vndr_ie_info_t *) iebuf;
+		memcpy(&pktflag, (void *)&ie_info->pktflag, sizeof(uint32));
+		pktflag = dtoh32(pktflag);
+		iebuf += sizeof(uint32);
+
+		printf("\n");
+
+		ie = &ie_info->vndr_ie_data;
+		printf("IE index = %d\n", iecount);
+		printf("-----------------\n");
+		printf("Pkt Flg = 0x%x\n", pktflag);
+		printf("Length  = %d\n", ie->len);
+		printf("OUI     = %02x:%02x:%02x\n",
+			ie->oui[0], ie->oui[1], ie->oui[2]);
+		printf("Data:\n");
+
+		data = &ie->data[0];
+		datalen = ie->len - VNDR_IE_MIN_LEN;
+		for (count = 0; (count < datalen);) {
+			for (col = 0; (col < MAX_DATA_COLS) &&
+				(count < datalen); col++, count++) {
+				printf("%02x ", *data++);
+			}
+			printf("\n");
+		}
+
+		iebuf += ie->len + VNDR_IE_HDR_LEN;
+	}
+}
+
+static int
+wl_rand(void *wl, cmd_t *cmd, char **argv)
+{
+	char *randbuf;
+	uint16 randnum;
+	int err;
+	void *ptr;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	randbuf = (char *)ptr;
+	memcpy(&randnum, randbuf, sizeof(uint16));
+	printf("%d\n", randnum);
+
+	return (0);
+}
+
+static int
+wl_wlc_ver(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int err;
+	wl_wlc_version_t *ver;
+	char buf[256];
+
+	UNUSED_PARAMETER(argv);
+
+	/* skip the command name */
+	argv++;
+
+	/* validate absence of arguments */
+	if (*argv) {
+		fprintf(stderr,
+			"\"%s\" wlc_ver iovar doesn't take any arguments\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((err = wlu_var_getbuf_sm(wl, cmd->name, NULL, 0, &ptr))) {
+		return err;
+	}
+
+	ver = (wl_wlc_version_t *)ptr;
+	sprintf(buf, "wlc_ver %d.%d\n" "epi_ver %d.%d.%d.%d\n",
+		ver->wlc_ver_major, ver->wlc_ver_minor, ver->epi_ver_major,
+		ver->epi_ver_minor, ver->epi_rc_num, ver->epi_incr_num);
+
+	fputs(buf, stdout);
+
+	return 0;
+}
+
+static int
+wl_wme_counters(void *wl, cmd_t *cmd, char **argv)
+{
+	char *statsbuf;
+	wl_wme_cnt_t cnt;
+	int err;
+	void *ptr;
+	char *pbuf = buf;
+	uint ac;
+	int ap_mode = 0;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf_sm (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	statsbuf = (char *)ptr;
+	memcpy(&cnt, statsbuf, sizeof(cnt));
+	cnt.version = dtoh16(cnt.version);
+	cnt.length = dtoh16(cnt.length);
+
+	if (cnt.version != WL_WME_CNT_VERSION) {
+		printf("\tIncorrect version of counters struct: expected %d; got %d\n",
+			WL_WME_CNT_VERSION, cnt.version);
+		return -1;
+	}
+
+	if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))) < 0) {
+		return err;
+	}
+	ap_mode = dtoh32(ap_mode);
+
+	/* summary stat counter line */
+	for (ac = AC_BE; ac < AC_COUNT; ac++) {
+		pbuf += sprintf(pbuf, "\n%s: tx frames: %u bytes: %u failed frames: %u "
+		                "failed bytes: %u\n",
+		                ac_names[ac], dtoh32(cnt.tx[ac].packets), dtoh32(cnt.tx[ac].bytes),
+		                dtoh32(cnt.tx_failed[ac].packets), dtoh32(cnt.tx_failed[ac].bytes));
+		pbuf += sprintf(pbuf, "       rx frames: %u bytes: %u failed frames: %u "
+		                "failed bytes: %u\n", dtoh32(cnt.rx[ac].packets),
+		                dtoh32(cnt.rx[ac].bytes), dtoh32(cnt.rx_failed[ac].packets),
+		                dtoh32(cnt.rx_failed[ac].bytes));
+
+		if (ap_mode)
+			pbuf += sprintf(pbuf, "       foward frames: %u bytes: %u \n",
+			                dtoh32(cnt.forward[ac].packets),
+			                dtoh32(cnt.forward[ac].bytes));
+
+		pbuf += sprintf(pbuf, "       tx frames time expired: %u \n",
+		                dtoh32(cnt.tx_expired[ac].packets));
+	}
+	pbuf += sprintf(pbuf, "\n");
+	fputs(buf, stdout);
+	return (0);
+}
+
+int
+get_oui_bytes(uchar *oui_str, uchar *oui)
+{
+	int idx;
+	uchar val;
+	uchar *src, *dest;
+	char hexstr[3];
+
+	src = oui_str;
+	dest = oui;
+
+	for (idx = 0; idx < MAX_OUI_SIZE; idx++) {
+		hexstr[0] = src[0];
+		hexstr[1] = src[1];
+		hexstr[2] = '\0';
+
+		val = (uchar) strtoul(hexstr, NULL, 16);
+
+		*dest++ = val;
+		src += 2;
+
+		if ((idx < (MAX_OUI_SIZE - 1)) && (*src++ != ':'))
+			return -1;
+	}
+
+	return 0;
+}
+
+int
+get_ie_data(uchar *data_str, uchar *ie_data, int len)
+{
+	uchar *src, *dest;
+	uchar val;
+	int idx;
+	char hexstr[3];
+
+	src = data_str;
+	dest = ie_data;
+
+	for (idx = 0; idx < len; idx++) {
+		hexstr[0] = src[0];
+		hexstr[1] = src[1];
+		hexstr[2] = '\0';
+
+		val = (uchar) strtoul(hexstr, NULL, 16);
+
+		*dest++ = val;
+		src += 2;
+	}
+
+	return 0;
+}
+
+int
+hexstrtobitvec(const char *cp, uchar *bitvec, int veclen)
+{
+	uchar value = 0;
+	int nibble;		/* index of current hex-format nibble to process */
+	int even;		/* 1 if even number of nibbles, 0 if odd number */
+	int i = 0;
+
+	if (cp[0] == '0' && cp[1] == 'x')
+		cp += 2;
+
+	memset(bitvec, '\0', veclen);
+	nibble = strlen(cp);
+	if (!nibble)
+		return -1;
+	even = ((nibble % 2) == 0);
+
+	/* convert from right to left (lsb is rightmost byte) */
+	--nibble;
+	while (nibble >= 0 && i < veclen && (isxdigit((int)cp[nibble]) &&
+		(value = isdigit((int)cp[nibble]) ? cp[nibble]-'0' :
+		(islower((int)cp[nibble]) ? toupper((int)cp[nibble]) : cp[nibble])-'A'+10) < 16)) {
+		if (even == ((nibble+1) % 2)) {
+			bitvec[i] += value*16;
+			++i;
+		} else
+			bitvec[i] = value;
+		--nibble;
+	}
+
+	return ((nibble == -1 && i <= veclen) ? 0 : -1);
+}
+
+#define WL_EVENTING_MASK_MAX_LEN	64
+#define WL_EVENTINT_MAX_GET_SIZE	(WL_EVENTING_MASK_MAX_LEN + EVENTMSGS_EXT_STRUCT_SIZE)
+
+static int
+wl_bitvecext(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, bcmerr;
+	eventmsgs_ext_t *eventmask_msg;
+	uint8 masksize;
+	err = 0;
+
+	bcmerr = 1;
+
+	/* set */
+	if (argv[1]) {
+		uint8 send_iovar_datasize;
+		/* send user mask size up to WL_EVENTING_MASK_MAX_LEN */
+		masksize = MIN((strlen(argv[1])/2), WL_EVENTING_MASK_MAX_LEN);
+		send_iovar_datasize = masksize + EVENTMSGS_EXT_STRUCT_SIZE;
+		eventmask_msg = (eventmsgs_ext_t*)malloc(send_iovar_datasize);
+		if (eventmask_msg == NULL) {
+			fprintf(stderr, "fail to allocate event_msgs"
+				"structure of %d bytes\n", send_iovar_datasize);
+			return BCME_NOMEM;
+		}
+		memset((void*)eventmask_msg, 0, send_iovar_datasize);
+		eventmask_msg->len = masksize;
+		eventmask_msg->command = EVENTMSGS_SET_MASK;
+		eventmask_msg->ver = EVENTMSGS_VER;
+		if (!(err = hexstrtobitvec(argv[1], eventmask_msg->mask, eventmask_msg->len))) {
+			err = wlu_var_setbuf(wl, cmd->name, (void*)eventmask_msg,
+				send_iovar_datasize);
+			if (err) {
+				int getint_error = 0;
+				getint_error = wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+				if ((!getint_error) && (bcmerr == BCME_UNSUPPORTED)) {
+					uchar bitvec[WL_EVENTING_MASK_LEN];
+					printf("old firmware support only 128 events"
+						"setting only the first 128 events\n");
+					memset(bitvec, '\0', WL_EVENTING_MASK_LEN);
+					if (!(err = hexstrtobitvec(argv[1], bitvec,
+						WL_EVENTING_MASK_LEN)))
+							err = wlu_var_setbuf(wl, "event_msgs",
+								bitvec, WL_EVENTING_MASK_LEN);
+				}
+			}
+		}
+		else {
+			fprintf(stderr, "Invalid mask %d\n", eventmask_msg->len);
+		}
+	}
+	/* get */
+	else {
+		void *ptr;
+		char *mask;
+		int i;
+		bool skipzeros;
+		eventmsgs_ext_t *eventmask_msg_in;
+
+		skipzeros = TRUE;
+		/* input structure have no mask */
+		eventmask_msg = (eventmsgs_ext_t*)malloc(EVENTMSGS_EXT_STRUCT_SIZE);
+		if (eventmask_msg == NULL) {
+			return BCME_NOMEM;
+		}
+		memset((void*)eventmask_msg, 0,	EVENTMSGS_EXT_STRUCT_SIZE);
+		/* command only used for set */
+		eventmask_msg->command = EVENTMSGS_NONE;
+		/* max read mask size is WL_EVENTING_MASK_MAX_LEN */
+		eventmask_msg->len = WL_EVENTING_MASK_MAX_LEN;
+		eventmask_msg->ver = EVENTMSGS_VER;
+		memset(buf, '\0', WL_EVENTINT_MAX_GET_SIZE);
+		if (!(err = wlu_var_getbuf_sm(wl, cmd->name, (void*)eventmask_msg,
+			EVENTMSGS_EXT_STRUCT_SIZE, &ptr))) {
+				eventmask_msg_in = (eventmsgs_ext_t*)ptr;
+				mask = (char *)eventmask_msg_in->mask;
+				masksize = eventmask_msg_in->len;
+		}
+		if (err) {
+			int getint_error = 0;
+			getint_error = wlu_iovar_getint(wl, "bcmerror", &bcmerr);
+			if ((!getint_error) && (bcmerr == BCME_UNSUPPORTED)) {
+				printf("old firmware support only 128 events"
+					"getting only the first 128 events\n");
+				if (!(err = wlu_var_getbuf_sm(wl, "event_msgs", NULL, 0, &ptr))) {
+					mask = (char *)ptr;
+					masksize = WL_EVENTING_MASK_LEN;
+				}
+			}
+		}
+		if (!err) {
+			printf("0x");
+			for (i = masksize - 1; i >= 0; i--) {
+				if (mask[i] || (i == 0))
+					skipzeros = FALSE;
+				if (skipzeros)
+					continue;
+				printf("%02x", mask[i] & 0xff);
+			}
+			printf("\n");
+		}
+	}
+	free(eventmask_msg);
+	return (err);
+}
+
+static int
+wl_eventbitvec(void *wl, cmd_t *cmd, char **argv)
+{
+	char *vbuf;
+	int err;
+	uchar bitvec[WL_EVENTING_MASK_LEN];
+	bool skipzeros;
+	int i;
+
+	err = 0;
+	skipzeros = TRUE;
+
+	/* set */
+	if (argv[1]) {
+		memset(bitvec, '\0', sizeof(bitvec));
+		if (!(err = hexstrtobitvec(argv[1], bitvec, sizeof(bitvec))))
+			err = wlu_var_setbuf(wl, cmd->name, bitvec, sizeof(bitvec));
+		else
+			return BCME_BADARG;
+	}
+	/* get */
+	else {
+		void *ptr;
+
+		memset(buf, '\0', WLC_IOCTL_MAXLEN);
+		if (!(err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr))) {
+			vbuf = (char *)ptr;
+			printf("0x");
+			for (i = (sizeof(bitvec) - 1); i >= 0; i--) {
+				if (vbuf[i] || (i == 0))
+					skipzeros = FALSE;
+				if (skipzeros)
+					continue;
+				printf("%02x", vbuf[i] & 0xff);
+			}
+			printf("\n");
+		}
+	}
+
+	return (err);
+}
+
+static int
+wl_auto_channel_sel(void *wl, cmd_t *cmd, char **argv)
+{
+	/*
+	* The following condition(s) must be met when Auto Channel Selection
+	* is enabled.
+	*  - the I/F is up (change radio channel requires it is up?)
+	*  - the AP must not be associated (setting SSID to empty should
+	*    make sure it for us)
+	*/
+	int chosen = 0;
+	wl_uint32_list_t request;
+	int ret = 0;
+
+	if (!*++argv) {
+		ret = wlu_get(wl, cmd->get, &chosen, sizeof(chosen));
+		chosen = wl_chspec32_from_driver(chosen);
+		if (ret >= 0 && chosen != 0) {
+			wf_chspec_ntoa((chanspec_t)chosen, buf);
+			printf("%s (0x%x)\n", buf, chosen);
+			return 0;
+		}
+		else {
+			if (chosen == 0)
+				printf("invalid chanspec (0x%x)\n", chosen);
+		}
+	} else {
+		if (atoi(*argv) == 1) {
+			request.count = htod32(0);
+			ret = wlu_set(wl, cmd->set, &request, sizeof(request));
+		} else if (atoi(*argv) == 2) {
+			ret = wlu_get(wl, cmd->get, &chosen, sizeof(chosen));
+			if (ret >= 0 && chosen != 0)
+				ret = wlu_iovar_setint(wl, "chanspec", (int)chosen);
+		} else {
+			ret = BCME_BADARG;
+		}
+	}
+	return ret;
+}
+
+static int
+wl_varstr(void *wl, cmd_t *cmd, char **argv)
+{
+	int error;
+	char *str;
+
+	if (!*++argv) {
+		void *ptr;
+
+		if ((error = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return (error);
+
+		str = (char *)ptr;
+		printf("%s\n", str);
+		return (0);
+	} else {
+		str = *argv;
+		/* str length include NULL */
+		return wlu_var_setbuf(wl, cmd->name, str, (strlen(str)+1));
+	}
+}
+
+/* Return TRUE if it's one of the wc cmds. If WC_TOOL is not defined,
+ * it'll return TRUE by default so all the commands are allowed.
+ */
+bool wc_cmd_check(const char *cmd_name)
+{
+	uint j;
+	if (wc_cmds == NULL)
+		return TRUE;
+
+	for (j = 0; j < ARRAYSIZE(wc_cmds); j++)
+		if (strcmp(wc_cmds[j], cmd_name) == 0)
+			return TRUE;
+	return FALSE;
+}
+
+
+/* get/set max bandwidth for each access category in ap */
+static int
+wme_maxbw_params(void *wl, cmd_t *cmd, char **argv)
+{
+	wme_max_bandwidth_t cur_params, new_params;
+	char *val_p, *ac_str, *param;
+	int buflen;
+	int aci;
+	int err;
+	int val;
+	int ap_mode = 0;
+
+	argv++;
+
+	if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))) < 0)
+		return err;
+
+	if (!ap_mode) {
+		printf("%s: AP only\n", cmd->name);
+		return -1;
+	}
+
+	buflen = WLC_IOCTL_MAXLEN;
+
+	/* get the current max bandwidth, using buf as an input buffer. */
+	strcpy(buf, "wme_maxbw_params");
+	if ((err = wlu_get(wl, WLC_GET_VAR, &buf[0], buflen)) < 0) {
+		return err;
+	}
+
+	/* cache the current values */
+	memcpy(&cur_params, buf, sizeof(wme_max_bandwidth_t));
+
+	if ((ac_str = *argv) == NULL) {
+		printf("WME bandwidth limit: \n");
+		for (aci = 0; aci < AC_COUNT; aci++) {
+			printf("%s: bandwidth limit %d\n", ac_names[aci],
+				cur_params.ac[aci]);
+		}
+	} else {
+		/* preload new values with current values */
+		memcpy(&new_params, &cur_params, sizeof(new_params));
+		while ((param = *argv++) != NULL) {
+			if ((val_p = *argv++) == NULL) {
+				printf("Need value following %s\n", param);
+				return BCME_USAGE_ERROR;
+			}
+
+			val = (int)strtoul(val_p, NULL, 0);
+
+			if (!strcmp(param, "be")) {
+				new_params.ac[AC_BE] = (uint32)val;
+			} else if (!strcmp(param, "bk")) {
+				new_params.ac[AC_BK] = (uint32)val;
+			} else if (!strcmp(param, "vi")) {
+				new_params.ac[AC_VI] = (uint32)val;
+			} else if (!strcmp(param, "vo")) {
+				new_params.ac[AC_VO] = (uint32)val;
+			} else {
+				printf("Unknown access category: %s\n", param);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		strcpy(buf, "wme_maxbw_params");
+		memcpy(buf + strlen(buf) + 1, &new_params, sizeof(wme_max_bandwidth_t));
+		err = wlu_set(wl, WLC_SET_VAR, &buf[0], buflen);
+
+	}
+
+	return err;
+}
+
+static int
+wl_antsel(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *ant_sel = "fixed";
+	char *val_name;
+	wlc_antselcfg_t val = {{0}, 0};
+	int err, argc, i;
+	char *endptr = NULL;
+	uint32 txchain_bitmap = 0;
+	uint16 antsel_mask = 0;
+
+	/* toss the command name */
+	val_name = *argv++;
+
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+	    if ((err = wlu_iovar_get(wl, "txchain", &txchain_bitmap, sizeof(txchain_bitmap))) < 0)
+				return err;
+
+		/* iterate over max 4 chains */
+		for (i = 0; i < 4; i ++) {
+			if (!(txchain_bitmap & (1<<i)))
+				antsel_mask |=  (0xF << i * 4);
+		}
+
+		if ((err = wlu_iovar_get(wl, val_name, &val, sizeof(wlc_antselcfg_t))) < 0)
+			return err;
+
+		printf("C3C2C1C0: ");
+		for (i = ANT_SELCFG_TX_UNICAST; i < ANT_SELCFG_MAX; i++) {
+			if (val.ant_config[i] & ANT_SELCFG_AUTO)
+				ant_sel = "auto";
+			printf("0x%04X %s ",
+			antsel_mask | (val.ant_config[i] & ANT_SELCFG_MASK), ant_sel);
+		}
+		printf("\n");
+	} else {
+		/* arg count */
+		for (argc = 0; argv[argc]; argc++);
+
+		if ((argc >= 2 && argc <= 3) || argc > ANT_SELCFG_MAX) {
+			printf("invalid %d args\n", argc);
+			return BCME_USAGE_ERROR;
+		}
+
+		val.ant_config[ANT_SELCFG_TX_UNICAST] = (uint8)strtol(*argv++, &endptr, 0);
+		printf("UTX 0x%02x\n", val.ant_config[ANT_SELCFG_TX_UNICAST]);
+		if (*endptr != '\0') {
+			printf("Invaild UTX parameter: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		if (argc == 1) {
+			val.ant_config[ANT_SELCFG_RX_UNICAST] =
+				val.ant_config[ANT_SELCFG_TX_UNICAST];
+			val.ant_config[ANT_SELCFG_TX_DEF] = val.ant_config[ANT_SELCFG_TX_UNICAST];
+			val.ant_config[ANT_SELCFG_RX_DEF] = val.ant_config[ANT_SELCFG_TX_UNICAST];
+		} else {
+			val.ant_config[ANT_SELCFG_RX_UNICAST] = (uint8)strtol(*argv++, &endptr, 0);
+			printf("URX 0x%02x\n", val.ant_config[ANT_SELCFG_RX_UNICAST]);
+			if (*endptr != '\0') {
+				printf("Invaild URX parameter: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+			val.ant_config[ANT_SELCFG_TX_DEF] = (uint8)strtol(*argv++, &endptr, 0);
+			printf("DTX 0x%02x\n", val.ant_config[ANT_SELCFG_TX_DEF]);
+			if (*endptr != '\0') {
+				printf("Invaild DTX parameter: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+			val.ant_config[ANT_SELCFG_RX_DEF] = (uint8)strtol(*argv++, &endptr, 0);
+			printf("DRX 0x%02x\n", val.ant_config[ANT_SELCFG_RX_DEF]);
+			if (*endptr != '\0') {
+				printf("Invaild DRX parameter: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+		}
+		err = wlu_iovar_set(wl, val_name, &val, sizeof(wlc_antselcfg_t));
+	}
+	return err;
+}
+
+
+static int
+wl_txfifo_sz(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "txfifo_sz";
+	wl_txfifo_sz_t ts, *reply;
+	uint fifo;
+	int err;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	fifo = atoi(param);
+	if (fifo > NFIFO)
+		return BCME_USAGE_ERROR;
+	ts.fifo = fifo;
+	ts.magic = WL_TXFIFO_SZ_MAGIC;
+
+	if ((param = *++argv)) {
+		ts.size = atoi(param);
+		err = wlu_var_setbuf(wl, cmdname, &ts, sizeof(ts));
+	} else {
+		if ((err = wlu_var_getbuf_sm(wl, cmdname, &ts, sizeof(ts), &ptr) < 0))
+			return err;
+		reply = (wl_txfifo_sz_t *)ptr;
+		printf("fifo %d size %d\n", fifo, reply->size);
+	}
+	return err;
+}
+
+#ifdef linux
+
+static int
+wl_escan_event_check(void *wl, cmd_t *cmd, char **argv)
+{
+	int					fd, err, i, octets;
+	struct sockaddr_ll	sll;
+	struct ifreq		ifr;
+	char				ifnames[IFNAMSIZ] = {"eth1"};
+	uint8               print_flag = 4;
+	bcm_event_t			* event;
+	uint32              status;
+	char*				data;
+	int					event_type;
+	uint8	event_inds_mask[WL_EVENTING_MASK_LEN];	/* event bit mask */
+
+	wl_escan_result_t* escan_data;
+
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		if (strlen(*argv) >= IFNAMSIZ) {
+			printf("Interface name %s too long\n", *argv);
+			return -1;
+		}
+		strncpy(ifnames, *argv, (IFNAMSIZ - 1));
+		if (*++argv)
+			print_flag = atoi(*argv);
+	} else {
+		strncpy(ifnames, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+
+	memset(event_inds_mask, '\0', WL_EVENTING_MASK_LEN);
+
+	if ((err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		return (err);
+	event_inds_mask[WLC_E_ESCAN_RESULT / 8] |= 1 << (WLC_E_ESCAN_RESULT % 8);
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		return (err);
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		return -1;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		close(fd);
+		return -1;
+	}
+
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		close(fd);
+		return -1;
+	}
+
+	data = (char*)malloc(ESCAN_EVENTS_BUFFER_SIZE);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			ESCAN_EVENTS_BUFFER_SIZE);
+		close(fd);
+		return BCME_NOMEM;
+	}
+
+	while (1) {
+		octets = recv(fd, data, ESCAN_EVENTS_BUFFER_SIZE, 0);
+		event = (bcm_event_t *)data;
+
+		event_type = ntoh32(event->event.event_type);
+
+		if ((event_type == WLC_E_ESCAN_RESULT) && (octets > 0)) {
+			escan_data = (wl_escan_result_t*)&data[sizeof(bcm_event_t)];
+			status = ntoh32(event->event.status);
+
+			if (print_flag & 1)
+				printf("WLC_E_ESCAN_RESULT, (sync_id,status) = (%d,%d)\n",
+				escan_data->sync_id, status);
+
+			if (print_flag & 2)
+				for (i = 0; i < escan_data->bss_count; i++)
+					dump_bss_info(&escan_data->bss_info[i]);
+
+			if (print_flag & 4) {
+				if (status == WLC_E_STATUS_PARTIAL) {
+					printf("sync_id: %d, WLC_E_STATUS_PARTIAL\n",
+					escan_data->sync_id);
+					for (i = 0; i < escan_data->bss_count; i++)
+						dump_bss_info(&escan_data->bss_info[i]);
+				}
+				if (status == WLC_E_STATUS_SUCCESS)
+					printf("sync_id: %d, WLC_E_STATUS_SUCCESS => SCAN_DONE\n",
+					escan_data->sync_id);
+				if ((status != WLC_E_STATUS_SUCCESS) &&
+					(status != WLC_E_STATUS_PARTIAL))
+					printf("sync_id: %d, status:%d, misc. error/abort\n",
+					escan_data->sync_id, status);
+			}
+
+			if (print_flag & 8) {
+				int    remainder = escan_data->bss_info[0].ie_length;
+				int    processed = sizeof(wl_escan_result_t);
+				uint8* iebuf = &((uint8*)escan_data)[sizeof(wl_escan_result_t)];
+
+				if (status != WLC_E_STATUS_PARTIAL)
+					continue;
+
+				printf("MOREINFO: (sync_id,buflen,ielen) = (%d,%d,%d)\n",
+					escan_data->sync_id,
+					escan_data->buflen,
+					escan_data->bss_info[0].ie_length);
+
+				/* do a tlv sanity check */
+				while (remainder > 0) {
+					processed += 1 + 1 + iebuf[1];
+					remainder -= 1 + 1 + iebuf[1];
+					iebuf     += 1 + 1 + iebuf[1];
+				}
+				if (processed >= ESCAN_EVENTS_BUFFER_SIZE)
+					break;
+
+				if (remainder != 0) {
+					printf("ERROR: IE tlv sanity check failed for "
+						"(ssid,sync_id,buflen,ielen,remainder) = "
+						"(%s,%d,%d,%d,%d)\n",
+						escan_data->bss_info[0].SSID,
+						escan_data->sync_id, escan_data->buflen,
+						escan_data->bss_info[0].ie_length,
+						remainder);
+					iebuf = &((uint8*)escan_data)[sizeof(wl_escan_result_t)];
+					if ((escan_data->buflen - sizeof(wl_escan_result_t)) > 0) {
+						for (i = 0;
+						i < (int)(escan_data->buflen -
+							sizeof(wl_escan_result_t));
+						i++) {
+							printf("%02x ", iebuf[i]);
+						}
+						printf("\n");
+					}
+				}
+			}
+		}
+	}
+
+	/* if we ever reach here */
+	free(data);
+	close(fd);
+
+	return (0);
+}
+
+static int
+wl_escanresults(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params)) +
+	    (WL_NUMCHANNELS * sizeof(uint16));
+	wl_escan_params_t *params;
+	int fd, err, octets;
+	int err2 = BCME_OK;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	bcm_event_t *event;
+	uint32 status;
+	char *data;
+	int event_type;
+	uint8 event_inds_mask[WL_EVENTING_MASK_LEN];	/* event bit mask */
+	bool revert_event_bit = FALSE;
+	wl_escan_result_t *escan_data;
+	struct escan_bss *escan_bss_head = NULL;
+	struct escan_bss *escan_bss_tail = NULL;
+	struct escan_bss *result;
+
+	fd_set rfds;
+	struct timeval tv;
+	int retval;
+
+	params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_escan_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	err = wl_scan_prep(wl, cmd, argv, &params->params, &params_size);
+	if (err)
+		goto exit2;
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+
+	memset(event_inds_mask, '\0', WL_EVENTING_MASK_LEN);
+
+	/* Read the event mask from driver and unmask the event WLC_E_ESCAN_RESULT */
+	if ((err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		goto exit2;
+
+	if (isclr(event_inds_mask, WLC_E_ESCAN_RESULT)) {
+		setbit(event_inds_mask, WLC_E_ESCAN_RESULT);
+		if ((err = wlu_iovar_set(wl, "event_msgs",
+		                         &event_inds_mask, WL_EVENTING_MASK_LEN)))
+			goto exit2;
+		revert_event_bit = TRUE;
+	}
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		err = -1;
+		goto exit2;
+	}
+
+	FD_ZERO(&rfds);
+	FD_SET(fd, &rfds);
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		goto exit2fd;
+	}
+
+	/* bind the socket first before starting escan so we won't miss any event */
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		goto exit2fd;
+	}
+
+	params->version = htod32(ESCAN_REQ_VERSION);
+	params->action = htod16(WL_SCAN_ACTION_START);
+
+	srand((unsigned)time(NULL));
+	params->sync_id = htod16(rand() & 0xffff);
+
+	params_size += OFFSETOF(wl_escan_params_t, params);
+	err = wlu_iovar_setbuf(wl, "escan", params, params_size, buf, WLC_IOCTL_MAXLEN);
+	if (err != 0)
+		goto exit2fd;
+
+	data = (char*)malloc(ESCAN_EVENTS_BUFFER_SIZE);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			ESCAN_EVENTS_BUFFER_SIZE);
+		err = BCME_NOMEM;
+		goto exit2fd;
+	}
+
+	/* Set scan timeout */
+	tv.tv_sec = WL_EVENT_TIMEOUT;
+	tv.tv_usec = 0;
+
+	/* receive scan result */
+	while ((retval = select(fd+1, &rfds, NULL, NULL, &tv)) > 0) {
+		octets = recv(fd, data, ESCAN_EVENTS_BUFFER_SIZE, 0);
+		event = (bcm_event_t *)data;
+		event_type = ntoh32(event->event.event_type);
+
+		if ((event_type == WLC_E_ESCAN_RESULT) && (octets > 0)) {
+			escan_data = (wl_escan_result_t*)&data[sizeof(bcm_event_t)];
+			status = ntoh32(event->event.status);
+
+			if (status == WLC_E_STATUS_PARTIAL) {
+				wl_bss_info_t *bi = &escan_data->bss_info[0];
+				wl_bss_info_t *bss;
+
+				/* check if we've received info of same BSSID */
+				for (result = escan_bss_head; result; result = result->next) {
+					bss = result->bss;
+
+					if (wlu_bcmp(bi->BSSID.octet, bss->BSSID.octet,
+						ETHER_ADDR_LEN) ||
+						CHSPEC_BAND(bi->chanspec) !=
+						CHSPEC_BAND(bss->chanspec) ||
+						bi->SSID_len != bss->SSID_len ||
+						wlu_bcmp(bi->SSID, bss->SSID, bi->SSID_len))
+						continue;
+
+					/* We've already got this BSS. Update RSSI if necessary */
+					/* Prefer valid RSSI */
+					if (bi->RSSI == WLC_RSSI_INVALID)
+						break;
+					else if (bss->RSSI == WLC_RSSI_INVALID)
+						goto escan_update;
+
+					/* Prefer on-channel RSSI */
+					if (!(bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
+					     (bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL))
+						break;
+					else if ((bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
+						!(bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL))
+						goto escan_update;
+
+					/* Prefer probe response RSSI */
+					if ((bi->flags & WL_BSS_FLAGS_FROM_BEACON) &&
+					    !(bss->flags & WL_BSS_FLAGS_FROM_BEACON))
+						break;
+					else if (!(bi->flags & WL_BSS_FLAGS_FROM_BEACON) &&
+					          (bss->flags & WL_BSS_FLAGS_FROM_BEACON))
+						goto escan_update;
+
+					/* Prefer better RSSI */
+					if (bi->RSSI <= bss->RSSI)
+						break;
+
+escan_update:				/* Update known entry */
+					bss->RSSI = bi->RSSI;
+					bss->SNR = bi->SNR;
+					bss->phy_noise = bi->phy_noise;
+					bss->flags = bi->flags;
+					break;
+				}
+
+				if (!result) {
+					/* New BSS. Allocate memory and save it */
+					struct escan_bss *ebss = malloc(
+						OFFSETOF(struct escan_bss, bss)	+ bi->length);
+
+					if (!ebss) {
+						perror("can't allocate memory for bss");
+						goto exit1;
+					}
+
+					ebss->next = NULL;
+					memcpy(&ebss->bss, bi, bi->length);
+					if (escan_bss_tail) {
+						escan_bss_tail->next = ebss;
+					}
+					else {
+						escan_bss_head = ebss;
+					}
+					escan_bss_tail = ebss;
+				}
+			}
+			else if (status == WLC_E_STATUS_SUCCESS) {
+				/* Escan finished. Let's go dump the results. */
+				break;
+			}
+			else {
+				printf("sync_id: %d, status:%d, misc. error/abort\n",
+					escan_data->sync_id, status);
+				goto exit1;
+			}
+		}
+	}
+
+	if (retval > 0) {
+		/* print scan results */
+		for (result = escan_bss_head; result; result = result->next) {
+			dump_bss_info(result->bss);
+		}
+	} else if (retval == 0) {
+		printf(" Scan timeout! \n");
+	} else {
+		printf(" Receive scan results failed!\n");
+	}
+
+exit1:
+	/* free scan results */
+	result = escan_bss_head;
+	while (result) {
+		struct escan_bss *tmp = result->next;
+		free(result);
+		result = tmp;
+	}
+
+	free(data);
+exit2fd:
+	close(fd);
+exit2:
+	free(params);
+
+	/* Revert the event bit if appropriate */
+	if (revert_event_bit &&
+	    !(err2 = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN))) {
+		clrbit(event_inds_mask, WLC_E_ESCAN_RESULT);
+		err2 = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN);
+	}
+
+	if (err2) {
+		fprintf(stderr, "Failed to revert event mask, error %d\n", err2);
+	}
+	return err ? err : err2;
+}
+
+/*
+* Description:
+* Primary job of this routine is to open a socket and listening
+* on this socket for BRCM events and display it on console
+*/
+
+#define WL_EVENTS_BUFFER_SIZE 2048
+static int
+wl_event_check(void *wl, cmd_t *cmd, char **argv)
+{
+	int fd, err, octets;
+	struct sockaddr_ll	sll;
+	struct ifreq		ifr;
+	char ifnames[IFNAMSIZ] = {"eth1"};
+	bcm_event_t * event;
+	uint32 status;
+	char* data;
+	uint event_type;
+	char time_str[TIME_STR_SZ];
+	struct tm  ts;
+	struct timespec tspec;
+	uint policy;
+	pid_t pid;
+	struct sched_param sp;
+	uint max;
+	uint ret;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		if (strlen(*argv) >= IFNAMSIZ) {
+			printf("Interface name %s too long\n", *argv);
+			return -1;
+		}
+		strncpy(ifnames, *argv, (IFNAMSIZ - 1));
+	} else if (wl) {
+		strncpy(ifnames, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		return -1;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		close(fd);
+		return -1;
+	}
+
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		close(fd);
+		return -1;
+	}
+
+	data = (char*)malloc(WL_EVENTS_BUFFER_SIZE);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			ESCAN_EVENTS_BUFFER_SIZE);
+		close(fd);
+		return BCME_NOMEM;
+	}
+	/* make this process as rtprocess with highest priority */
+
+	/* get our scheduling policy */
+	pid = getpid();
+	policy = sched_getscheduler(pid);
+	switch (policy) {
+	case SCHED_OTHER:
+	{
+		max = sched_get_priority_max(SCHED_RR);
+		sp.sched_priority = max;
+		/* set the process scheduling also to RR */
+		sched_setscheduler(pid, SCHED_RR, &sp);
+		break;
+	}
+	case SCHED_RR:
+	{
+		max = sched_get_priority_max(SCHED_RR);
+		sp.sched_priority = max;
+		/* set the priority to max */
+		sched_setparam(pid, &sp);
+	break;
+	}
+	case SCHED_FIFO:
+	{
+		max = sched_get_priority_max(SCHED_RR);
+		sp.sched_priority = max;
+		sched_setscheduler(pid, SCHED_RR, &sp);
+		break;
+	}
+	case -1:
+		perror("sched_getscheduler fail!!");
+		break;
+	default:
+		printf("Unknown policy:%u!!Will not change policy to max!!\n", policy);
+		break;
+	}
+
+	while (1) {
+		octets = recv(fd, data, WL_EVENTS_BUFFER_SIZE, 0);
+		UNUSED_PARAMETER(octets);
+		event = (bcm_event_t *)data;
+		event_type = ntoh32(event->event.event_type);
+		/* get the  RTC  time in sec/usec */
+		ret = clock_gettime(CLOCK_REALTIME, &tspec);
+		if (ret) {
+			printf("clock_gettime error:%d\n", ret);
+			free(data);
+			close(fd);
+			return -1;
+		}
+		/* convert it in year-month-day-hour-min-sec */
+		ts = *localtime(&tspec.tv_sec);
+		strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &ts);
+		/* print first line of events */
+		printf("%s:%09d %-8.16s %d:%s:", time_str, (uint)tspec.tv_nsec, ifnames,
+			event_type, wlu_lookup_name(wlc_event_names,
+			event_type));
+
+		/* event subtype interpretation */
+		switch (event_type)
+		{
+			case WLC_E_SET_SSID:
+			{
+				status = ntoh32(event->event.status);
+				if (status == WLC_E_STATUS_SUCCESS) {
+					uint32 ssid_len = ntoh32(event->event.datalen);
+					char ssid[SSID_FMT_BUF_LEN];
+					wl_format_ssid(ssid, (uint8*)(data+sizeof(bcm_event_t)),
+					ssid_len);
+					printf("SSID->\"%s\"", ssid);
+				}
+				else {
+					printf("SET_SSID_FAIL:%d", status);
+				}
+				break;
+			}
+
+			case WLC_E_JOIN:
+			{
+				status = ntoh32(event->event.status);
+				if (status == WLC_E_STATUS_SUCCESS) {
+					printf("JOIN_SUCCESS:");
+					printf("%02X:%02X:%02X:%02X:%02X:%02X",
+					event->event.addr.octet[0], event->event.addr.octet[1],
+					event->event.addr.octet[2], event->event.addr.octet[3],
+					event->event.addr.octet[4], event->event.addr.octet[5]);
+				}
+				else {
+					printf("JOIN_FAIL:%d", status);
+				}
+				break;
+			}
+			case WLC_E_AUTH:
+			{
+				status = ntoh32(event->event.status);
+				uint32 reason = ntoh32(event->event.reason);
+				if (status == WLC_E_STATUS_SUCCESS) {
+					printf("AUTH_REQ_SUCCESS:%d", reason);
+				}
+				else {
+					printf("AUTH_FAIL:%d", status);
+				}
+				break;
+			}
+			case WLC_E_AUTH_IND:
+			{
+				status = ntoh32(event->event.status);
+				uint32 reason = ntoh32(event->event.reason);
+				if (status == WLC_E_STATUS_SUCCESS) {
+					printf("AUTH_IND:%d", reason);
+				}
+				else {
+					printf("AUTH_IND_FAIL:%d", status);
+				}
+				break;
+			}
+			case WLC_E_DEAUTH:
+			{
+				status = ntoh32(event->event.status);
+				uint32 reason = ntoh32(event->event.reason);
+				if (status == WLC_E_STATUS_SUCCESS) {
+					printf("DEAUTH_REQ:%d", reason);
+				}
+				else {
+					printf("DEAUTH_REQ_FAIL:%d", status);
+				}
+				break;
+			}
+			case WLC_E_DEAUTH_IND:
+			{
+				status = ntoh32(event->event.status);
+				uint32 reason = ntoh32(event->event.reason);
+				if (status == WLC_E_STATUS_SUCCESS) {
+					printf("DEAUTH_IND:%d", reason);
+				}
+				else {
+					printf("DEAUTH_IND:%d", status);
+				}
+				break;
+			}
+			case WLC_E_ASSOC:
+			{
+				status = ntoh32(event->event.status);
+				if (status == WLC_E_STATUS_SUCCESS) {
+					printf("ASSOCRESP_SUCCESS");
+				}
+				else {
+					printf("ASSOCRESP_FAIL:%d", status);
+				}
+				break;
+			}
+			case WLC_E_DISASSOC:
+			{
+				status = ntoh32(event->event.status);
+				uint32 reason = ntoh32(event->event.reason);
+				if (status == WLC_E_STATUS_SUCCESS) {
+					printf("DISASSOC_REQ:%d", reason);
+				}
+				else {
+					printf("DISASSOC_REQ_FAIL:%d", status);
+				}
+			break;
+			}
+			case WLC_E_DISASSOC_IND:
+			{
+				status = ntoh32(event->event.status);
+				uint32 reason = ntoh32(event->event.reason);
+				if (status == WLC_E_STATUS_SUCCESS) {
+					printf("DISASSOC_IND:%d", reason);
+				}
+				else {
+					printf("DISASSOC_IND_FAIL:%d", status);
+				}
+				break;
+			}
+			case WLC_E_SCAN_COMPLETE:
+			{
+				status = ntoh32(event->event.status);
+				if (status == WLC_E_STATUS_SUCCESS) {
+					printf("SCAN_SUCCESS");
+				}
+				else {
+					printf("SCAN_FAIL:%d", status);
+				}
+				break;
+			}
+			case WLC_E_LINK:
+			{
+				uint16 flag = ntoh16(event->event.flags);
+				if (flag) {
+					printf("LINK_UP");
+				}
+				else {
+				printf("LINK_DOWN:%d", ntoh32(event->event.reason));
+				}
+				break;
+			}
+			default:
+			printf(" ");
+			break;
+		}
+		printf("\n");
+		fflush(stdout);
+	}
+
+	/* if we ever reach here */
+	free(data);
+	close(fd);
+	return (0);
+}
+
+#endif   /* linux */
+int
+hexstr2hex(char *str)
+{
+	int i, len;
+	char hexstr[3];
+	char *src;
+
+	src = str;
+	len = strlen(str)/2;
+
+	for (i = 0; i < len; i++) {
+		hexstr[0] = src[0];
+		hexstr[1] = src[1];
+		hexstr[2] = '\0';
+		str[i] = strtoul(hexstr, NULL, 16);
+		src += 2;
+	}
+
+	return i;
+}
+
+static int
+wl_hs20_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	int ret;
+	int bsscfg_idx = 0;
+	int consumed = 0;
+	int length;
+	int malloc_size;
+	tlv_t *tlv;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1]) {
+		fprintf(stderr, "Too few arguments\n");
+		return -1;
+	}
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv + 1, argv[0], &bsscfg_idx, &consumed)) != 0)
+		return ret;
+	if (consumed)
+		argv = argv + consumed;
+
+	length = atoi(argv[1]);
+
+	if (length < 0 || length > 255) {
+		fprintf(stderr, "Invalid length\n");
+		return -1;
+	}
+	else if (length > 0) {
+		if (!argv[2]) {
+			fprintf(stderr,
+				"Data bytes should be specified for non-zero length\n");
+			return -1;
+		}
+		else {
+			/* Ensure each data byte is 2 characters long */
+			if ((int)strlen(argv[2]) != (length * 2)) {
+				fprintf(stderr, "Please specify all the data bytes for this IE\n");
+				return -1;
+			}
+		}
+	}
+
+	malloc_size = OFFSETOF(tlv_t, data) + length;
+	tlv = malloc(malloc_size);
+	if (tlv == 0) {
+		fprintf(stderr, "Error allocating %d bytes for IE params\n", malloc_size);
+		return -1;
+	}
+	tlv->id = DOT11_MNG_VS_ID;
+	tlv->len = length;
+
+	if (length > 0) {
+		if ((err = get_ie_data((uchar *)argv[2], tlv->data, length))) {
+			fprintf(stderr, "Error parsing data arg\n");
+			free(tlv);
+			return err;
+		}
+	}
+
+	if (bsscfg_idx == -1)
+		err = wlu_var_setbuf(wl, "hs20_ie", tlv, malloc_size);
+	else
+		err = wlu_bssiovar_setbuf(wl, "hs20_ie", bsscfg_idx,
+			tlv, malloc_size, buf, WLC_IOCTL_MAXLEN);
+
+	free(tlv);
+	return (err);
+}
+
+static dbg_msg_t toe_cmpnt[] = {
+	{TOE_TX_CSUM_OL,	"tx_csum_ol"},
+	{TOE_RX_CSUM_OL,	"rx_csum_ol"},
+	{0,			NULL}
+};
+
+static dbg_msg_t arpoe_cmpnt[] = {
+	{ARP_OL_AGENT,		"agent"},
+	{ARP_OL_SNOOP,		"snoop"},
+	{ARP_OL_HOST_AUTO_REPLY, "host_auto_reply"},
+	{ARP_OL_PEER_AUTO_REPLY, "peer_auto_reply"},
+	{0,			NULL}
+};
+
+/*
+ *  Tcpip Offload Component-wise get/set control.
+ */
+int
+wl_offload_cmpnt(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint val, last_val = 0, cmpnt_add = 0, cmpnt_del = 0;
+	char *endptr;
+	dbg_msg_t *dbg_msg = NULL;
+	void *ptr = NULL;
+	int cmpnt;
+
+	if (strcmp(cmd->name, "toe_ol") == 0)
+		dbg_msg = toe_cmpnt;
+	else if (strcmp(cmd->name, "arp_ol") == 0)
+		dbg_msg = arpoe_cmpnt;
+	else {
+		printf("Not a valid command\n");
+		return BCME_BADARG;
+	}
+
+	if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return (ret);
+	cmpnt = dtoh32(*(int *)ptr);
+
+	if (!*++argv) {
+		printf("0x%x ", cmpnt);
+		for (i = 0; (val = dbg_msg[i].value); i++) {
+			if ((cmpnt & val) && (val != last_val))
+				printf(" %s", dbg_msg[i].string);
+			last_val = val;
+		}
+		printf("\n");
+		return (0);
+	}
+
+	while (*argv) {
+		char *s = *argv;
+		if (*s == '+' || *s == '-')
+			s++;
+		else
+			cmpnt_del = ~0;	/* make the whole list absolute */
+		val = strtoul(s, &endptr, 0);
+		/* not a plain integer if not all the string was parsed by strtoul */
+		if (*endptr != '\0') {
+			for (i = 0; (val = dbg_msg[i].value); i++)
+				if (stricmp(dbg_msg[i].string, s) == 0)
+					break;
+			if (!val)
+				goto usage;
+		}
+		if (**argv == '-')
+			cmpnt_del |= val;
+		else
+			cmpnt_add |= val;
+		++argv;
+	}
+
+	cmpnt &= ~cmpnt_del;
+	cmpnt |= cmpnt_add;
+
+	cmpnt = htod32(cmpnt);
+	return (wlu_var_setbuf(wl, cmd->name, &cmpnt, sizeof(int)));
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+
+	for (i = 0; (val = dbg_msg[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, dbg_msg[i].string);
+		else
+			fprintf(stderr, ", %s", dbg_msg[i].string);
+		last_val = val;
+	}
+	fprintf(stderr, "\n");
+
+	return 0;
+}
+
+#define MAX_HOST_ICMP_IPV6     4
+
+int
+wl_hostipv6_extended(void *wl, cmd_t *cmd, char **argv)
+{
+
+	int ret;
+	uint16 *ip_addr;
+	wl_icmp_ipv6_cfg_t *cfg;
+
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+		uint32 i, k;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		cfg = (wl_icmp_ipv6_cfg_t *)ptr;
+
+		if (cfg->version != WL_ICMP_IPV6_CFG_VERSION) {
+			printf("Version mismatch %d, expected %d\n", cfg->version,
+				WL_ICMP_IPV6_CFG_VERSION);
+			return BCME_VERSION;
+		}
+		/* Check length */
+		if (cfg->length != WL_ICMP_CFG_IPV6_LEN(cfg->num_ipv6)) {
+			printf("Length mismatch %d, calculated length %d\n", cfg->length,
+				(int)WL_ICMP_CFG_IPV6_LEN(cfg->num_ipv6));
+			return BCME_BADARG;
+		}
+		printf("Total %d Host ipv6 addresses\n", cfg->num_ipv6);
+		for (k = 0; k < cfg->num_ipv6; k++) {
+			ip_addr = (uint16*)cfg->host_ipv6[k].addr;
+			/* Print ipv6 Addr */
+			for (i = 0; i < 8; i++) {
+				printf("%x", ntoh16(ip_addr[i]));
+				if (i < 7)
+					printf(":");
+			}
+			printf("\r\n");
+		}
+	} else {
+		int argc, buf_size;
+		struct ipv6_addr ipa_set[MAX_HOST_ICMP_IPV6], null_ipa;
+
+		/* Set */
+		memset(null_ipa.addr, 0, IPV6_ADDR_LEN);
+		for (argc = 0; argc < MAX_HOST_ICMP_IPV6 && argv[argc]; argc++) {
+			if (!wl_atoipv6(argv[argc], &ipa_set[argc]))
+				return BCME_USAGE_ERROR;
+			if (!memcmp(null_ipa.addr, ipa_set->addr, IPV6_ADDR_LEN)) {
+				argc = 0;
+				break;
+			}
+		}
+		buf_size = WL_ICMP_CFG_IPV6_LEN(argc);
+		cfg = (wl_icmp_ipv6_cfg_t *)malloc(buf_size);
+		if (!cfg) {
+			printf("%s: Unable to allocate %d bytes!\n", __FUNCTION__, buf_size);
+			return BCME_NOMEM;
+		}
+		memset(cfg, 0, buf_size);
+		cfg->version = WL_ICMP_IPV6_CFG_VERSION;
+		cfg->fixed_length = WL_ICMP_CFG_IPV6_FIXED_LEN;
+		cfg->length = buf_size;
+		cfg->flags = 0;
+		if (!argc) {
+			cfg->flags |= WL_ICMP_IPV6_CLEAR_ALL;
+		}
+		cfg->num_ipv6 = argc;
+		memcpy(cfg->host_ipv6, ipa_set,
+			cfg->num_ipv6 * sizeof(struct ipv6_addr));
+		ret = wlu_var_setbuf(wl, cmd->name, cfg, buf_size);
+		free(cfg);
+	}
+	return ret;
+}
+
+/*
+ * If a host IP address is given, add it to the host-cache,
+ * e.g. "wl nd_hostip fe00:0:0:0:0:290:1fc0:18c0 ".
+ * If no address is given, dump all the addresses.
+ */
+int
+wl_hostipv6(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	struct ipv6_addr ipa_set, *ipa_get, null_ipa;
+	uint16 *ip_addr;
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		ip_addr = (uint16*)ptr;
+		memset(null_ipa.addr, 0, IPV6_ADDR_LEN);
+		for (ipa_get = (struct ipv6_addr *)ptr;
+			 memcmp(null_ipa.addr, ipa_get->addr, IPV6_ADDR_LEN) != 0;
+			 ipa_get++) {
+			/* Print ipv6 Addr */
+			for (i = 0; i < 8; i++) {
+				printf("%x", ntoh16(ip_addr[i]));
+				if (i < 7)
+					printf(":");
+			}
+			printf("\r\n");
+
+			ip_addr += 8;
+		}
+	} else {
+		/* Add */
+		if (!wl_atoipv6(*argv, &ipa_set))
+			return BCME_USAGE_ERROR;
+
+		/* we add one ip-addr at a time */
+		return wlu_var_setbuf(wl, cmd->name, &ipa_set, IPV6_ADDR_LEN);
+	}
+	return ret;
+}
+
+/*
+ * If a host IP address is given, add it to the host-cache, e.g. "wl arp_hostip 192.168.1.1".
+ * If no address is given, dump all the addresses.
+ */
+int
+wl_hostip(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct ipv4_addr ipa_set, *ipa_get, null_ipa;
+
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		memset(null_ipa.addr, 0, IPV4_ADDR_LEN);
+
+		for (ipa_get = (struct ipv4_addr *)ptr;
+		     memcmp(null_ipa.addr, ipa_get->addr, IPV4_ADDR_LEN) != 0;
+		     ipa_get++)
+			printf("%s\n", wl_iptoa(ipa_get));
+
+		printf("Total %d host addresses\n", (int)(ipa_get - (struct ipv4_addr *)ptr));
+	} else {
+		/* Add */
+		if (!wl_atoip(*argv, &ipa_set))
+			return BCME_USAGE_ERROR;
+		/* we add one ip-addr at a time */
+		return wlu_var_setbuf(wl, cmd->name, &ipa_set, sizeof(IPV4_ADDR_LEN));
+	}
+
+	return ret;
+}
+
+static int
+wl_mcast_ar(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	uint argc;
+	wl_rmc_entry_t *reply = NULL;
+	wl_rmc_entry_t rmc_entry;
+	void *ptr = NULL;
+
+	memset(&rmc_entry, 0, sizeof(wl_rmc_entry_t));
+	if (!*++argv) {
+		/* Get and display activer receiver address */
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0) {
+			return ret;
+		}
+
+		reply = (wl_rmc_entry_t*)ptr;
+
+		printf("%s\n", wl_ether_etoa(&reply->addr));
+		return 0;
+	}
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* Set activer receiver's mac address */
+	if (argc > 0 && argv[0]) {
+		printf(" %s \n", argv[0]);
+		if (!wl_ether_atoe(argv[0], &rmc_entry.addr)) {
+			if (strlen(argv[0]) == 1 && atoi(argv[0]) == 0) {
+				memset(&rmc_entry, 0, sizeof(wl_rmc_entry_t));
+			} else {
+				printf("Invalid argument, Please enter mac address\n"
+					"or enter \"0\" for auto ar selection\n");
+				return -1;
+			}
+		}
+	} else {
+		printf("Too few arguments\n");
+		return -1;
+	}
+
+	ret = wlu_var_setbuf(wl, cmd->name, &rmc_entry, sizeof(wl_rmc_entry_t));
+
+	return ret;
+}
+
+static void
+wl_rate_histo_print(wl_mac_ratehisto_res_t *rate_histo_res)
+{
+	uint i, nss;
+
+	printf("Rates\n");
+	for (i = 0; i < (DOT11_RATE_MAX + 1); i++) {
+		if (rate_histo_res->rate[i]) {
+			if (DIV_REM(i, 2))
+				printf("%.2d\t%d.%d Mbit/s\n",
+					rate_histo_res->rate[i], DIV_QUO(i, 2), DIV_REM(i, 2)/10);
+			else
+				printf("%.2d\t%d Mbit/s\n",
+					rate_histo_res->rate[i], DIV_QUO(i, 2));
+		}
+	}
+
+	printf("MCS indexes:\n");
+	for (i = 0; i < (WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX); i++) {
+		if (rate_histo_res->mcs[i]) {
+			printf("%d\tMCS %d\n", rate_histo_res->mcs[i], i);
+		}
+	}
+
+	printf("VHT indexes:\n");
+	for (nss = 0; nss < WL_TX_CHAINS_MAX; nss++) {
+		for (i = 0; i < WL_RATESET_SZ_VHT_MCS; i++) {
+			if (rate_histo_res->vht[i][nss]) {
+				printf("%d\tVHT %d Nss %d\n", rate_histo_res->vht[i][nss], i,
+					nss + 1);
+			}
+		}
+	}
+
+	return;
+}
+
+static int
+wl_rate_histo(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr = NULL;
+	int err;
+	wl_mac_ratehisto_res_t *rate_histo_res;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return err;
+
+	rate_histo_res = (wl_mac_ratehisto_res_t *)ptr;
+
+	wl_rate_histo_print(rate_histo_res);
+
+	return 0;
+}
+
+static int
+wl_mac_rate_histo(void *wl, cmd_t *cmd, char **argv)
+{
+	struct ether_addr ea;
+	int buflen, err;
+	wl_mac_ratehisto_cmd_t *rate_histo_cmd;
+	wl_mac_ratehisto_res_t *rate_histo_res;
+
+	if (!*++argv || !wl_ether_atoe(*argv, &ea))
+		return BCME_USAGE_ERROR;
+
+	strcpy(buf, "mac_rate_histo");
+	buflen = strlen(buf) + 1;
+	rate_histo_cmd = (wl_mac_ratehisto_cmd_t *)(buf + buflen);
+	memcpy((char*)&rate_histo_cmd->ea, (char*)&ea, ETHER_ADDR_LEN);
+
+	if (*++argv)
+	{
+		/* The access category is obtained and checked for validity */
+		rate_histo_cmd->ac_cat = (uint8)strtol(*argv, NULL, 0);
+		if (!(rate_histo_cmd->ac_cat == 0x10 || rate_histo_cmd->ac_cat == 0x4)) {
+			printf("Only Access Category 0x10 and 0x4 is supported\n");
+			return BCME_BADARG;
+		}
+
+		if (*++argv) {
+			/* The number of pkts to avg is obtained and checked for valid range */
+			rate_histo_cmd->num_pkts = (uint8)strtol(*argv, NULL, 10);
+		} else {
+			/* Set default value as maximum of all access categories
+			 * so that it is set to the max value below
+			 */
+			rate_histo_cmd->num_pkts = 64;
+		}
+
+		if (rate_histo_cmd->ac_cat == 0x10 && rate_histo_cmd->num_pkts > 64) {
+			rate_histo_cmd->num_pkts = 64;
+		} else if (rate_histo_cmd->ac_cat == 0x4 && rate_histo_cmd->num_pkts > 32) {
+			rate_histo_cmd->num_pkts = 32;
+		}
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	rate_histo_res = (wl_mac_ratehisto_res_t *)buf;
+
+	wl_rate_histo_print(rate_histo_res);
+
+	printf("First TSF Timestamp: %08x%08x\n", rate_histo_res->tsf_timer[0][1],
+		rate_histo_res->tsf_timer[0][0]);
+	printf("Last TSF Timestamp : %08x%08x\n", rate_histo_res->tsf_timer[1][1],
+		rate_histo_res->tsf_timer[1][0]);
+
+	return 0;
+}
+
+static int
+wl_sarlimit(void *wl, cmd_t *cmd, char **argv)
+{
+	uint i;
+	int ret;
+	sar_limit_t sar;
+	uint argc;
+	char *endptr;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argc != 0 && argc != sizeof(sar_limit_t)) {
+		printf("Error: Input %d SAR values, need total %d SAR values\n",
+		       argc, (int)sizeof(sar_limit_t));
+		return BCME_USAGE_ERROR;
+	}
+
+	if (argc == 0) {
+		if ((ret = wlu_iovar_get(wl, cmd->name, &sar, sizeof(sar_limit_t))) < 0) {
+			return (ret);
+		}
+		printf("\t2G:    %4d %4d %4d %4d\n",
+		       sar.band2g[0], sar.band2g[1], sar.band2g[2], sar.band2g[3]);
+		for (i = 0; i < WLC_SUBBAND_MAX; i++) {
+			printf("\t5G[%1d]  %4d %4d %4d %4d\n", i,
+			       sar.band5g[i][0], sar.band5g[i][1],
+			       sar.band5g[i][2], sar.band5g[i][3]);
+		}
+	} else {
+		uint8 *ptr = (uint8 *)&sar;
+		memset(ptr, WLC_TXPWR_MAX, sizeof(sar_limit_t));
+		for (i = 0; i < argc; i++) {
+			ptr[i] = (uint8)(strtol(argv[1 + i], &endptr, 0));
+			if (*endptr != '\0') {
+				printf("error\n");
+				return BCME_USAGE_ERROR;
+			}
+		}
+		printf("\t2G:    %4d %4d %4d %4d\n",
+		       sar.band2g[0], sar.band2g[1], sar.band2g[2], sar.band2g[3]);
+		for (i = 0; i < WLC_SUBBAND_MAX; i++) {
+			printf("\t5G[%1d]  %4d %4d %4d %4d\n", i,
+			       sar.band5g[i][0], sar.band5g[i][1],
+			       sar.band5g[i][2], sar.band5g[i][3]);
+		}
+		ret = wlu_iovar_set(wl, cmd->name, &sar, sizeof(sar_limit_t));
+	}
+
+	return ret;
+}
+
+#ifdef SR_DEBUG
+/* Displays PMU related info on screen */
+static int
+wl_dump_pmu(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	pmu_reg_t *pmu_var;
+	int err;
+	uint i;
+	uint32 pmu_chip_ctl_reg;
+	uint32 pmu_chip_reg_reg;
+	uint32 pmu_chip_pll_reg;
+	uint32 pmu_chip_res_reg;
+	UNUSED_PARAMETER(argv);
+	if ((err = wlu_var_getbuf_med (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+	pmu_var = (pmu_reg_t *)ptr;
+	printf("PMU Control          : 0x%08x\n", pmu_var->pmu_control);
+	printf("PMU Capabilities     : 0x%08x\n", pmu_var->pmu_capabilities);
+	printf("PMU Status           : 0x%08x\n", pmu_var->pmu_status);
+	printf("Resource State       : 0x%08x\n", pmu_var->res_state);
+	printf("Resurce Pending      : 0x%08x\n", pmu_var->res_pending);
+	printf("PMU Timer            : 0x%08x\n", pmu_var->pmu_timer1);
+	printf("Minimum Resource Mask: 0x%08x\n", pmu_var->min_res_mask);
+	printf("Maximum Resource Mask: 0x%08x\n", pmu_var->max_res_mask);
+	/* Displays values of the 5 PMU Chip Control Registers */
+	pmu_chip_ctl_reg = (pmu_var->pmu_capabilities & 0xf8000000);
+	pmu_chip_ctl_reg = pmu_chip_ctl_reg >> 27;
+	for (i = 0; i < pmu_chip_ctl_reg; i++) {
+		printf("PMU ChipControl[%d]   : 0x%08x\n", i, pmu_var->pmu_chipcontrol1[i]);
+	}
+	/* Displays values of the 6 PMU Reg Control Registers */
+	pmu_chip_reg_reg = (pmu_var->pmu_capabilities & 0x07c00000);
+	pmu_chip_reg_reg = pmu_chip_reg_reg >> 22;
+	for (i = 0; i < pmu_chip_reg_reg; i++) {
+		printf("PMU RegControl[%d]    : 0x%08x\n", i, pmu_var->pmu_regcontrol[i]);
+	}
+	/* Displays values of the 6 PMU Pll Control Registers */
+	pmu_chip_pll_reg = (pmu_var->pmu_capabilities & 0x003e0000);
+	pmu_chip_pll_reg = pmu_chip_pll_reg >> 17;
+	for (i = 0; i < pmu_chip_pll_reg; i++) {
+		printf("PMU PllControl[%d]    : 0x%08x\n", i, pmu_var->pmu_pllcontrol[i]);
+	}
+	/* Displays values of the 31 PMU Resource Up/Down Timer */
+	pmu_chip_res_reg = (pmu_var->pmu_capabilities & 0x00001f00);
+	pmu_chip_res_reg = pmu_chip_res_reg >> 8;
+	for (i = 0; i < pmu_chip_res_reg; i++) {
+		printf("PMU Resource Up/Down Timer[%d]    : 0x%08x\n", i,
+			pmu_var->pmu_rsrc_up_down_timer[i]);
+	}
+	/* Displays values of the 31 PMU Resource Dependancy Mask */
+	pmu_chip_res_reg = (pmu_var->pmu_capabilities & 0x00001f00);
+	pmu_chip_res_reg = pmu_chip_res_reg >> 8;
+	for (i = 0; i < pmu_chip_res_reg; i++) {
+		printf("PMU Resource Dependancy Mask[%d]    : 0x%08x\n", i,
+			pmu_var->rsrc_dep_mask[i]);
+	}
+	return 0;
+}
+#endif /* #ifdef SR_DEBUG */
+
+static int
+wl_antgain(void *wl, cmd_t *cmd, char **argv)
+{
+#if	defined(DONGLEBUILD)
+	return 0;
+#else
+	int	err = 0;
+	uint	val;
+	uint8	ag[2];
+	uint8	*rag;
+	void	*ptr;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {	/* write maxpower */
+		if (find_pattern(argv, "ag0", &val))
+			ag[0] = val & 0xff;
+		else {
+			printf("Missing ag0\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if (find_pattern(argv, "ag1", &val))
+			ag[1] = val & 0xff;
+		else {
+			printf("Missing ag1\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if ((err = wlu_var_setbuf(wl, "antgain", &ag, 2 * sizeof(uint8)) < 0)) {
+			printf("wl_antgain: fail to set\n");
+		}
+	} else {
+		if ((err = wlu_var_getbuf(wl, "antgain", NULL, 0, &ptr) < 0)) {
+			printf("wl_antgain: fail to get antgain\n");
+			return err;
+		}
+		rag = (uint8*)ptr;
+		printf("ag0=%x\n", rag[0]);
+		printf("ag1=%x\n", rag[1]);
+	}
+
+	return err;
+#endif 
+}
+
+/* Convert user's input in hex pattern to byte-size mask */
+int
+wl_pattern_atoh(char *src, char *dst)
+{
+	int i;
+	if (strncmp(src, "0x", 2) != 0 &&
+	    strncmp(src, "0X", 2) != 0) {
+		printf("Data invalid format. Needs to start with 0x\n");
+		return -1;
+	}
+	src = src + 2; /* Skip past 0x */
+	if (strlen(src) % 2 != 0) {
+		printf("Data invalid format. Needs to be of even length\n");
+		return -1;
+	}
+	for (i = 0; *src != '\0'; i++) {
+		char num[3];
+		strncpy(num, src, 2);
+		num[2] = '\0';
+		dst[i] = (uint8)strtoul(num, NULL, 16);
+		src += 2;
+	}
+	return i;
+}
+
+
+#define MAX_PWR_STAT_TYPES	32
+
+static int
+wl_pwrstats(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pwrstats_query_t *p_query;
+	wl_pwrstats_t	*p_pwrstats;
+	void	*ptr = NULL;
+	int	rc = 0;
+	uint	i, argc, len, taglen;
+	uint16	type;
+
+	/* Count <type> args and allocate buffer */
+	for (argv++, argc = 0; argv[argc]; argc++)
+		;
+	if (argc > MAX_PWR_STAT_TYPES) {
+		fprintf(stderr, "Currently limited to %d types in one query\n",
+		        MAX_PWR_STAT_TYPES);
+		return -1;
+	}
+
+	len = OFFSETOF(wl_pwrstats_query_t, type) + argc * sizeof(uint16);
+	p_query = (wl_pwrstats_query_t *)malloc(len);
+	if (p_query == NULL) {
+		fprintf(stderr, "malloc failed to allocate %d bytes\n", len);
+		return -1;
+	}
+
+	/* Build a list of types */
+	p_query->length = argc;
+	for (i = 0; i < argc; i++, argv++) {
+		char *endptr;
+		p_query->type[i] = strtoul(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "Type '%s' (arg %d) not a number?\n", *argv, i);
+			free(p_query);
+			return -1;
+		}
+	}
+
+	/* Now issue the get with the query as parameter */
+	rc = wlu_var_getbuf(wl, cmd->name, p_query, len, &ptr);
+	free(p_query);
+	if (rc < 0)
+		return rc;
+
+	p_pwrstats = (wl_pwrstats_t *)ptr;
+
+	if (dtoh16(p_pwrstats->version) != WL_PWRSTATS_VERSION) {
+		printf("Power stats version mismatch\n");
+		return BCME_ERROR;
+	}
+
+	/* Basic information */
+	printf("Version: %d, Length %d bytes\n",
+	       dtoh16(p_pwrstats->version), dtoh16(p_pwrstats->length));
+
+	/* Run down tags displaying content */
+	len = dtoh16(p_pwrstats->length) - WL_PWR_STATS_HDRLEN;
+	for (ptr = p_pwrstats->data; len >= 2 * sizeof(uint16); *(uint8**)&ptr += taglen) {
+		/* Grab tag/len words */
+		type = dtoh16(((uint16*)ptr)[0]);
+		taglen = dtoh16(((uint16*)ptr)[1]);
+
+		if ((taglen < 2 * sizeof(uint16)) || (taglen > len)) {
+			fprintf(stderr, "Bad len %d for tag %d, remaining len %d\n",
+			        taglen, type, len);
+			rc = BCME_ERROR;
+			break;
+		}
+
+		if (taglen & 0xF000) {
+			fprintf(stderr, "Resrved bits in len %d for tag %d, remaining len %d\n",
+			        taglen, type, len);
+			rc = BCME_ERROR;
+			break;
+		}
+
+		/* Tag-specific display */
+		switch (type) {
+		case WL_PWRSTATS_TYPE_PHY:
+		{
+			wl_pwr_phy_stats_t stats;
+
+			if (taglen < sizeof(wl_pwr_phy_stats_t)) {
+				fprintf(stderr, "Short len for %d: %d < %d\n",
+				        type, taglen, (int)sizeof(wl_pwr_phy_stats_t));
+				rc = BCME_ERROR;
+				break;
+			}
+
+			memcpy(&stats, ptr, taglen);
+			printf("PHY:\n"
+			       "  TX Duration: %u\n"
+			       "  RX Duration: %u\n",
+			       dtoh32(stats.tx_dur),
+			       dtoh32(stats.rx_dur));
+		}
+		break;
+
+		case WL_PWRSTATS_TYPE_SCAN:
+		{
+			wl_pwr_scan_stats_t stats;
+
+			if (taglen < sizeof(wl_pwr_scan_stats_t)) {
+				fprintf(stderr, "Short len for %d: %d < %d\n",
+				        type, taglen, (int)sizeof(wl_pwr_scan_stats_t));
+				rc = BCME_ERROR;
+				break;
+			}
+
+			memcpy(&stats, ptr, taglen);
+			printf("SCAN:\n"
+			       "  User-Scan:\tCount: %u\tDuration: %u\n"
+			       "  Assoc-Scan:\tCount: %u\tDuration: %u\n"
+			       "  Roam-Scan:\tCount: %u\tDuration: %u\n"
+			       "  PNO-Scan:\tCount: %u\tDuration: %u\n"
+			       "  Other-Scan:\tCount: %u\tDuration: %u\n",
+			       dtoh32(stats.user_scans.count),
+			       dtoh32(stats.user_scans.dur),
+			       dtoh32(stats.assoc_scans.count),
+			       dtoh32(stats.assoc_scans.dur),
+			       dtoh32(stats.roam_scans.count),
+			       dtoh32(stats.roam_scans.dur),
+			       dtoh32(stats.pno_scans[0].count),
+			       dtoh32(stats.pno_scans[0].dur),
+			       dtoh32(stats.other_scans.count),
+			       dtoh32(stats.other_scans.dur));
+		}
+		break;
+
+		case WL_PWRSTATS_TYPE_USB_HSIC:
+		{
+			wl_pwr_usb_hsic_stats_t stats;
+
+			if (taglen < sizeof(wl_pwr_usb_hsic_stats_t)) {
+				fprintf(stderr, "Short len for %d: %d < %d\n",
+				        type, taglen, (int)sizeof(wl_pwr_usb_hsic_stats_t));
+				rc = BCME_ERROR;
+				break;
+			}
+
+			memcpy(&stats, ptr, taglen);
+			printf("HSIC:\n"
+			       "  Suspend count: %u\n"
+			       "  Resume count: %u\n"
+			       "  Disconnect count: %u\n"
+			       "  Reconnect count: %u\n"
+			       "  Active duration: %u\n"
+			       "  Suspend duration: %u\n"
+			       "  Disconnect duration:%u\n",
+			       dtoh32(stats.hsic.suspend_ct),
+			       dtoh32(stats.hsic.resume_ct),
+			       dtoh32(stats.hsic.disconnect_ct),
+			       dtoh32(stats.hsic.reconnect_ct),
+			       dtoh32(stats.hsic.active_dur),
+			       dtoh32(stats.hsic.suspend_dur),
+			       dtoh32(stats.hsic.disconnect_dur));
+		}
+		break;
+
+		case WL_PWRSTATS_TYPE_PCIE:
+		{
+			wl_pwr_pcie_stats_t stats;
+
+			if (taglen < sizeof(wl_pwr_pcie_stats_t)) {
+				fprintf(stderr, "Short len for %d: %d < %d\n",
+				        type, taglen, (int)sizeof(wl_pwr_pcie_stats_t));
+				rc = BCME_ERROR;
+				break;
+			}
+
+			memcpy(&stats, ptr, taglen);
+			if (dtoh32(stats.pcie.l0_cnt) == 0) {
+				printf("link stats are not supported for this pcie core\n");
+			}
+			printf("PCIE:\n"
+			       "  D3 Suspend count: %u\n"
+			       "  D0 Resume count: %u\n"
+			       "  PERST# assert count: %u\n"
+			       "  PERST# deassert count: %u\n"
+			       "  Active duration: %u ms\n"
+			       "  D3 Suspend duration: %u ms\n"
+			       "  PERST# duration:%u ms\n"
+			       "  l0 cnt:%u dur:%u usecs\n"
+			       "  l1 cnt:%u dur:%u usecs\n"
+			       "  l1_1 cnt:%u dur:%u usecs\n"
+			       "  l1_2 cnt:%u dur:%u usecs\n"
+			       "  l2 cnt:%u dur:%u usecs\n"
+			       "  LTR_ACTIVE Count %u Duration: %u ms\n"
+			       "  LTR_SLEEP Count %u Duration: %u ms\n"
+			       "  DeepSleep Count %u Duration: %u ms\n",
+			       dtoh32(stats.pcie.d3_suspend_ct),
+			       dtoh32(stats.pcie.d0_resume_ct),
+			       dtoh32(stats.pcie.perst_assrt_ct),
+			       dtoh32(stats.pcie.perst_deassrt_ct),
+			       dtoh32(stats.pcie.active_dur),
+			       dtoh32(stats.pcie.d3_suspend_dur),
+			       dtoh32(stats.pcie.perst_dur),
+			       dtoh32(stats.pcie.l0_cnt),
+			       dtoh32(stats.pcie.l0_usecs),
+			       dtoh32(stats.pcie.l1_cnt),
+			       dtoh32(stats.pcie.l1_usecs),
+			       dtoh32(stats.pcie.l1_1_cnt),
+			       dtoh32(stats.pcie.l1_1_usecs),
+			       dtoh32(stats.pcie.l1_2_cnt),
+			       dtoh32(stats.pcie.l1_2_usecs),
+			       dtoh32(stats.pcie.l2_cnt),
+			       dtoh32(stats.pcie.l2_usecs),
+			       dtoh32(stats.pcie.ltr_active_ct),
+			       dtoh32(stats.pcie.ltr_active_dur),
+			       dtoh32(stats.pcie.ltr_sleep_ct),
+			       dtoh32(stats.pcie.ltr_sleep_dur),
+			       dtoh32(stats.pcie.deepsleep_count),
+			       dtoh32(stats.pcie.deepsleep_dur));
+
+			printf("\nIPC Stats\n");
+			printf("  Submissions:\tCount: %u\th2d drbl: %u\t",
+				dtoh32(stats.pcie.num_submissions),
+				dtoh32(stats.pcie.num_h2d_doorbell));
+			if (stats.pcie.num_h2d_doorbell)
+				printf("Avg per h2d drbl: %d.%d\n",
+					DIV_QUO(dtoh32(stats.pcie.num_submissions),
+					dtoh32(stats.pcie.num_h2d_doorbell)),
+					DIV_REM(dtoh32(stats.pcie.num_submissions),
+					dtoh32(stats.pcie.num_h2d_doorbell)));
+			else
+				printf("  Avg per h2d drbl: 0.0\n");
+
+			printf("  Completions:\tCount: %u\td2h drbl: %u\t",
+				dtoh32(stats.pcie.num_completions),
+				dtoh32(stats.pcie.num_d2h_doorbell));
+			if (stats.pcie.num_d2h_doorbell)
+				printf("Avg per d2h drbl: %d.%d\n",
+					DIV_QUO(dtoh32(stats.pcie.num_completions),
+					dtoh32(stats.pcie.num_d2h_doorbell)),
+					DIV_REM(dtoh32(stats.pcie.num_completions),
+					dtoh32(stats.pcie.num_d2h_doorbell)));
+			else
+				printf("Avg per d2h drbl: 0.0\n");
+
+			printf("   Rx Cmplt:\tCount: %u\trx_cmplt drbl: %u\t",
+				dtoh32(stats.pcie.num_rxcmplt),
+				dtoh32(stats.pcie.num_rxcmplt_drbl));
+			if (stats.pcie.num_rxcmplt_drbl)
+				printf("Avg per rx_cmplt drbl: %d.%d\n",
+					DIV_QUO(dtoh32(stats.pcie.num_rxcmplt),
+					dtoh32(stats.pcie.num_rxcmplt_drbl)),
+					DIV_REM(dtoh32(stats.pcie.num_rxcmplt),
+					dtoh32(stats.pcie.num_rxcmplt_drbl)));
+			else
+				printf("Avg per rx_cmplt drbl: 0.0\n");
+
+			printf("   Tx Cmplt:\tCount: %u\ttx_cmplt drbl: %u\t",
+				dtoh32(stats.pcie.num_txstatus),
+				dtoh32(stats.pcie.num_txstatus_drbl));
+			if (stats.pcie.num_txstatus_drbl)
+				printf("Avg per tx_cmplt drbl: %d.%d\n",
+					DIV_QUO(dtoh32(stats.pcie.num_txstatus),
+					dtoh32(stats.pcie.num_txstatus_drbl)),
+					DIV_REM(dtoh32(stats.pcie.num_txstatus),
+					dtoh32(stats.pcie.num_txstatus_drbl)));
+			else
+				printf("Avg per tx_cmplt drbl: 0.0\n");
+
+		}
+		break;
+
+		case WL_PWRSTATS_TYPE_SDIO:
+		{
+			wl_pwr_sdio_stats_t stats;
+
+			if (taglen < sizeof(wl_pwr_sdio_stats_t)) {
+				fprintf(stderr, "Short len for %d: %d < %d\n",
+				        type, taglen, (int)sizeof(wl_pwr_sdio_stats_t));
+				rc = BCME_ERROR;
+				break;
+			}
+
+			memcpy(&stats, ptr, taglen);
+			printf("SDIO:\n"
+				"  active duration: %u\n"
+				"  wakehost count: %u\n"
+				"  intr count: data: %u\tmailbox: %u\terror: %u\n"
+				"  ds_wake ON: count: %u\t duration: %u\n"
+				"  ds_wake OFF: count: %u\t duration: %u\n"
+				"  ds_d0 count: %u\t duration: %u\n"
+				"  ds_d3 count: %u\t duration: %u\n"
+				"  DEV_WAKE count: ASSRT: %u\tDASST: %u\n"
+				"  ds mb rx count: DSACK: %u\tDSNACK: %u\tD3INFORM: %u\n"
+				"  ds mb tx count: DSREQ: %u\tDSEXIT: %u\tD3ACK: %u\tD3EXIT: %u\n",
+
+				dtoh32(stats.sdio.active_dur),
+				dtoh32(stats.sdio.wakehost_cnt),
+
+				dtoh32(stats.sdio.data_intr_cnt),
+				dtoh32(stats.sdio.mb_intr_cnt),
+				dtoh32(stats.sdio.error_intr_cnt),
+
+				dtoh32(stats.sdio.ds_wake_on_cnt),
+				dtoh32(stats.sdio.ds_wake_on_dur),
+				dtoh32(stats.sdio.ds_wake_off_cnt),
+				dtoh32(stats.sdio.ds_wake_off_dur),
+
+				dtoh32(stats.sdio.ds_d0_cnt),
+				dtoh32(stats.sdio.ds_d0_dur),
+				dtoh32(stats.sdio.ds_d3_cnt),
+				dtoh32(stats.sdio.ds_d3_dur),
+
+				dtoh32(stats.sdio.ds_dw_assrt_cnt),
+				dtoh32(stats.sdio.ds_dw_dassrt_cnt),
+
+				dtoh32(stats.sdio.ds_rx_dsack_cnt),
+				dtoh32(stats.sdio.ds_rx_dsnack_cnt),
+				dtoh32(stats.sdio.ds_rx_d3inform_cnt),
+				dtoh32(stats.sdio.ds_tx_dsreq_cnt),
+				dtoh32(stats.sdio.ds_tx_dsexit_cnt),
+				dtoh32(stats.sdio.ds_tx_d3ack_cnt),
+				dtoh32(stats.sdio.ds_tx_d3exit_cnt));
+
+		}
+		break;
+
+		case WL_PWRSTATS_TYPE_PM_AWAKE1:
+		{
+			wl_pwr_pm_awake_stats_v1_t stats;
+			bool skip = FALSE;
+			uint32 dur_time, bits;
+			uint endidx;
+
+			if (taglen < sizeof(wl_pwr_pm_awake_stats_v1_t)) {
+				fprintf(stderr, "Short len for %d: %d < %d\n",
+				        type, taglen, (int)sizeof(wl_pwr_pm_awake_stats_v1_t));
+				rc = BCME_ERROR;
+				break;
+			}
+
+			memcpy(&stats, ptr, taglen);
+			printf("PM WAKE:\n"
+			       "  Current Time: %u\n"
+			       "  HW MACC: 0x%08x\n"
+			       "  SW MACC: 0x%08x\n"
+			       "  PM Dur: %u\n"
+			       "  MPC Dur: %u\n"
+			       "  TSF Drift (Last/Min/Max/Avg/Cnt): %d/%d/%d/%u/%u\n"
+			       "  Frts (end_cnt/dur): %u/%u\n",
+			       dtoh32(stats.awake_data.curr_time),
+			       dtoh32(stats.awake_data.hw_macc),
+			       dtoh32(stats.awake_data.sw_macc),
+			       dtoh32(stats.awake_data.pm_dur),
+			       dtoh32(stats.awake_data.mpc_dur),
+			       dtoh32(stats.awake_data.last_drift),
+			       dtoh32(stats.awake_data.min_drift),
+			       dtoh32(stats.awake_data.max_drift),
+			       dtoh32(stats.awake_data.avg_drift),
+			       dtoh32(stats.awake_data.drift_cnt),
+			       dtoh32(stats.frts_end_cnt),
+			       dtoh32(stats.frts_time));
+
+			printf("\n");
+
+			i = endidx = stats.awake_data.pmwake_idx;
+			if (endidx > WLC_STA_AWAKE_STATES_MAX_V1) {
+				fprintf(stderr, "Unexpected idx %d > %d\n",
+				        endidx, WLC_STA_AWAKE_STATES_MAX_V1);
+				rc = BCME_ERROR;
+				break;
+			}
+
+			if (endidx == 0)
+				endidx = WLC_STA_AWAKE_STATES_MAX_V1;
+
+			do {
+				if (i >= WLC_STA_AWAKE_STATES_MAX_V1)
+					i = 0;
+
+				dur_time = dtoh32(stats.awake_data.pm_state[i].timestamp);
+				bits = dtoh32(stats.awake_data.pm_state[i].reason);
+				if (dur_time == 0 && bits == 0)
+					continue;
+
+				printf("  State: %2d  reason: 0x%04x  time: %u\n",
+				       i, bits, dur_time);
+			} while (++i != endidx);
+			printf("\n");
+
+			for (i = 0; i < WLC_PMD_EVENT_MAX_V1; i++) {
+				dur_time = dtoh32(stats.awake_data.pmd_event_wake_dur[i]);
+				if (dur_time == 0) {
+					if (i != 0)
+						skip = TRUE;
+					continue;
+				}
+				if (skip) {
+					printf("  ---\n");
+					skip = FALSE;
+				}
+				printf("  Event: %2d Wake-Duration: %u\n", i, dur_time);
+			}
+		}
+		break;
+
+		case WL_PWRSTATS_TYPE_PM_AWAKE2:
+		{
+			wl_pwr_pm_awake_stats_v2_t *stats = (wl_pwr_pm_awake_stats_v2_t *)ptr;
+			bool skip = FALSE;
+			uint32 dur_time, bits;
+			uint endidx;
+
+			if (taglen < sizeof(wl_pwr_pm_awake_stats_v2_t)) {
+				fprintf(stderr, "Short len for %d: %d < %d\n",
+				        type, taglen, (int)sizeof(wl_pwr_pm_awake_stats_v2_t));
+				rc = BCME_ERROR;
+				break;
+			}
+
+			printf("PM WAKE:\n"
+			       "  Current Time: %u\n"
+			       "  HW MACC: 0x%08x\n"
+			       "  SW MACC: 0x%08x\n"
+			       "  PM Dur: %u\n"
+			       "  MPC Dur: %u\n"
+			       "  TSF Drift (Last/Min/Max/Avg/Cnt): %d/%d/%d/%u/%u\n"
+			       "  Frts (end_cnt/dur): %u/%u\n"
+			       "  Flags: %d, ASLEEP=%s\n",
+			       dtoh32(stats->awake_data.curr_time),
+			       dtoh32(stats->awake_data.hw_macc),
+			       dtoh32(stats->awake_data.sw_macc),
+			       dtoh32(stats->awake_data.pm_dur),
+			       dtoh32(stats->awake_data.mpc_dur),
+			       dtoh32(stats->awake_data.last_drift),
+			       dtoh32(stats->awake_data.min_drift),
+			       dtoh32(stats->awake_data.max_drift),
+			       dtoh32(stats->awake_data.avg_drift),
+			       dtoh32(stats->awake_data.drift_cnt),
+			       dtoh32(stats->awake_data.frts_end_cnt),
+			       dtoh32(stats->awake_data.frts_time),
+			       stats->awake_data.flags,
+			       ((stats->awake_data.flags &
+			       WL_PWR_PM_AWAKE_STATS_WAKE_MASK) == WL_PWR_PM_AWAKE_STATS_ASLEEP) ?
+			       "True":"False");
+
+			printf("\n");
+			i = endidx = stats->awake_data.pmwake_idx;
+			if (endidx > stats->awake_data.pm_state_len) {
+				fprintf(stderr, "Unexpected idx %d > %d\n",
+				        endidx, stats->awake_data.pm_state_len);
+				rc = BCME_ERROR;
+				break;
+			}
+
+			if (endidx == 0)
+				endidx = stats->awake_data.pm_state_len;
+
+			do {
+				wlc_pm_debug_t *pm_state = (wlc_pm_debug_t *)
+					(((uint8 *)&stats->awake_data) +
+					stats->awake_data.pm_state_offset);
+				if (i >= stats->awake_data.pm_state_len)
+					i = 0;
+
+				dur_time = dtoh32(pm_state[i].timestamp);
+				bits = dtoh32(pm_state[i].reason);
+				if (dur_time == 0 && bits == 0)
+					continue;
+
+				printf("  State: %2d  reason: 0x%04x  time: %u\n",
+				       i, bits, dur_time);
+			} while (++i != endidx);
+			printf("\n");
+
+			for (i = 0; i < stats->awake_data.pmd_event_wake_dur_len; i++) {
+				uint32 *pmd_event_wake_dur = (uint32 *)
+					(((uint8 *)&stats->awake_data) +
+					stats->awake_data.pmd_event_wake_dur_offset);
+				dur_time = dtoh32(pmd_event_wake_dur[i]);
+				if (dur_time == 0) {
+					if (i != 0)
+						skip = TRUE;
+					continue;
+				}
+				if (skip) {
+					printf("  ---\n");
+					skip = FALSE;
+				}
+				printf("  Event: %2d Wake-Duration: %u\n", i, dur_time);
+			}
+		}
+		break;
+
+		case WL_PWRSTATS_TYPE_CONNECTION:
+		{
+			wl_pwr_connect_stats_t connect_stats;
+
+			if (taglen < sizeof(wl_pwr_connect_stats_t)) {
+				fprintf(stderr, "Short len for %d: %d < %d\n",
+				        type, taglen, (int)sizeof(wl_pwr_connect_stats_t));
+				rc = BCME_ERROR;
+				break;
+			}
+
+			memcpy(&connect_stats, ptr, taglen);
+			printf("Connect:\n"
+					"  Count: %u\n"
+					"  Duration: %u\n",
+					dtoh32(connect_stats.count),
+					dtoh32(connect_stats.dur));
+		}
+		break;
+
+		case WL_PWRSTATS_TYPE_MIMO_PS_METRICS:
+		{
+			wl_mimo_meas_metrics_t stats;
+			bool ocl_stats = FALSE;
+
+			if (taglen < STRUCT_SIZE_THROUGH(&stats, total_tx_time_3chain)) {
+				fprintf(stderr, "Short len for %d: %d < %d\n",
+				        type, taglen,
+				        (int)STRUCT_SIZE_THROUGH(&stats, total_tx_time_3chain));
+				rc = BCME_ERROR;
+				break;
+			} else if (taglen >= STRUCT_SIZE_THROUGH(&stats, total_rx_time_ocl)) {
+				ocl_stats = TRUE;
+			}
+
+			memcpy(&stats, ptr, taglen);
+			printf("MIMO ps measurement metrics:\n");
+			if (ocl_stats) {
+				printf("  MIMO  Idle duration:\t%10u (OCL Idle: %10u)\n"
+					   "  OCL   Idle duration:\t%10u\n",
+					   dtoh32(stats.total_idle_time_mimo),
+					   dtoh32(stats.total_idle_time_ocl),
+					   dtoh32(stats.total_idle_time_ocl));
+			} else {
+				printf("  MIMO  Idle duration:\t%10u\n",
+				       dtoh32(stats.total_idle_time_mimo));
+			}
+			printf("  SISO  Idle duration:\t%10u\n",
+			       dtoh32(stats.total_idle_time_siso));
+			if (ocl_stats) {
+				printf("  MIMO  Rx duration:\t%10u (OCL Rx: %10u)\n"
+					   "  OCL   Rx duration:\t%10u\n",
+					   dtoh32(stats.total_rx_time_mimo),
+					   dtoh32(stats.total_rx_time_ocl),
+					   dtoh32(stats.total_rx_time_ocl));
+			} else {
+				printf("  MIMO  Rx duration:\t%10u\n",
+				       dtoh32(stats.total_rx_time_mimo));
+			}
+			printf("  SISO  RX duration:\t%10u\n"
+				   "  TX 1-chain duration:\t%10u\n"
+				   "  TX 2-chain duration:\t%10u\n"
+				   "  TX 3-chain duration:\t%10u\n",
+				   dtoh32(stats.total_rx_time_siso),
+				   dtoh32(stats.total_tx_time_1chain),
+				   dtoh32(stats.total_tx_time_2chain),
+				   dtoh32(stats.total_tx_time_3chain));
+		}
+		break;
+		default:
+			printf("Skipping uknown %d-byte tag %d\n", taglen, type);
+			break;
+		}
+
+		printf("\n");
+		if (rc)
+			break;
+
+		/* Adjust length to account for padding, but don't exceed total len */
+		taglen = (ROUNDUP(taglen, 4) > len) ? len : ROUNDUP(taglen, 4);
+		len -= taglen;
+	}
+
+	if (len && (len < 2 * sizeof(uint16))) {
+		fprintf(stderr, "Invalid length remaining %d\n", len);
+		rc = BCME_ERROR;
+	}
+
+	return (rc);
+}
+
+
+/*
+* Function to output heap details for wl memuse command
+*/
+
+static int
+wl_memuse(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	memuse_info_t *mu;
+	wlc_rev_info_t revinfo;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	if ((err = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+		return err;
+
+	if (revinfo.driverrev && dtoh32(revinfo.driverrev) < DINGO_FW_REV) {
+		/* memuse implementation for FW branch version < 9.0 (before Dingo) */
+		wl_varstr(wl, cmd, argv);
+	}
+	else {
+		/* memuse implementation for FW branch version > 9.0 (Dingo and above) */
+		memset(buf, 0, sizeof(memuse_info_t));
+		strcpy(buf, cmd->name);
+
+		if ((err = wlu_get(wl, WLC_GET_VAR, &buf[0], sizeof(memuse_info_t))) < 0) {
+			return err;
+		}
+
+		mu = (memuse_info_t *)buf;
+
+		if (mu->ver == RTE_MEMUSEINFO_VER && mu->len >= sizeof(memuse_info_t)) {
+			printf("Heap Total: %d(%dK)\n", mu->arena_size, KB(mu->arena_size));
+			printf("Free: %d(%dK), LWM: %d(%dK)\n",
+			       mu->arena_free, KB(mu->arena_free),
+			       mu->free_lwm, KB(mu->free_lwm));
+			printf("In use: %d(%dK), HWM: %d(%dK)\n",
+			       mu->inuse_size, KB(mu->inuse_size),
+			       mu->inuse_hwm, KB(mu->inuse_hwm));
+			printf("Malloc failure count: %d\n", mu->mf_count);
+		} else {
+			printf("Heap Total: %d(%dK), Heap Free: %d(%dK)\n",
+				mu->arena_size, KB(mu->arena_size),
+				mu->arena_free, KB(mu->arena_free));
+		}
+	}
+	return (0);
+}
+
+
+/* this is the batched command packet size. now for remoteWL, we set it to 512 bytes */
+#define MEMBLOCK (512 - 32) /* allow 32 bytes for overhead (header, alignment, etc) */
+
+int wl_seq_batch_in_client(bool enable)
+{
+	batch_in_client = enable;
+	return 0;
+}
+
+int
+wl_seq_start(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	if (!batch_in_client) {
+		return wlu_iovar_setbuf(wl, "seq_start", NULL, 0, buf, WLC_IOCTL_MAXLEN);
+	}
+	else {
+		if (cmd_batching_mode) {
+			printf("calling seq_start() when it's already in batching mode\n");
+			clean_up_cmd_list();
+			cmd_batching_mode = FALSE;
+			return BCME_USAGE_ERROR;
+		}
+		else {
+			cmd_batching_mode = TRUE;
+			cmd_pkt_list_num = 0;
+
+			cmd_list.head = NULL;
+			cmd_list.tail = NULL;
+		}
+	}
+
+	return 0;
+}
+
+int
+wl_seq_stop(void *wl, cmd_t *cmd, char **argv)
+{
+	char *bufp;
+	int ret = 0;
+	int seq_list_len;
+	int len;
+	wl_seq_cmd_pkt_t *next_cmd;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	if (!batch_in_client) {
+		return wlu_iovar_setbuf(wl, "seq_stop", NULL, 0, buf, WLC_IOCTL_MAXLEN);
+	}
+	else {
+		if (!cmd_batching_mode) {
+			printf("calling seq_stop when it's already out of batching mode\n");
+			return BCME_USAGE_ERROR;
+		}
+		cmd_batching_mode = FALSE;
+
+		next_cmd = cmd_list.head;
+
+		/* dump batched commands to the DUT */
+
+		if (next_cmd == NULL) {
+			printf("no command batched\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		ret = wlu_iovar_setbuf(wl, "seq_start", NULL, 0, buf, WLC_IOCTL_MAXLEN);
+		if (ret) {
+			printf("failed to send seq_start\n");
+			goto fail;
+		}
+
+		while (next_cmd != NULL) {
+			bufp = buf;
+			memset(bufp, 0, WLC_IOCTL_MAXLEN);
+
+			strcpy(bufp, "seq_list");
+			bufp += (strlen("seq_list") + 1);
+
+			seq_list_len = bufp - buf;
+
+			while ((seq_list_len < MEMBLOCK) && (next_cmd != NULL)) {
+				/* note, driver handles the IOCTL buffer 32-bit alignment */
+				len = next_cmd->cmd_header.len;
+				len += (seq_list_len + sizeof(wl_seq_cmd_ioctl_t));
+
+				if (len < MEMBLOCK) {
+					memcpy(bufp, &(next_cmd->cmd_header),
+						sizeof(wl_seq_cmd_ioctl_t));
+					bufp += sizeof(wl_seq_cmd_ioctl_t);
+					memcpy(bufp, next_cmd->data, next_cmd->cmd_header.len);
+					bufp += next_cmd->cmd_header.len;
+					seq_list_len = len;
+
+					next_cmd = next_cmd->next;
+				}
+				else
+					break;
+			}
+
+			ret = wl_set(wl, WLC_SET_VAR, &buf[0], seq_list_len);
+
+			if (ret) {
+				printf("failed to send seq_list\n");
+				goto fail;
+			}
+		}
+
+		ret = wlu_iovar_setbuf(wl, "seq_stop", NULL, 0, buf, WLC_IOCTL_MAXLEN);
+		if (ret) {
+			printf("failed to send seq_stop\n");
+		}
+
+	fail:
+		clean_up_cmd_list();
+		return ret;
+	}
+}
+
+/* mkeep-alive : Send a periodic keep-alive packet or null-data at the specificed interval. */
+/* wowl_keepalive : Send a periodic keep alive packet the specificed interval in wowl mode. */
+int
+wl_mkeep_alive(void *wl, cmd_t *cmd, char **argv)
+{
+	const char 				*str;
+	wl_mkeep_alive_pkt_t	mkeep_alive_pkt;
+	wl_mkeep_alive_pkt_t	*mkeep_alive_pktp;
+	int						buf_len;
+	int						str_len;
+	int						len_bytes;
+	int						i;
+	int 					rc;
+	void					*ptr = NULL;
+	bool					immed_flag = FALSE;
+
+	memset(&mkeep_alive_pkt, 0, sizeof(wl_mkeep_alive_pkt_t));
+
+	str = *argv;  /* mkeep_alive or wowl_keepalive */
+	if (*++argv == NULL) {
+		return BCME_USAGE_ERROR;
+	}
+	else {
+		/* read the packet index */
+		int mkeep_alive_id = htod32(strtoul(*argv, NULL, 0));
+
+		if (*++argv == NULL) {
+			/*
+			** Get current keep-alive status.
+			*/
+			if ((rc = wlu_var_getbuf(wl, cmd->name, &mkeep_alive_id,
+				sizeof(int), &ptr)) < 0)
+				return rc;
+
+			mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) ptr;
+
+			printf("Id            :%d\n"
+				   "Period (msec) :%d\n"
+				   "Length        :%d\n"
+				   "Packet        :0x",
+				   mkeep_alive_pktp->keep_alive_id,
+				   dtoh32(mkeep_alive_pktp->period_msec),
+				   dtoh16(mkeep_alive_pktp->len_bytes));
+
+			for (i = 0; i < mkeep_alive_pktp->len_bytes; i++)
+				printf("%02x", mkeep_alive_pktp->data[i]);
+
+			printf("\n");
+			return rc;
+		}
+
+		str_len = strlen(str);
+		strncpy(buf, str, str_len);
+		buf[ str_len ] = '\0';
+		mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (buf + str_len + 1);
+		if (strcmp(*argv, "immediate") == 0) {
+			immed_flag = TRUE;
+			argv++;
+		}
+		mkeep_alive_pkt.period_msec = strtoul(*argv, NULL, 0);
+		if (mkeep_alive_pkt.period_msec & WL_MKEEP_ALIVE_IMMEDIATE) {
+			fprintf(stderr, "Period %d too large\n", mkeep_alive_pkt.period_msec);
+			return -1;
+		}
+		if (immed_flag && mkeep_alive_pkt.period_msec) {
+			mkeep_alive_pkt.period_msec |= WL_MKEEP_ALIVE_IMMEDIATE;
+		}
+		mkeep_alive_pkt.period_msec = htod32(mkeep_alive_pkt.period_msec);
+		buf_len = str_len + 1;
+		mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION);
+		mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN);
+		mkeep_alive_pkt.keep_alive_id = mkeep_alive_id;
+
+		len_bytes = 0;
+
+		buf_len += WL_MKEEP_ALIVE_FIXED_LEN;
+		if (mkeep_alive_pkt.period_msec != 0) {
+			if (NULL != *++argv) {
+				len_bytes = wl_pattern_atoh(*argv, (char *) mkeep_alive_pktp->data);
+				buf_len += len_bytes;
+			}
+		}
+		mkeep_alive_pkt.len_bytes = htod16(len_bytes);
+
+		/* Keep-alive attributes are set in local	variable (mkeep_alive_pkt), and
+		 * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no
+		 * guarantee that the buffer is properly aligned.
+		 */
+		memcpy((char *)mkeep_alive_pktp, &mkeep_alive_pkt, WL_MKEEP_ALIVE_FIXED_LEN);
+
+		rc = wlu_set(wl, WLC_SET_VAR, buf, buf_len);
+	}
+
+	return (rc);
+}
+
+#ifdef RWL_WIFI
+/* Function added to support RWL_WIFI Transport
+* Used to find the remote server with proper mac address given by
+* the user,this cmd is specific to RWL_WIFIi protocol
+*/
+static int wl_wifiserver(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+
+	if ((ret = wlu_iovar_set(wl, cmd->name, *argv, strlen(*argv))) < 0) {
+		printf("Error finding the remote server  %s\n", argv[0]);
+		return ret;
+	}
+	return ret;
+}
+#endif
+
+static int
+wl_srchmem(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	struct args {
+		int reg;
+		uint32 ssidlen;
+		uint8 ssid[DOT11_MAX_SSID_LEN];
+	} x;
+	char *endptr;
+	uint argc;
+	char *iovar;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(&x, 0, sizeof(x));
+
+	/* save command name */
+	iovar = argv[0];
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* required arg: reg offset */
+	if (argc < 1)
+		return BCME_USAGE_ERROR;
+
+	x.reg = strtol(argv[0], &endptr, 0);
+	if (*endptr != '\0' || x.reg > 15)
+		return BCME_USAGE_ERROR;
+
+	if (argc > 2)
+		return BCME_USAGE_ERROR;
+
+	if (argc == 2) {
+		uint32 len;
+
+		len = strlen(argv[1]);
+		if (len > sizeof(x.ssid)) {
+			printf("ssid too long\n");
+			return BCME_BADARG;
+		}
+		memcpy(x.ssid, argv[1], len);
+		x.ssidlen = len;
+	}
+
+	/* issue the get or set ioctl */
+	if (argc == 1) {
+		x.reg = htod32(x.reg);
+
+		ret = wlu_iovar_getbuf(wl, iovar, &x, sizeof(x), buf, WLC_IOCTL_SMLEN);
+		if (ret < 0) {
+			printf("get returned error 0x%x\n", ret);
+			return (ret);
+		}
+
+		wl_hexdump((uchar *)buf, sizeof(x.ssidlen) + sizeof(x.ssid));
+	} else {
+		x.reg = htod32(x.reg);
+		x.ssidlen = htod32(x.ssidlen);
+
+		ret = wlu_iovar_set(wl, iovar, &x, sizeof(x));
+		if (ret < 0) {
+			printf("set returned error 0x%x\n", ret);
+			return (ret);
+		}
+	}
+
+	return (ret);
+}
+
+cntry_name_t cntry_names[] = {
+
+{"AFGHANISTAN",		"AF"},
+{"ALBANIA",		"AL"},
+{"ALGERIA",		"DZ"},
+{"AMERICAN SAMOA",	"AS"},
+{"ANDORRA",		"AD"},
+{"ANGOLA",		"AO"},
+{"ANGUILLA",		"AI"},
+{"ANTARCTICA",		"AQ"},
+{"ANTIGUA AND BARBUDA",	"AG"},
+{"ARGENTINA",		"AR"},
+{"ARMENIA",		"AM"},
+{"ARUBA",		"AW"},
+{"ASCENSION ISLAND",	"AC"},
+{"AUSTRALIA",		"AU"},
+{"AUSTRIA",		"AT"},
+{"AZERBAIJAN",		"AZ"},
+{"BAHAMAS",		"BS"},
+{"BAHRAIN",		"BH"},
+{"BANGLADESH",		"BD"},
+{"BARBADOS",		"BB"},
+{"BELARUS",		"BY"},
+{"BELGIUM",		"BE"},
+{"BELIZE",		"BZ"},
+{"BENIN",		"BJ"},
+{"BERMUDA",		"BM"},
+{"BHUTAN",		"BT"},
+{"BOLIVIA",		"BO"},
+{"BONAIRE SAINT EUSTATIUS AND SABA",		"BQ"},
+{"BOSNIA AND HERZEGOVINA",		"BA"},
+{"BOTSWANA",		"BW"},
+{"BOUVET ISLAND",	"BV"},
+{"BRAZIL",		"BR"},
+{"BRITISH INDIAN OCEAN TERRITORY",		"IO"},
+{"BRUNEI DARUSSALAM",	"BN"},
+{"BULGARIA",		"BG"},
+{"BURKINA FASO",	"BF"},
+{"BURUNDI",		"BI"},
+{"CAMBODIA",		"KH"},
+{"CAMEROON",		"CM"},
+{"CANADA",		"CA"},
+{"CAPE VERDE",		"CV"},
+{"CAYMAN ISLANDS",	"KY"},
+{"CENTRAL AFRICAN REPUBLIC",		"CF"},
+{"CHAD",		"TD"},
+{"CHILE",		"CL"},
+{"CHINA",		"CN"},
+{"CHRISTMAS ISLAND",	"CX"},
+{"CLIPPERTON ISLAND",	"CP"},
+{"COCOS (KEELING) ISLANDS",		"CC"},
+{"COLOMBIA",		"CO"},
+{"COMOROS",		"KM"},
+{"CONGO",		"CG"},
+{"CONGO, THE DEMOCRATIC REPUBLIC OF THE",		"CD"},
+{"COOK ISLANDS",	"CK"},
+{"COSTA RICA",		"CR"},
+{"COTE D'IVOIRE",	"CI"},
+{"CROATIA",		"HR"},
+{"CUBA",		"CU"},
+{"CURACAO",		"CW"},
+{"CYPRUS",		"CY"},
+{"CZECH REPUBLIC",	"CZ"},
+{"DENMARK",		"DK"},
+{"DJIBOUTI",		"DJ"},
+{"DOMINICA",		"DM"},
+{"DOMINICAN REPUBLIC",	"DO"},
+{"ECUADOR",		"EC"},
+{"EGYPT",		"EG"},
+{"EL SALVADOR",		"SV"},
+{"EQUATORIAL GUINEA",	"GQ"},
+{"ERITREA",		"ER"},
+{"ESTONIA",		"EE"},
+{"ETHIOPIA",		"ET"},
+{"FALKLAND ISLANDS (MALVINAS)",		"FK"},
+{"FAROE ISLANDS",	"FO"},
+{"FIJI",		"FJ"},
+{"FINLAND",		"FI"},
+{"FRANCE",		"FR"},
+{"FRENCH GUIANA",	"GF"},
+{"FRENCH POLYNESIA",	"PF"},
+{"FRENCH SOUTHERN TERRITORIES",		"TF"},
+{"GABON",		"GA"},
+{"GAMBIA",		"GM"},
+{"GEORGIA",		"GE"},
+{"GERMANY",		"DE"},
+{"GHANA",		"GH"},
+{"GIBRALTAR",		"GI"},
+{"GREECE",		"GR"},
+{"GREENLAND",		"GL"},
+{"GRENADA",		"GD"},
+{"GUADELOUPE",		"GP"},
+{"GUAM",		"GU"},
+{"GUATEMALA",		"GT"},
+{"GUERNSEY",		"GG"},
+{"GUINEA",		"GN"},
+{"GUINEA-BISSAU",	"GW"},
+{"GUYANA",		"GY"},
+{"HAITI",		"HT"},
+{"HEARD ISLAND AND MCDONALD ISLANDS",		"HM"},
+{"HOLY SEE (VATICAN CITY STATE)",		"VA"},
+{"HONDURAS",		"HN"},
+{"HONG KONG",		"HK"},
+{"HUNGARY",		"HU"},
+{"ICELAND",		"IS"},
+{"INDIA",		"IN"},
+{"INDONESIA",		"ID"},
+{"IRAN, ISLAMIC REPUBLIC OF",		"IR"},
+{"IRAQ",		"IQ"},
+{"IRELAND",		"IE"},
+{"ISRAEL",		"IL"},
+{"ITALY",		"IT"},
+{"JAMAICA",		"JM"},
+{"JAPAN",		"JP"},
+{"JERSEY",		"JE"},
+{"JORDAN",		"JO"},
+{"KAZAKHSTAN",		"KZ"},
+{"KENYA",		"KE"},
+{"KIRIBATI",		"KI"},
+{"KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF",		"KP"},
+{"KOREA, REPUBLIC OF",	"KR"},
+{"KUWAIT",		"KW"},
+{"KYRGYZSTAN",		"KG"},
+{"LAO PEOPLE'S DEMOCRATIC REPUBLIC",		"LA"},
+{"LATVIA",		"LV"},
+{"LEBANON",		"LB"},
+{"LESOTHO",		"LS"},
+{"LIBERIA",		"LR"},
+{"LIBYAN ARAB JAMAHIRIYA",		"LY"},
+{"LIECHTENSTEIN",	"LI"},
+{"LITHUANIA",		"LT"},
+{"LUXEMBOURG",		"LU"},
+{"MACAO",		"MO"},
+{"MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF",		"MK"},
+{"MADAGASCAR",		"MG"},
+{"MALAWI",		"MW"},
+{"MALAYSIA",		"MY"},
+{"MALDIVES",		"MV"},
+{"MALI",		"ML"},
+{"MALTA",		"MT"},
+{"MAN, ISLE OF",	"IM"},
+{"MARSHALL ISLANDS",	"MH"},
+{"MARTINIQUE",		"MQ"},
+{"MAURITANIA",		"MR"},
+{"MAURITIUS",		"MU"},
+{"MAYOTTE",		"YT"},
+{"MEXICO",		"MX"},
+{"MICRONESIA, FEDERATED STATES OF",		"FM"},
+{"MOLDOVA, REPUBLIC OF",		"MD"},
+{"MONACO",		"MC"},
+{"MONGOLIA",		"MN"},
+{"MONTENEGRO",		"ME"},
+{"MONTSERRAT",		"MS"},
+{"MOROCCO",		"MA"},
+{"MOZAMBIQUE",		"MZ"},
+{"MYANMAR",		"MM"},
+{"NAMIBIA",		"NA"},
+{"NAURU",		"NR"},
+{"NEPAL",		"NP"},
+{"NETHERLANDS",		"NL"},
+{"NETHERLANDS ANTILLES",		"AN"},
+{"NEW CALEDONIA",	"NC"},
+{"NEW ZEALAND",		"NZ"},
+{"NICARAGUA",		"NI"},
+{"NIGER",		"NE"},
+{"NIGERIA",		"NG"},
+{"NIUE",		"NU"},
+{"NORFOLK ISLAND",		"NF"},
+{"NORTHERN MARIANA ISLANDS",		"MP"},
+{"NORWAY",		"NO"},
+{"OMAN",		"OM"},
+{"PAKISTAN",		"PK"},
+{"PALAU",		"PW"},
+{"PALESTINIAN TERRITORY, OCCUPIED",		"PS"},
+{"PANAMA",		"PA"},
+{"PAPUA NEW GUINEA",	"PG"},
+{"PARAGUAY",		"PY"},
+{"PERU",		"PE"},
+{"PHILIPPINES",		"PH"},
+{"PITCAIRN",		"PN"},
+{"POLAND",		"PL"},
+{"PORTUGAL",		"PT"},
+{"PUERTO RICO",		"PR"},
+{"QATAR",		"QA"},
+{"Q1",		"Q1"},
+{"REUNION",		"RE"},
+{"ROMANIA",		"RO"},
+{"RUSSIAN FEDERATION",	"RU"},
+{"RWANDA",		"RW"},
+{"SAINT HELENA",	"SH"},
+{"SAINT KITTS AND NEVIS",		"KN"},
+{"SAINT LUCIA",		"LC"},
+{"SAINT PIERRE AND MIQUELON",		"PM"},
+{"SAINT VINCENT AND THE GRENADINES",		"VC"},
+{"SAMOA",		"WS"},
+{"SAN MARINO",		"SM"},
+{"SAINT MARTIN",	"MF"},
+{"SAO TOME AND PRINCIPE",		"ST"},
+{"SAUDI ARABIA",	"SA"},
+{"SENEGAL",		"SN"},
+{"SERBIA",		"RS"},
+{"SEYCHELLES",		"SC"},
+{"SIERRA LEONE",	"SL"},
+{"SINGAPORE",		"SG"},
+{"SLOVAKIA",		"SK"},
+{"SLOVENIA",		"SI"},
+{"SOLOMON ISLANDS",	"SB"},
+{"SOMALIA",		"SO"},
+{"SOUTH AFRICA",	"ZA"},
+{"SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS",		"GS"},
+{"SPAIN",		"ES"},
+{"SRI LANKA",		"LK"},
+{"SUDAN",		"SD"},
+{"SURINAME",		"SR"},
+{"SVALBARD AND JAN MAYEN",		"SJ"},
+{"SWAZILAND",		"SZ"},
+{"SWEDEN",		"SE"},
+{"SWITZERLAND",		"CH"},
+{"SYRIAN ARAB REPUBLIC",		"SY"},
+{"TAIWAN, PROVINCE OF CHINA",		"TW"},
+{"TAJIKISTAN",		"TJ"},
+{"TANZANIA, UNITED REPUBLIC OF",		"TZ"},
+{"THAILAND",		"TH"},
+{"TIMOR-LESTE (EAST TIMOR)",		"TL"},
+{"TOGO",		"TG"},
+{"TOKELAU",		"TK"},
+{"TONGA",		"TO"},
+{"TRINIDAD AND TOBAGO",	"TT"},
+{"TRISTAN DA CUNHA",	"TA"},
+{"TUNISIA",		"TN"},
+{"TURKEY",		"TR"},
+{"TURKMENISTAN",	"TM"},
+{"TURKS AND CAICOS ISLANDS",		"TC"},
+{"TUVALU",		"TV"},
+{"UGANDA",		"UG"},
+{"UKRAINE",		"UA"},
+{"UNITED ARAB EMIRATES",		"AE"},
+{"UNITED KINGDOM",	"GB"},
+{"UNITED STATES",	"US"},
+{"UNITED STATES MINOR OUTLYING ISLANDS",		"UM"},
+{"URUGUAY",		"UY"},
+{"UZBEKISTAN",		"UZ"},
+{"VANUATU",		"VU"},
+{"VENEZUELA",		"VE"},
+{"VIET NAM",		"VN"},
+{"VIRGIN ISLANDS, BRITISH",		"VG"},
+{"VIRGIN ISLANDS, U.S.",		"VI"},
+{"WALLIS AND FUTUNA",	"WF"},
+{"WESTERN SAHARA",	"EH"},
+{"YEMEN",		"YE"},
+{"YUGOSLAVIA",		"YU"},
+{"ZAMBIA",		"ZM"},
+{"ZIMBABWE",		"ZW"},
+{"RADAR CHANNELS",	"RDR"},
+{"ALL CHANNELS",	"ALL"},
+{NULL,			NULL}
+};
+
+static int
+wl_ptk_start(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *str;
+	int buf_len;
+	int str_len;
+	int rc;
+	int count;
+	struct wl_ptk_start_iov_v1 *ptk_start_args;
+
+	UNUSED_PARAMETER(cmd);
+
+	count = ARGCNT(argv);
+
+	/*
+	** Set the attributes.
+	*/
+	if (count < 5) {
+		fprintf(stderr, "<sec-type> <peer_addr> <pmk> <role> expected\n");
+		rc = -1;
+		goto exit;
+	}
+
+	str = "ptk_start";
+	str_len = strlen(str);
+	strncpy(buf, str, str_len);
+	buf[ str_len ] = '\0';
+
+	ptk_start_args = (struct wl_ptk_start_iov_v1 *) (buf + str_len + 1);
+	ptk_start_args->sec_type = strtoul(*(argv + 1), NULL, 0); /* WL_PTK_START_SEC_TYPE_PMK */
+	if (!wl_ether_atoe(*(argv + 2), &ptk_start_args->peer_addr)) {
+		fprintf(stderr, "awdl ranging config mac addr err\n");
+		rc = -1;
+		goto exit;
+	}
+	ptk_start_args->tlvs[0].id = WL_PTK_START_TLV_PMK;
+	ptk_start_args->tlvs[0].len = strlen(*(argv+3));
+	strncpy((char*)ptk_start_args->tlvs[0].data, *(argv+3), ptk_start_args->tlvs[0].len);
+	printf("PMK[len = %d]: %s\n", ptk_start_args->tlvs[0].len,
+	(char*)ptk_start_args->tlvs[0].data);
+	ptk_start_args->role = strtoul(*(argv + 4), NULL, 0);   /* WL_PTK_START_SEC_TYPE_PMK */
+
+	buf_len = str_len + 1 + sizeof(struct wl_ptk_start_iov_v1) +  ptk_start_args->tlvs[0].len;
+	rc = wlu_set(wl,
+		WLC_SET_VAR,
+		buf,
+		buf_len);
+exit:
+	return (rc);
+}
+
+void
+wl_print_mcsset(char *mcsset)
+{
+	int i;
+
+	printf("MCS SET : [ ");
+	for (i = 0; i < (MCSSET_LEN * 8); i++)
+		if (isset(mcsset, i))
+			printf("%d ", i);
+	printf("]\n");
+}
+
+static void
+wl_print_vhtmcsset(uint16 *mcsset)
+{
+	int i, j;
+
+	for (i = 0; i < VHT_CAP_MCS_MAP_NSS_MAX; i++) {
+		if (mcsset[i]) {
+			if (i == 0)
+				printf("VHT SET : ");
+			else
+				printf("        : ");
+			/* std MCS 0-9 and prop MCS 10-11 */
+			for (j = 0; j <= 11; j++)
+				if (isbitset(mcsset[i], j))
+					printf("%dx%d ", j, i + 1);
+			printf("\n");
+		} else {
+			break;
+		}
+	}
+}
+
+static void
+wl_print_txbf_mcsset(char *mcsset, char *prefix)
+{
+	int i;
+
+	printf("%s MCS : [ ", prefix);
+	for (i = 0; i < (TXBF_RATE_MCS_ALL * 8); i++)
+		if (isset(mcsset, i))
+			printf("%d ", i);
+	printf("]\n");
+}
+
+static void
+wl_print_txbf_vhtmcsset(uint16 *mcsset, char *prefix)
+{
+	int i, j;
+
+	for (i = 0; i < TXBF_RATE_VHT_ALL; i++) {
+		if (mcsset[i]) {
+			if (i == 0)
+				printf("%s VHT : ", prefix);
+			else
+				printf("        : ");
+			for (j = 0; j <= 11; j++)
+				if (isbitset(mcsset[i], j))
+					printf("%dx%d ", j, i + 1);
+			printf("\n");
+		} else {
+			break;
+		}
+	}
+}
+
+static int
+wl_assertlog(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err;
+	int i;
+	char *log_p = NULL;
+	assertlog_results_t *results;
+	void *ptr = NULL;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc > 1)
+		return BCME_USAGE_ERROR;
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return err;
+
+	results = (assertlog_results_t *)buf;
+
+	printf("get external assert logs: %d\n", results->num);
+	if (!results->num)
+		return 0;
+
+	if (results->version != ASSERTLOG_CUR_VER) {
+		printf("Version mismatch: version = 0x%x, expected 0x%x\n",
+			results->version, ASSERTLOG_CUR_VER);
+		return 0;
+	}
+
+	log_p = (char *)&results->logs[0];
+
+	printf("id: \ttime(ms) \tstring\n");
+	for (i = 0; i < (int)results->num; i++) {
+		printf("%d: \t%d \t%s", i, ((assert_record_t *)log_p)->time,
+			((assert_record_t *)log_p)->str);
+		log_p += results->record_len;
+	}
+
+	return 0;
+}
+
+static const char *
+cca_level(int score, int med, int hi)
+{
+	if (score < med)
+		return ("Low");
+	if (score >= med && score < hi)
+		return ("Medium");
+	if (score >= hi)
+		return ("High");
+	return NULL;
+}
+
+static const char *cca_errors[] = {
+	"No error",
+	"Preferred band",
+	"Dwell Duration too low",
+	"Channel prefs",
+	"Interference too high",
+	"Only 1 channel inoput"
+};
+static void
+free_cca_array(cca_congest_channel_req_t **favg, int favg_chan_elts)
+{
+	int i;
+
+	if (favg == NULL)
+		{
+		return;
+		}
+	for (i = 0; i < favg_chan_elts; i++) {
+		if (favg[i] != NULL) {
+			free(favg[i]);
+			favg[i] = NULL;
+		}
+	}
+	if (favg != NULL) {
+		free(favg);
+		favg = NULL;
+	}
+}
+static int
+wl_cca_get_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	cca_congest_channel_req_t *results;
+	cca_congest_channel_req_t req;
+	cca_congest_t *chptr;
+	cca_congest_channel_req_t **avg = NULL, **new_avg = NULL; /* Max num of channels */
+	void *ptr = NULL;
+	char *param, *val_p;
+	int base, limit, i, channel, err = 0;
+	int ibss_per, obss_per, inter_per, val;
+	const char *ibss_lvl = NULL;
+	const char *obss_lvl = NULL;
+	const char *inter_lvl = NULL;
+	int tmp_channel;
+	chanspec_t new_chanspec, cur_chanspec;
+	bool do_individ = FALSE;
+	bool do_analyze = TRUE;
+	bool curband = FALSE;
+	int avg_chan_idx = 0, avg_chan_elts = 40;
+	uint32 flags;
+	int j;
+
+
+	req.num_secs = 10;
+	tmp_channel = 0xff;
+
+	argv++;
+
+	/* Parse args */
+	while ((param = *argv++) != NULL) {
+		if (stricmp(param, "-n") == 0) {
+			do_analyze = FALSE;
+			continue;
+		}
+		if (stricmp(param, "-i") == 0) {
+			do_individ = TRUE;
+			continue;
+		}
+		if (stricmp(param, "-curband") == 0) {
+			curband = TRUE;
+			continue;
+		}
+
+		if ((val_p = *argv++) == NULL) {
+			printf("Need value following %s\n", param);
+			return BCME_USAGE_ERROR;
+		}
+		if (stricmp(param, "-c") == 0) {
+			tmp_channel = (int)strtoul(val_p, NULL, 0);
+		}
+
+		if (stricmp(param, "-cs") == 0) {
+			if ((new_chanspec = wf_chspec_aton(val_p)))
+				tmp_channel = wf_chspec_ctlchan(new_chanspec);
+		}
+
+		if (stricmp(param, "-s") == 0) {
+			req.num_secs = (int)strtoul(val_p, NULL, 0);
+			if (req.num_secs == 0 || req.num_secs > MAX_CCA_SECS) {
+				printf("%d: Num of seconds must be <= %d\n",
+					req.num_secs, MAX_CCA_SECS);
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	if (tmp_channel == 0) {
+		/* do all channels */
+		base = 1; limit = MAXCHANNEL;
+	} else {
+		/* Use current channel as default if none specified */
+		if (tmp_channel == 0xff) {
+			if ((err = wlu_iovar_getint(wl, "chanspec", (int*)&val)) < 0) {
+				printf("CCA: Can't get currrent chanspec\n");
+				return err;
+			}
+			cur_chanspec = wl_chspec32_from_driver(val);
+			tmp_channel = wf_chspec_ctlchan(cur_chanspec);
+			printf("Using channel %d\n", tmp_channel);
+		}
+		base = limit = tmp_channel;
+	}
+
+	avg = (cca_congest_channel_req_t **)
+		calloc(1, sizeof(cca_congest_channel_req_t*) * avg_chan_elts);
+	if (avg == NULL) {
+		printf("unable to allocate memory\n");
+		return BCME_NOMEM;
+	}
+
+	for (channel = base; channel <= limit; channel++) {
+
+		/* Get stats for each channel */
+		req.chanspec = CH20MHZ_CHSPEC(channel);
+		req.chanspec = wl_chspec_to_driver(req.chanspec);
+		if ((err = wlu_var_getbuf(wl, cmd->name, &req, sizeof(req), &ptr)) < 0) {
+		goto func_exit;
+		}
+
+		results = (cca_congest_channel_req_t *)ptr;
+		results->chanspec = wl_chspec_from_driver(results->chanspec);
+		if (results->chanspec == 0 || results->num_secs == 0)
+			continue;
+
+		if (results->num_secs > MAX_CCA_SECS) {
+			printf("Bogus num of seconds returned %d\n", results->num_secs);
+			err = -1;
+			goto func_exit;
+		}
+
+		/* Summarize and save summary for this channel */
+		if (avg_chan_idx >= avg_chan_elts) {
+			new_avg = (cca_congest_channel_req_t **)calloc
+			(1, sizeof(cca_congest_channel_req_t*) * (avg_chan_elts + 10));
+
+			if (new_avg == NULL) {
+				printf("unable to allocate memory\n");
+				err = BCME_NOMEM;
+				goto func_exit;
+			}
+			memcpy(new_avg, avg, avg_chan_elts);
+			free_cca_array(avg, avg_chan_elts);
+			avg_chan_elts += 10;
+			avg = new_avg;
+			new_avg = NULL;
+		}
+
+		avg[avg_chan_idx] = (cca_congest_channel_req_t *)
+			malloc(sizeof(cca_congest_channel_req_t));
+		if (avg[avg_chan_idx] == NULL) {
+			printf("unable to allocate memory\n");
+			err = BCME_NOMEM;
+			goto func_exit;
+		}
+		cca_per_chan_summary(results, avg[avg_chan_idx], 1);
+		if (avg[avg_chan_idx]->num_secs)
+			avg_chan_idx++;
+
+		/* printf stats for each second of each channel */
+		if (do_individ) {
+			if (channel == base)
+				printf("chan dur      ibss           obss"
+					"           interf       time\n");
+			for (i = 0; i < results->num_secs; i++) {
+				chptr = &results->secs[i];
+				if (chptr->duration) {
+					/* Percentages */
+					ibss_per = chptr->congest_ibss * 100 /chptr->duration;
+					obss_per = chptr->congest_obss * 100 /chptr->duration;
+					inter_per = chptr->interference * 100 /chptr->duration;
+					/* Levels */
+					ibss_lvl = cca_level(ibss_per, IBSS_MED, IBSS_HI);
+					obss_lvl = cca_level(obss_per, OBSS_MED, OBSS_HI);
+					inter_lvl = cca_level(inter_per, INTERFER_MED, INTERFER_HI);
+
+				printf("%-3u %4d %4u %2d%% %-6s %4u %2d%% %-6s %4u %2d%% %-6s %d\n",
+					CHSPEC_CHANNEL(results->chanspec),
+					chptr->duration,
+					chptr->congest_ibss, ibss_per, ibss_lvl,
+					chptr->congest_obss, obss_per, obss_lvl,
+					chptr->interference, inter_per, inter_lvl,
+					chptr->timestamp);
+				}
+			}
+		}
+	}
+
+	/* Print summary stats of each channel */
+	printf("Summaries:\n");
+	printf("chan dur      ibss           obss             interf     num seconds\n");
+	for (j = 0; j < avg_chan_idx; j++) {
+		/* Percentages */
+		ibss_per = avg[j]->secs[0].congest_ibss;
+		obss_per = avg[j]->secs[0].congest_obss;
+		inter_per = avg[j]->secs[0].interference;
+		/* Levels */
+		ibss_lvl = cca_level(ibss_per, IBSS_MED, IBSS_HI);
+		obss_lvl = cca_level(obss_per, OBSS_MED, OBSS_HI);
+		inter_lvl = cca_level(inter_per, INTERFER_MED, INTERFER_HI);
+
+		if (avg[j]->num_secs) {
+			printf("%-3u %4d %4s %2d%% %-6s %4s %2d%% %-6s %4s %2d%% %-6s %d\n",
+				CHSPEC_CHANNEL(avg[j]->chanspec),
+				avg[j]->secs[0].duration,
+				"", avg[j]->secs[0].congest_ibss, ibss_lvl,
+				"", avg[j]->secs[0].congest_obss, obss_lvl,
+				"", avg[j]->secs[0].interference, inter_lvl,
+				avg[j]->num_secs);
+		}
+	}
+
+	if (!do_analyze) {
+		goto func_exit;
+	}
+
+	if ((err = wlu_iovar_getint(wl, "chanspec", (int *)&val)) < 0) {
+		printf("CCA: Can't get currrent chanspec\n");
+		goto func_exit;
+	}
+	cur_chanspec = wl_chspec32_from_driver(val);
+	flags = 0;
+	if (curband) {
+		if (CHSPEC_IS5G(cur_chanspec))
+			flags |= CCA_FLAG_5G_ONLY;
+		if (CHSPEC_IS2G(cur_chanspec))
+			flags |= CCA_FLAG_2G_ONLY;
+	}
+
+	if ((err = cca_analyze(avg,  avg_chan_idx, flags, &new_chanspec)) != 0) {
+		if (err > 0) {
+			printf("Cannot find a good channel due to: %s\n", cca_errors[err]);
+			err = BCME_ERROR;
+		}
+		goto func_exit;
+	}
+	printf("Recommended channel: %d\n", wf_chspec_ctlchan(new_chanspec));
+
+	func_exit:
+	free_cca_array(avg, avg_chan_elts);
+
+	return err;
+}
+
+static int
+wl_txdelay_params(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	txdelay_params_t param;
+	int argc;
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get current txdelay params */
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &param,
+			(sizeof(txdelay_params_t)))) < 0)
+			return (err);
+
+		printf("Txdelay params: ratio[%d] cnt[%d] period[%d] tune[%d]\n",
+			param.ratio, param.cnt,	param.period, param.tune);
+	}
+	else {
+		char *endptr;
+		/* Validate num of entries */
+		for (argc = 0; argv[argc]; argc++);
+		if (argc != 4)
+			return BCME_USAGE_ERROR;
+
+		argc = 0;
+		param.ratio = strtol(argv[argc], &endptr, 0);
+		argc++;
+		param.cnt = strtol(argv[argc], &endptr, 0);
+		argc++;
+		param.period = strtol(argv[argc], &endptr, 0);
+		argc++;
+		param.tune = strtol(argv[argc], &endptr, 0);
+
+		/* Set txdelay params */
+		err = wlu_iovar_set(wl, cmd->name, (void *) &param,
+			(sizeof(txdelay_params_t)));
+	}
+	return (err);
+}
+
+static void
+dlystat_dump(txdelay_stats_t *txdelay_stats)
+{
+	const char *const aci_names[] = { "AC_BE", "AC_BK", "AC_VI", "AC_VO"};
+	uint32 i, last, s;
+	uint ac;
+	uint32 sum;
+	uint32 max_val, total = 0;
+	scb_delay_stats_t *delay_stats;
+	struct ether_addr *ea;
+	uint32 dlystat_cnt = txdelay_stats->scb_cnt;
+
+	if (txdelay_stats->full_result == TXDELAY_STATS_PARTIAL_RESULT) {
+		printf("\tThis is partial results for SCBs\n"
+				"\tcaused by insuffient IOCTL buffer\n"
+				"\tIf you want to get full SCBs\n"
+				"\tPlease use iteration for each of specific mac_address\n"
+				"\twhich can be got from other iovars such as assoclist\n");
+	}
+
+	for (s = 0; s < dlystat_cnt; s++) {
+		ea = &txdelay_stats->scb_delay_stats[s].ea;
+		printf("[SCB%d]\n\t%s\n", s, wl_ether_etoa(ea));
+		/* Report Latency and packet loss statistics (for each AC) */
+		for (ac = 0; ac < AC_COUNT; ac++) {
+
+			delay_stats = txdelay_stats->scb_delay_stats[s].dlystats + ac;
+			for (i = 0, total = 0, sum = 0; i < SCB_RETRY_SHORT_DEF; i++) {
+				total += delay_stats->txmpdu_cnt[i];
+				sum += delay_stats->delay_sum[i];
+			}
+			if (total) {
+				printf("%s:  PLoss %d/%d (%d%%)\n",
+						aci_names[ac], delay_stats->txmpdu_lost, total,
+						(delay_stats->txmpdu_lost * 100) / total);
+				printf("\tDelay stats in usec (avg/min/max): %d %d %d\n",
+						CEIL(sum, total), delay_stats->delay_min,
+						delay_stats->delay_max);
+				printf("\tTxcnt Hist    :");
+				for (i = 0; i < SCB_RETRY_SHORT_DEF; i++) {
+					printf("  %d", delay_stats->txmpdu_cnt[i]);
+				}
+				printf("\n\tDelay vs Txcnt:");
+				for (i = 0; i < SCB_RETRY_SHORT_DEF; i++) {
+					if (delay_stats->txmpdu_cnt[i])
+						printf("  %d", delay_stats->delay_sum[i] /
+								delay_stats->txmpdu_cnt[i]);
+					else
+						printf("  -1");
+				}
+				printf("\n");
+
+				for (i = 0, max_val = 0, last = 0; i < WLPKTDLY_HIST_NBINS; i++) {
+					max_val += delay_stats->delay_hist[i];
+					if (delay_stats->delay_hist[i]) last = i;
+				}
+				last = 8 * (last/8 + 1) - 1;
+				if (max_val) {
+					printf("\tDelay Hist \n\t\t:");
+					for (i = 0; i <= last; i++) {
+						printf(" %d(%d%%)", delay_stats->
+								delay_hist[i],
+								(delay_stats->delay_hist[i] * 100)
+								/ max_val);
+						if ((i % 8) == 7 && i != last)
+							printf("\n\t\t:");
+					}
+				}
+				printf("\n");
+			}
+		}
+		printf("\n");
+	}
+}
+
+static int
+wl_dlystats(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	txdelay_stats_t *dlystats_param;
+	txdelay_stats_t *delay_stats;
+
+	dlystats_param = (txdelay_stats_t *)malloc(sizeof(*dlystats_param));
+
+	if (dlystats_param == NULL) {
+		return BCME_NOMEM;
+	}
+
+	memset(dlystats_param, 0, sizeof(*dlystats_param));
+	dlystats_param->version = TXDELAY_STATS_VERSION;
+
+	if (*++argv) {
+		if (!wl_ether_atoe(*argv, &dlystats_param->scb_delay_stats[0].ea)) {
+			ret = BCME_USAGE_ERROR;
+			goto EXIT;
+		}
+		dlystats_param->scb_cnt = 1;
+	} else {
+		dlystats_param->scb_cnt = MAX_TXDELAY_STATS_SCBS;
+	}
+
+	ret = wlu_iovar_getbuf(wl, cmd->name, dlystats_param, sizeof(*dlystats_param),
+			buf, WLC_IOCTL_MAXLEN);
+
+
+	if (ret) {
+		if (ret == BCME_VERSION) {
+			printf("txdelay_stats_t version is mismatched\n");
+		}
+		goto EXIT;
+	}
+
+	delay_stats = (txdelay_stats_t *)buf;
+	dlystat_dump(delay_stats);
+
+EXIT:
+	free(dlystats_param);
+	return ret;
+}
+
+static int
+wl_dlystats_clear(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+
+	UNUSED_PARAMETER(argv);
+
+	err = wlu_iovar_set(wl, cmd->name, buf, 0);
+
+	return err;
+}
+
+static int
+wl_intfer_params(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_intfer_params_t param;
+	int		argc;
+	char 	*endptr = NULL;
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get current txdelay params */
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &param,
+			(sizeof(wl_intfer_params_t)))) < 0)
+			goto error;
+
+		if (param.version != INTFER_VERSION) {
+			printf("Interference params structure version (%d) is not the "
+				"version (%d) supported by this tool",
+				INTFER_VERSION, param.version);
+			err = BCME_USAGE_ERROR;
+		}
+		else
+			printf("Intference params: period[%x] cnt[%x] txfail_thresh[%x]"
+				" tcptxfail_thresh[%x]\n", param.period, param.cnt,
+				param.txfail_thresh, param.tcptxfail_thresh);
+	}
+	else {
+		/* Validate num of entries */
+		err = BCME_USAGE_ERROR;
+
+		for (argc = 0; argv[argc]; argc++);
+		if (argc != 4)
+			goto error;
+
+		param.period = (uint8)strtol(argv[0], &endptr, 0);
+		if (*endptr != '\0')
+		    goto error;
+
+		param.cnt = (uint8)strtol(argv[1], &endptr, 0);
+		if (*endptr != '\0')
+		    goto error;
+
+		param.txfail_thresh = (uint8)strtol(argv[2], &endptr, 0);
+		if (*endptr != '\0')
+		    goto error;
+
+		param.tcptxfail_thresh = (uint8)strtol(argv[3], &endptr, 0);
+		if (*endptr != '\0')
+		    goto error;
+
+		/* Set intfer params */
+		param.version = INTFER_VERSION;
+		err = wlu_iovar_set(wl, cmd->name, (void *) &param,
+			(sizeof(wl_intfer_params_t)));
+	}
+error:
+	return (err);
+}
+
+static int
+wl_rpmt(void *wl, cmd_t *cmd, char **argv)
+{
+	int count;
+	int len;
+	char *endptr;
+	uint32 val;
+
+	argv ++;
+
+	count = ARGCNT(argv);
+	if (count != 2) {
+		return BCME_USAGE_ERROR;
+	}
+
+	strcpy(buf, cmd->name);
+	len = strlen(buf) + 1;
+
+	val = htod32(strtoul(argv[0], &endptr, 0));
+	memcpy(&buf[len], &val, sizeof(uint32));
+	len += sizeof(uint32);
+	val = htod32(strtoul(argv[1], &endptr, 0));
+	memcpy(&buf[len], &val, sizeof(uint32));
+	len += sizeof(uint32);
+
+	return wlu_set(wl, WLC_SET_VAR, buf, len);
+}
+
+static int
+wl_tsf(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "tsf";
+	struct tsf {
+		uint32 low;
+		uint32 high;
+	} tsf_buf;
+	char *endptr;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* toss the command name */
+	argv++;
+
+	if (*argv == NULL) {
+		/* get */
+		err = wlu_iovar_get(wl, cmdname, &tsf_buf, sizeof(tsf_buf));
+		if (err)
+			return err;
+		printf("0x%08X 0x%08X\n", htod32(tsf_buf.high), htod32(tsf_buf.low));
+	} else {
+		/* set */
+		if (argv[1] == NULL)
+			return BCME_USAGE_ERROR;
+
+		tsf_buf.high = (uint32)strtoul(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "%s: %s: error parsing \"%s\" as an integer\n",
+			        wlu_av0, cmdname, *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		argv++;
+		tsf_buf.low = (uint32)strtoul(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "%s: %s: error parsing \"%s\" as an integer\n",
+			        wlu_av0, cmdname, *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		tsf_buf.low = dtoh32(tsf_buf.low);
+		tsf_buf.high = dtoh32(tsf_buf.high);
+
+		err = wlu_iovar_set(wl, cmdname, &tsf_buf, sizeof(tsf_buf));
+		if (err)
+			return err;
+	}
+
+	return err;
+}
+
+static int wl_event_log_set_init(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "event_log_set_init";
+	wl_el_set_params_t pars;
+	int argc;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc != 3) {
+		return BCME_USAGE_ERROR;
+	}
+
+	memset(&pars, 0, sizeof(wl_el_set_params_t));
+	pars.set = atoi(argv[1]);
+	pars.size = htod32(atoi(argv[2]));
+
+	err = wlu_iovar_set(wl, cmdname, &pars, sizeof(wl_el_set_params_t));
+
+	return err;
+}
+
+static int wl_event_log_set_expand(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "event_log_set_expand";
+	wl_el_set_params_t pars;
+	int argc;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc != 3) {
+		return BCME_USAGE_ERROR;
+	}
+
+	memset(&pars, 0, sizeof(wl_el_set_params_t));
+	pars.set = atoi(argv[1]);
+	pars.size = htod32(atoi(argv[2]));
+
+	err = wlu_iovar_set(wl, cmdname, &pars, sizeof(wl_el_set_params_t));
+
+	return err;
+}
+
+static int wl_event_log_set_shrink(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "event_log_set_shrink";
+	wl_el_set_params_t pars;
+	int argc;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if ((argc < 2) || (argc > 3)) {
+		return BCME_USAGE_ERROR;
+	}
+
+	memset(&pars, 0, sizeof(wl_el_set_params_t));
+	pars.set = atoi(argv[1]);
+	if (argc == 3)
+		pars.size = htod32(atoi(argv[2]));
+
+	err = wlu_iovar_set(wl, cmdname, &pars, sizeof(wl_el_set_params_t));
+
+	return err;
+}
+
+static int wl_event_log_tag_control(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "event_log_tag_control";
+	wl_el_tag_params_t pars;
+	int argc;
+	int err;
+	int flags = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc < 4) {
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+
+	memset(&pars, 0, sizeof(wl_el_tag_params_t));
+	pars.tag = htod16(atoi(*argv++));
+	pars.set = atoi(*argv++);
+
+	while (*argv) {
+		if (!strcmp(*argv, "LOG")) {
+			flags |= EVENT_LOG_TAG_FLAG_LOG;
+		} else if (!strcmp(*argv, "PRINT")) {
+			flags |= EVENT_LOG_TAG_FLAG_PRINT;
+		} else if (!strcmp(*argv, "NONE")) {
+			flags |= EVENT_LOG_TAG_FLAG_NONE;
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+		argv++;
+	}
+
+	pars.flags = flags;
+
+	err = wlu_iovar_set(wl, cmdname, &pars, sizeof(pars));
+
+	return err;
+}
+
+static int wl_event_log_get(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "event_log_get";
+	char *set_arg = NULL;
+	wl_el_set_params_t pars;
+	int argc;
+	int err = BCME_OK;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argv++, argc = 0; argv[argc]; argc++);
+
+	memset(&pars, 0, sizeof(wl_el_set_params_t));
+
+	/* Look for -f */
+	if ((*argv) && !strcmp(*argv, "-f")) {
+		set_arg = *++argv;
+		if (!set_arg)
+		{
+			fprintf(stderr, "Missing argument to -f option\n");
+			return BCME_USAGE_ERROR;
+		}
+		/* Ignore other arguments */
+		pars.set = atoi(set_arg);
+		pars.size = 0;
+
+		/* cause a flush of an event log buffer associated with this particular
+		 * set. This flush is caused by trigerring logtrace
+		 */
+		err = wlu_iovar_set(wl, cmdname, &pars, sizeof(wl_el_set_params_t));
+	}
+	else
+	{
+		fprintf(stderr, "Missing -f option. Currently -g <set> -s <buf_len> "
+			"options are not supported\n");
+		err = BCME_USAGE_ERROR;
+	}
+	return err;
+}
+
+#ifdef SERDOWNLOAD
+
+static int dhd_rwl_download(void *dhd, char *fwname, char *command);
+
+int
+rwl_download(void *dhd, cmd_t *cmd, char **argv)
+{
+	char *fname = NULL;
+	char *vname = NULL;
+	int ret = 0;
+	UNUSED_PARAMETER(cmd);
+	if (!*++argv) {
+		fprintf(stderr, "Require dongle image filename \n");
+		ret = -1;
+		goto exit;
+	}
+	else {
+		fname = *argv;
+		if (debug)
+			printf("dongle image file is %s\n", fname);
+	}
+	if (!*++argv) {
+		fprintf(stderr, "vars filename missing, assuming no var file\n");
+		ret = -1;
+		goto exit;
+	}
+	else {
+		vname = *argv;
+		if (debug)
+			printf("dongle var file is %s\n", vname);
+	}
+	ret = dhd_rwl_download(dhd, fname, "download");
+	printf("ret = %d\n", ret);
+
+	if (ret == 0)
+		ret = dhd_rwl_download(dhd, vname, "nvdownload");
+exit:
+	return ret;
+}
+
+static int
+dhd_rwl_download(void *dhd, char *fwfile, char *command)
+{
+	unsigned char *bufp  = NULL;
+	int len = 0, length = 0;
+	int ret = 0;
+	char *p;
+	unsigned char *buff = NULL;
+	int remained_bytes;
+	uint32 start = 0;
+	FILE *fp = NULL;
+	struct stat finfo;
+	unsigned long status;
+
+	/* Open the firmware file */
+	if (!(fp = fopen(fwfile, "rb"))) {
+		perror(fwfile);
+		ret = -1;
+		goto exit;
+	}
+
+	if (stat(fwfile, &finfo)) {
+		printf("dhd_rwl_download: %s: %s\n", fwfile, strerror(errno));
+		ret = -1;
+		goto exit;
+	}
+
+	length = finfo.st_size;
+
+	if (length <= 0) {
+		ret = -1;
+		goto exit;
+	}
+
+	if ((bufp = malloc(length +4)) == NULL) {
+		printf("dhd_rwl_download: Unable to allowcate %d bytes!\n", len);
+		ret = -1;
+		goto exit;
+	}
+
+	/* Read the firmware file into the buffer */
+	status  = fread(bufp, sizeof(uint8), length, fp);
+
+	/* close the firmware file */
+	fclose(fp);
+	fp = NULL;
+
+	if ((int)status < length) {
+		printf("dhd_rwl_download: Short read in %s!\n", fwfile);
+		ret = -1;
+		goto exit;
+	}
+
+
+	printf("Starting %s, total file length is %d\n", command, length);
+
+	/* do the download reset */
+	if ((ret = wlu_iovar_setint(dhd, command, TRUE))) {
+		fprintf(stderr, "dhd_rwl_download: failed to put dongle to download mode\n");
+		ret = -1;
+		goto exit;
+	}
+
+	buff = bufp;
+	remained_bytes = len = length;
+
+	while (remained_bytes > 0) {
+		printf(".");
+		p = buf;
+		memset(p, 0, WLC_IOCTL_MAXLEN);
+		strcpy(p, "membytes");
+		p += strlen("membytes") + 1;
+
+		memcpy(p, &start, sizeof(int));
+		p += sizeof(int);
+
+		if (remained_bytes >= MEMBLOCK)
+			len = MEMBLOCK;
+		else
+			len = remained_bytes;
+
+		memcpy(p, &len, sizeof(int));
+		p += sizeof(int);
+
+		memcpy(p, buff, len);
+		p += len;
+
+		if (debug) {
+			printf("sending %d bytes block: \n", (int)(p - buf));
+		}
+
+		ret = wlu_set(dhd, WLC_SET_VAR, &buf[0], (int) (p - buf));
+
+		if (ret) {
+			fprintf(stderr, "%s: error %d on writing %d membytes at 0x%08x\n",
+				"wl_set()", ret, len, start);
+			goto exit;
+		}
+
+		start += len;
+		buff += len;
+		remained_bytes -= len;
+	}
+	printf("\n");
+
+	/* start running the downloaded code, download complete */
+	if ((ret = wlu_iovar_setint(dhd, command, FALSE))) {
+		fprintf(stderr, "dhd_rwl_download: failed to take dongle out of download mode\n");
+		goto exit;
+	}
+
+exit:
+	if (bufp)
+		free(bufp);
+
+	if (fp)
+		fclose(fp);
+
+	return ret;
+}
+
+/* Check that strlen("membytes")+1 + 2*sizeof(int32) + MEMBLOCK <= WLC_IOCTL_MAXLEN */
+#if (MEMBLOCK + 17 > WLC_IOCTL_MAXLEN)
+#error MEMBLOCK/WLC_IOCTL_MAXLEN sizing
+#endif
+
+static int dhd_hsic_download(void *dhd, char *fwname, char *nvname);
+static int ReadFiles(char *fwfile, char *nvfile, unsigned char ** buffer);
+static int check_file(unsigned char *headers);
+
+static char* chip_select = "none";
+
+int
+dhd_init(void *dhd, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv) {
+		fprintf(stderr, "Error: Missing require chip ID"
+			"<4325,  4329, 43291, 4330a1, 4330 or hsic>\n");
+		ret = BCME_USAGE_ERROR;
+	}
+	else if (strcmp(*argv, "4325") && strcmp(*argv, "4329") &&
+		strcmp(*argv, "43291") && strcmp(*argv, "4330") &&
+		strcmp(*argv, "4330a1") && strcmp(*argv, "hsic")) {
+		fprintf(stderr, "Error: Unsupported chip ID %s\n", *argv);
+		ret = BCME_BADARG;
+	}
+	else if ((ret = wlu_iovar_setbuf(dhd, "init", *argv, strlen(*argv) + 1,
+		buf, WLC_IOCTL_MAXLEN))) {
+		fprintf(stderr, "Error: %s: failed to initialize the dongle \n",
+		        "dhd_init()");
+	}
+	else
+		ret = 0;
+
+	if (ret == 0) {
+		if (!strcmp(*argv, "4325"))  {
+			fprintf(stdout, "4325 is the selected chip id\n");
+			chip_select = "4325";
+		} else if (!strcmp(*argv, "4329"))  {
+			fprintf(stdout, "4329 is the selected chip id\n");
+			chip_select = "4329";
+	        } else if (!strcmp(*argv, "43291"))  {
+			fprintf(stdout, "43291 is the selected chip id\n");
+		        chip_select = "43291";
+		} else if (!strcmp(*argv, "4330"))  {
+			fprintf(stdout, "4330b0 is the selected chip id\n");
+		        chip_select = "4330b0";
+		} else if (!strcmp(*argv, "4330a1"))  {
+			fprintf(stdout, "4330a1 is the selected chip id\n");
+		        chip_select = "4330a1";
+		} else if (!strcmp(*argv, "hsic"))  {
+			fprintf(stdout, "hsic interface is selected\n");
+		        chip_select = "hsic";
+		} else
+			chip_select = "none";
+	}
+
+	return ret;
+}
+
+int
+dhd_download(void *dhd, cmd_t *cmd, char **argv)
+{
+	char *fname = NULL;
+	char *vname = NULL;
+	uint32 start = 0;
+	uint32 last4bytes;
+	int ret = 0;
+	uint file_size;
+	int ram_size = 0, var_size, var_words, nvram_len, remained_bytes;
+	FILE *fp = NULL;
+	struct stat finfo;
+	char *bufp;
+	int len;
+	uint8 memblock[MEMBLOCK];
+	uint8 varbuf[WLC_IOCTL_MAXLEN];
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!strcmp(chip_select, "none")) {
+		fprintf(stderr, "chip init must be called before firmware download. \n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (!strcmp(chip_select, "4325")) {
+		fprintf(stdout, "using 4325 ram_info\n");
+		ram_size = RAM_SIZE_4325;
+	} else if (!strcmp(chip_select, "4329")) {
+		fprintf(stdout, "using 4329 ram_info\n");
+		ram_size = RAM_SIZE_4329;
+	} else if (!strcmp(chip_select, "43291")) {
+		fprintf(stdout, "using 43291 ram_info\n");
+		ram_size = RAM_SIZE_43291;
+	} else if (!strcmp(chip_select, "4330b0")) {
+		fprintf(stdout, "using 4330 b0 ram_info\n");
+		ram_size = RAM_SIZE_4330_b0;
+	} else if (!strcmp(chip_select, "4330a1")) {
+		fprintf(stdout, "using 4330a1 ram_info\n");
+		ram_size = RAM_SIZE_4330_a1;
+	} else if (!strcmp(chip_select, "hsic")) {
+		fprintf(stdout, "using hsic interface\n");
+	} else {
+		fprintf(stderr, "Error: unknown chip\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (!*++argv) {
+		fprintf(stderr, "Require dongle image filename \n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	else {
+		fname = *argv;
+		if (debug)
+			printf("dongle image file is %s\n", fname);
+	}
+
+	if (!*++argv) {
+		fprintf(stderr, "vars filename missing, assuming no var file\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+
+	}
+	else {
+		vname = *argv;
+		if (debug)
+			printf("dongle var file is %s\n", vname);
+	}
+
+
+	/* do the download on hsic */
+	/* merge the firmware and the nvram */
+	if (!strcmp(chip_select, "hsic")) {
+		/* the hsic firwmare and download code */
+		ret = dhd_hsic_download(dhd, fname, vname);
+		return ret;
+	}
+
+	if (!(fp = fopen(fname, "rb"))) {
+		perror(fname);
+		ret = BCME_BADARG;
+		goto exit;
+	}
+
+	if (stat(fname, &finfo)) {
+		perror(fname);
+		ret = -1;
+		goto exit;
+	}
+	file_size = finfo.st_size;
+	if (debug) {
+		printf("%s file_size=%d\n", fname, file_size);
+	}
+
+	/* do the download reset if not suppressed */
+	if ((ret = wlu_iovar_setint(dhd, "download", TRUE))) {
+		fprintf(stderr, "%s: failed to put dongle in download mode\n",
+				"dhd_iovar_setint()");
+		goto exit;
+	}
+
+	memset(memblock, 0, MEMBLOCK);
+
+	printf("downloading %s, file_size=%d\n", fname, file_size);
+
+	/* read the file and push blocks down to memory */
+	while ((len = fread(memblock, sizeof(uint8), MEMBLOCK, fp))) {
+		if (len < MEMBLOCK && !feof(fp)) {
+			fprintf(stderr, "%s: error reading file %s\n", "fread()", fname);
+			ret = -1;
+			goto exit;
+		}
+
+		if (debug) {
+			printf("memblock=\n%s\n", memblock);
+		}
+
+		bufp = buf;
+		memset(bufp, 0, WLC_IOCTL_MAXLEN);
+		strcpy(bufp, "membytes");
+		bufp += strlen("membytes") + 1;
+		memcpy(bufp, &start, sizeof(int));
+		bufp += sizeof(int);
+		memcpy(bufp, &len, sizeof(int));
+		bufp += sizeof(int);
+		memcpy(bufp, memblock, len);
+
+		ret = wl_set(dhd, WLC_SET_VAR, &buf[0], (bufp - buf + len));
+
+		if (ret) {
+			fprintf(stderr, "%s: error %d on writing %d membytes at 0x%08x\n",
+			        "wl_set()", ret, len, start);
+			goto exit;
+		}
+
+		start += len;
+		memset(memblock, 0, MEMBLOCK);
+	}
+
+	if (!feof(fp)) {
+		fprintf(stderr, "%s: error reading file %s\n", "feof()", fname);
+		ret = -1;
+		goto exit;
+	}
+	fclose(fp);
+	fp = NULL;
+
+	if (vname) {
+	/* download the vars file if specified */
+	/* read in the file */
+		if (!(fp = fopen(vname, "rb"))) {
+			perror(vname);
+			ret = BCME_BADARG;
+			goto exit;
+		}
+
+		if (stat(vname, &finfo)) {
+			perror(vname);
+			ret = -1;
+			goto exit;
+		}
+		file_size = finfo.st_size;
+
+		printf("downloading %s, file_size=%d\n", vname, file_size);
+
+		memset(varbuf, 0, WLC_IOCTL_MAXLEN);
+
+		/* read the file and push blocks down to memory */
+		if (fread(varbuf, 1, file_size, fp) != file_size) {
+			perror(fname);
+			ret = -1;
+			goto exit;
+		}
+
+		fclose(fp);
+		fp = NULL;
+
+		if (debug) {
+			printf("the original varbuf=%s\n", varbuf);
+		}
+
+		/* convert linefeeds to nuls */
+		nvram_len = process_nvram_vars((char*)&varbuf, file_size);
+		if (debug) {
+			printf("after process_nvram_vars(), %s nvram_len=%d\n%s\n",
+			vname, nvram_len, varbuf);
+		}
+		bufp = (char*)&varbuf + nvram_len;
+		*bufp++ = 0;
+
+		var_size = ROUNDUP(nvram_len + 1, 4);
+		/* calculate start address */
+		start = ram_size - var_size - 4;
+
+		if (debug) {
+			printf("var_size=%d, start=0x%0X\n", var_size, start);
+		}
+
+		/* need to send the last 4 bytes. */
+		var_words = var_size / 4;
+		last4bytes = (~var_words << 16) | (var_words & 0x0000FFFF);
+		last4bytes = htol32(last4bytes);
+
+		if (debug) {
+			printf("last4bytes=0x%0X\n", last4bytes);
+		}
+
+		bufp = (char*)&varbuf + var_size;
+		memcpy(bufp, &last4bytes, 4);
+
+		/* send down var_size+4 bytes with each time "membytes" MEMBLOCK bytes */
+		bufp = (char*)&varbuf;
+		remained_bytes = var_size + 4;
+
+		while (remained_bytes > 0) {
+			char *p;
+
+			p = buf;
+			memset(p, 0, WLC_IOCTL_MAXLEN);
+
+			strcpy(p, "membytes");
+			p += strlen("membytes") + 1;
+
+			memcpy(p, &start, sizeof(int));
+			p += sizeof(int);
+
+			if (remained_bytes >= MEMBLOCK) {
+				len = MEMBLOCK;
+			}
+			else
+				len = remained_bytes;
+
+			memcpy(p, &len, sizeof(int));
+			p += sizeof(int);
+
+			memcpy(p, bufp, len);
+			p += len;
+
+			if (debug) {
+				printf("sending %d bytes block:\n", (int)(p - buf));
+				printf("%s\n", buf);
+			}
+
+			ret = wl_set(dhd, WLC_SET_VAR, &buf[0], (p - buf));
+
+			if (ret) {
+				fprintf(stderr, "%s: error %d on writing %d membytes at 0x%08x\n",
+						"wl_set()", ret, len, start);
+				goto exit;
+			}
+
+			start += len;
+			bufp += len;
+			remained_bytes -= len;
+		}
+	}
+
+	/* start running the downloaded code if not suppressed */
+	if ((ret = wlu_iovar_setint(dhd, "download", FALSE))) {
+		fprintf(stderr, "%s: failed to take dongle out of download mode\n",
+				"dhd_iovar_setint()");
+		goto exit;
+	}
+
+exit:
+	if (fp)
+		fclose(fp);
+
+	return ret;
+}
+
+
+int
+dhd_upload(void *dhd, cmd_t *cmd, char **argv)
+{
+	char *fname = NULL;
+	uint32 start = 0;
+	uint32 size;
+	int ram_size;
+	FILE *fp = NULL;
+	uint len;
+	int ret = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!strcmp(chip_select, "none")) {
+		fprintf(stderr, "chip init must be called before firmware download. \n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (!strcmp(chip_select, "4325")) {
+		fprintf(stdout, "using 4325 ram_info\n");
+		ram_size = RAM_SIZE_4325;
+	} else if (!strcmp(chip_select, "4329")) {
+		fprintf(stdout, "using 4329 ram_info\n");
+		ram_size = RAM_SIZE_4329;
+	} else if (!strcmp(chip_select, "43291")) {
+		fprintf(stdout, "using 43291 ram_info\n");
+		ram_size = RAM_SIZE_43291;
+	} else if (!strcmp(chip_select, "4330b0")) {
+		fprintf(stdout, "using 4330 b0 ram_info\n");
+		ram_size = RAM_SIZE_4330_b0;
+	} else if (!strcmp(chip_select, "4330a1")) {
+		fprintf(stdout, "using 4330 a1 ram_info\n");
+		ram_size = RAM_SIZE_4330_a1;
+	} else {
+		fprintf(stderr, "Error: unknown chip\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	argv++;
+
+	if (debug) {
+		printf("argv=%s\n", *argv);
+	}
+
+	fname = *argv;
+
+	/* validate arguments */
+	if (!fname) {
+		fprintf(stderr, "filename required\n");
+		ret = BCME_BADARG;
+		goto exit;
+	}
+
+	if (!(fp = fopen(fname, "wb"))) {
+		perror(fname);
+		ret = BCME_BADARG;
+		goto exit;
+	}
+
+	/* default size to full RAM */
+	size = ram_size - start;
+
+	/* read memory and write to file */
+	while (size) {
+		char *ptr;
+		int params[2];
+
+		len = MIN(MEMBLOCK, size);
+
+		params[0] = start;
+		params[1] = len;
+		ret = wlu_iovar_getbuf(dhd, "membytes", params, 2 * sizeof(int),
+		(void**)&ptr, MEMBLOCK);
+		if (ret) {
+			fprintf(stderr, "dhd_upload(): failed reading %d membytes from 0x%08x\n",
+			        len, start);
+			break;
+		}
+
+		if (fwrite(ptr, sizeof(*ptr), len, fp) != len) {
+			fprintf(stderr, "dhd_upload(): error writing to file %s\n", fname);
+			ret = -1;
+			break;
+		}
+
+		start += len;
+		size -= len;
+	}
+
+	fclose(fp);
+exit:
+	return ret;
+}
+
+static int
+dhd_hsic_download(void *dhd, char *fwfile, char *nvfile)
+{
+	unsigned char *bufp  = NULL;
+	int len = 0, length = 0;
+	int ret = 0;
+	char *p;
+	unsigned char *buff = NULL;
+	int remained_bytes;
+	uint32 start = 0;
+
+	/* read and merge fw and nvram files */
+	length = ReadFiles(fwfile, nvfile, &bufp);
+	if (length <= 0) {
+		ret = -1;
+		goto exit;
+	}
+
+	printf("Starting download, total file length is %d\n", length);
+
+	/* do the download reset */
+	if ((ret = wlu_iovar_setint(dhd, "download", TRUE))) {
+		fprintf(stderr, "dhd_hsic_download: failed to put dongle to download mode\n");
+		goto exit;
+	}
+
+	buff = bufp;
+	remained_bytes = len = length;
+
+	while (remained_bytes > 0) {
+		printf(".");
+		p = buf;
+		memset(p, 0, WLC_IOCTL_MAXLEN);
+		strcpy(p, "membytes");
+		p += strlen("membytes") + 1;
+
+		memcpy(p, &start, sizeof(int));
+		p += sizeof(int);
+
+		if (remained_bytes >= MEMBLOCK)
+			len = MEMBLOCK;
+		else
+			len = remained_bytes;
+
+		memcpy(p, &len, sizeof(int));
+		p += sizeof(int);
+
+		memcpy(p, buff, len);
+		p += len;
+
+		if (debug) {
+			printf("sending %d bytes block: \n", (int)(p - buf));
+		}
+
+		ret = wlu_set(dhd, WLC_SET_VAR, &buf[0], (p - buf));
+
+		if (ret) {
+			fprintf(stderr, "%s: error %d on writing %d membytes at 0x%08x\n",
+				"wl_set()", ret, len, start);
+			goto exit;
+		}
+
+		start += len;
+		buff += len;
+		remained_bytes -= len;
+	}
+	printf("\n");
+
+	/* start running the downloaded code, download complete */
+	if ((ret = wlu_iovar_setint(dhd, "download", FALSE))) {
+		fprintf(stderr, "dhd_hsic_download: failed to take dongle out of download mode\n");
+		goto exit;
+	}
+
+exit:
+	if (bufp)
+		free(bufp);
+
+	return ret;
+}
+
+static int ReadFiles(char *fname, char *vname, unsigned char ** buffer)
+{
+	FILE *fp = NULL;
+	FILE *fp1 = NULL;
+	struct stat finfo;
+	uint8 *buf = NULL;
+	int len, fwlen, actual_len, nvlen = 0;
+	struct trx_header *hdr;
+	unsigned long status;
+	unsigned int pad;
+	unsigned int i;
+	int ret = -1;
+
+	/* Open the firmware file */
+	if (!(fp = fopen(fname, "rb"))) {
+		perror(fname);
+		ret = BCME_BADARG;
+		goto exit;
+	}
+
+	if (stat(fname, &finfo)) {
+		printf("dhd_download: %s: %s\n", fname, strerror(errno));
+		ret = -1;
+		goto exit;
+	}
+	len = fwlen = finfo.st_size;
+
+	/* Open nvram file */
+	if (!(fp1 = fopen(vname, "rb"))) {
+		perror(fname);
+		ret = BCME_BADARG;
+		goto exit;
+	}
+
+	if (stat(vname, &finfo)) {
+		printf("dhd_download: %s: %s\n", vname, strerror(errno));
+		ret = -1;
+		goto exit;
+	}
+	nvlen = finfo.st_size;
+	len += nvlen;
+
+	if ((buf = malloc(len +4)) == NULL) {
+		printf("dhd_download: Unable to allowcate %d bytes!\n", len);
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+
+	/* Read the firmware file into the buffer */
+	status  = fread(buf, sizeof(uint8), fwlen, fp);
+
+	/* close the firmware file */
+	fclose(fp);
+
+	if ((int)status < fwlen) {
+		printf("dhd_download: Short read in %s!\n", fname);
+		ret = -1;
+		goto exit;
+	}
+
+	/* Validating the format /length etc of the file */
+	if ((actual_len = check_file(buf)) <= 0) {
+		printf("dhd_download: Failed input file check on %s!\n", fname);
+		ret = -1;
+		goto exit;
+	}
+
+	/* Read the nvram file into the buffer */
+	status  = fread(buf + actual_len, sizeof(uint8), nvlen, fp1);
+
+	/* close the nvram file */
+	fclose(fp1);
+
+	if ((int)status < nvlen) {
+		printf("dhd_download: Short read in %s!\n", vname);
+		ret = -1;
+		goto exit;
+	}
+
+	/* porcess nvram vars if user specifics a text file instead of binary */
+	nvlen = process_nvram_vars((char*) &buf[actual_len], (unsigned int) nvlen);
+
+	if (nvlen % 4) {
+		pad = 4 - (nvlen % 4);
+		for (i = 0; i < pad; i ++)
+			buf[actual_len + nvlen + i] = 0;
+		nvlen += pad;
+	}
+
+	/* fix up len to be actual len + nvram len */
+	len = actual_len + nvlen;
+	/* update trx header with added nvram bytes */
+	hdr = (struct trx_header *) buf;
+	hdr->len = htol32(len);
+	/* pass the actual fw len */
+	hdr->offsets[TRX_OFFSETS_NVM_LEN_IDX] = htol32(nvlen);
+	/* caculate CRC over header */
+	hdr->crc32 = hndcrc32((uint8 *) &hdr->flag_version,
+		sizeof(struct trx_header) - OFFSETOF(struct trx_header, flag_version),
+		CRC32_INIT_VALUE);
+
+	/* Calculate CRC over data */
+	for (i = sizeof(struct trx_header); i < (unsigned int)len; ++i)
+		hdr->crc32 = hndcrc32((uint8 *)&buf[i], 1, hdr->crc32);
+	hdr->crc32 = htol32(hdr->crc32);
+
+	*buffer  = buf;
+	return len;
+
+exit:
+	if (buf)
+		free(buf);
+
+	return ret;
+}
+
+static int
+check_file(unsigned char *headers)
+{
+	struct trx_header *trx;
+	int actual_len = -1;
+
+	/* Extract trx header */
+	trx = (struct trx_header *)headers;
+	if ((ltoh32(trx->magic)) != TRX_MAGIC) {
+		printf("check_file: Error: trx bad hdr %x!\n", ltoh32(trx->magic));
+		return -1;
+	}
+
+	if (ltoh32(trx->flag_version) & TRX_UNCOMP_IMAGE) {
+		actual_len = ltoh32(trx->offsets[TRX_OFFSETS_DLFWLEN_IDX]) +
+			sizeof(struct trx_header);
+		return actual_len;
+	}
+	return actual_len;
+}
+#endif /* SERDOWNLOAD */
+
+static int
+wlu_mempool(void *wl, cmd_t *cmd, char **argv)
+{
+	void               *ptr;
+	int                ret;
+	int                i;
+	wl_mempool_stats_t *stats;
+	bcm_mp_stats_t     *mp_stats;
+
+
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return ret;
+
+	stats = (wl_mempool_stats_t *) ptr;
+	mp_stats = stats->s;
+
+	printf("%-8s %8s %8s %8s %8s %8s\n", "Name", "SZ", "Max", "Curr", "HiWater", "Failed");
+	for (i = 0; i < stats->num; i++) {
+		printf("%-8s %8d %8d %8d %8d %8d\n", mp_stats->name, (int) mp_stats->objsz,
+		       mp_stats->nobj, mp_stats->num_alloc, mp_stats->high_water,
+		       mp_stats->failed_alloc);
+
+		mp_stats++;
+	}
+
+	return (0);
+}
+
+static int
+wl_rxfifo_counters(void *wl, cmd_t *cmd, char **argv)
+{
+	char *statsbuf;
+	wl_rxfifo_cnt_t cnt;
+	int err;
+	void *ptr;
+	int i;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf_sm (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	statsbuf = (char *)ptr;
+	memcpy(&cnt, statsbuf, sizeof(cnt));
+	cnt.version = dtoh16(cnt.version);
+	cnt.length = dtoh16(cnt.length);
+
+	if (cnt.version != WL_RXFIFO_CNT_VERSION) {
+		printf("\tIncorrect version of rxfifo counters struct: expected %d; got %d\n",
+		   WL_RXFIFO_CNT_VERSION, cnt.version);
+		return -1;
+	}
+
+	for (i = 0; i < MAX_RX_FIFO; i++) {
+		printf("RXFIFO[%d]: data: %u\tmgmtctl: %u \n",
+				i, cnt.rxf_data[i], cnt.rxf_mgmtctl[i]);
+	}
+
+	return (0);
+}
+
+static int
+wl_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int err;
+	uchar *data;
+	int bsscfg_idx = 0;
+	int consumed = 0;
+	int iecount;
+	ie_setbuf_t *ie_setbuf;
+	ie_getbuf_t param;
+	uchar datalen, type, count, col;
+
+	/* parse a bsscfg_idx option if present */
+	if ((err = wl_cfg_option(argv + 1, argv[0], &bsscfg_idx, &consumed)) != 0)
+		return err;
+	if (consumed)
+		argv = argv + consumed;
+	else
+		bsscfg_idx = -1;
+
+	if (!*++argv) {
+		fprintf(stderr, "missing parameter type\n");
+		return BCME_USAGE_ERROR;
+	}
+	/* get IE type */
+	type = (uchar)atoi(argv[0]);
+
+	if (!*++argv) {
+		param.id = type;
+		ptr = buf;
+		if (bsscfg_idx == -1)
+			err = wlu_var_getbuf(wl, cmd->name, &param, sizeof(param), &ptr);
+		else
+			err = wl_bssiovar_getbuf(wl, cmd->name, bsscfg_idx, &param, sizeof(param),
+			buf, WLC_IOCTL_MAXLEN);
+		if (err == 0) {
+			data = (uchar *)ptr;
+			datalen = data[1]+2;
+			printf("%s len %d\n", cmd->name, datalen);
+			printf("%s Data:\n", cmd->name);
+			for (count = 0; (count < datalen);) {
+				for (col = 0; (col < MAX_DATA_COLS) &&
+					(count < datalen); col++, count++) {
+					printf("%02x", *data++);
+				}
+				printf("\n");
+			}
+		}
+		else {
+			fprintf(stderr, "Error %d getting IOVar\n", err);
+		}
+		return err;
+	}
+
+	/* get IE length */
+	datalen = (uchar)atoi(argv[0]);
+
+	if (datalen > 0) {
+		if (!argv[1]) {
+			fprintf(stderr, "Data bytes should be specified for IE of length %d\n",
+				datalen);
+			return BCME_USAGE_ERROR;
+		}
+		else {
+			/* Ensure each data byte is 2 characters long */
+			if ((int)strlen (argv[1]) < (datalen * 2)) {
+				fprintf(stderr, "Please specify all the data bytes for this IE\n");
+				return BCME_BADARG;
+			}
+		}
+	}
+
+	if ((datalen == 0) && (argv[1] != NULL))
+		fprintf(stderr, "Ignoring data bytes for IE of length %d\n", datalen);
+
+	count = sizeof(ie_setbuf_t) + datalen - 1;
+	data = malloc(count);
+	if (data == NULL) {
+		fprintf(stderr, "memory alloc failure\n");
+		return BCME_NOMEM;
+	}
+
+	ie_setbuf = (ie_setbuf_t *) data;
+	/* Copy the ie SET command ("add") to the buffer */
+	strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
+	ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+	/* Buffer contains only 1 IE */
+	iecount = htod32(1);
+	memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int));
+
+	/* Now, add the IE to the buffer */
+	ie_setbuf->ie_buffer.ie_list[0].ie_data.id = type;
+	ie_setbuf->ie_buffer.ie_list[0].ie_data.len = datalen;
+
+	if (datalen > 0) {
+		if ((err = get_ie_data ((uchar *)argv[1],
+		          (uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0],
+		          datalen))) {
+			free(data);
+			fprintf(stderr, "Error parsing data arg\n");
+			return err;
+		}
+	}
+
+	if (bsscfg_idx == -1)
+		err = wlu_var_setbuf(wl, cmd->name, data, count);
+	else
+		err = wlu_bssiovar_setbuf(wl, cmd->name, bsscfg_idx,
+			data, count, buf, WLC_IOCTL_MAXLEN);
+
+	free(data);
+	return (err);
+}
+
+/* Restore the ignored warnings status */
+
+
+static int
+wl_sleep_ret_ext(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int argc, i;
+	uint32 val;
+	char *endptr = NULL;
+	wl_pm2_sleep_ret_ext_t sleep_ret_ext;
+	wl_pm2_sleep_ret_ext_t* sleep_ret_ext_ptr;
+
+	/* Skip the command name */
+	UNUSED_PARAMETER(cmd);
+	argv++;
+
+	/* If no arguments are given, print the existing settings */
+	argc = ARGCNT(argv);
+	if (argc == 0) {
+		char *logic_str;
+
+		/* Get and print the values */
+		if ((ret = wlu_var_getbuf_med(wl, cmd->name, NULL, 0, (void*) &sleep_ret_ext_ptr)))
+			return ret;
+
+		if (sleep_ret_ext_ptr->logic == WL_DFRTS_LOGIC_OFF)
+			logic_str = "DISABLED";
+		else if (sleep_ret_ext_ptr->logic == WL_DFRTS_LOGIC_OR)
+			logic_str = "OR";
+		else if (sleep_ret_ext_ptr->logic == WL_DFRTS_LOGIC_AND)
+			logic_str = "AND";
+		else
+			logic_str = "ERROR";
+
+		printf("logic: %d (%s)\n",
+		       sleep_ret_ext_ptr->logic, logic_str);
+		if (sleep_ret_ext_ptr->logic != WL_DFRTS_LOGIC_OFF) {
+			printf("low_ms: %d\n", sleep_ret_ext_ptr->low_ms);
+			printf("high_ms: %d\n", sleep_ret_ext_ptr->high_ms);
+			printf("rx_pkts_threshold: %d\n",
+				sleep_ret_ext_ptr->rx_pkts_threshold);
+			printf("tx_pkts_threshold: %d\n",
+			       sleep_ret_ext_ptr->tx_pkts_threshold);
+			printf("txrx_pkts_threshold: %d\n",
+			       sleep_ret_ext_ptr->txrx_pkts_threshold);
+			printf("rx_bytes_threshold: %d\n",
+			       sleep_ret_ext_ptr->rx_bytes_threshold);
+			printf("tx_bytes_threshold: %d\n",
+			       sleep_ret_ext_ptr->tx_bytes_threshold);
+			printf("txrx_bytes_threshold: %d\n",
+			       sleep_ret_ext_ptr->txrx_bytes_threshold);
+		}
+		return 0;
+	}
+
+	memset(&sleep_ret_ext, 0, sizeof(wl_pm2_sleep_ret_ext_t));
+	i = 0;
+
+	/* Get the first 'logic' argument. */
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	if (val != WL_DFRTS_LOGIC_OFF && val != WL_DFRTS_LOGIC_OR &&
+		val != WL_DFRTS_LOGIC_AND) {
+		printf("Invalid logic value %u\n", val);
+		goto usage;
+	}
+	sleep_ret_ext.logic = val;
+	++i;
+
+	/* If logic is 0 (disable) then no more arguments are needed */
+	if (sleep_ret_ext.logic == 0)
+		goto set;
+
+	if (argc < 9)
+		goto usage;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.low_ms = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.high_ms = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.rx_pkts_threshold = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.tx_pkts_threshold = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.txrx_pkts_threshold = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.rx_bytes_threshold = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.tx_bytes_threshold = val;
+	++i;
+
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	sleep_ret_ext.txrx_bytes_threshold = val;
+	++i;
+
+	if (i != argc)
+		goto usage;
+
+set:
+	return wlu_var_setbuf(wl, cmd->name, &sleep_ret_ext,
+		sizeof(wl_pm2_sleep_ret_ext_t));
+
+usage:
+	printf("Usage: %s [logic] [<low_ms> <high_ms>"
+		" <rxP> <txP> <txrxP> <rxB> <txB> <txrxB>\n", wlu_av0);
+	printf("Parameters:\n");
+	printf("logic   : 0=disable, 1=OR, 2=AND all non-zero switching thresholds.\n");
+	printf("low_ms  : Low pm2_sleep_ret value.\n");
+	printf("high_ms : High pm2_sleep_ret value.\n");
+	printf("rxP     : Switching threshold in # of rx packets.\n");
+	printf("          eg. Switch from the low to high FRTS value if rxP or\n");
+	printf("          more packets are received in a PM2 radio wake period.\n");
+	printf("          0 means ignore this threshold.\n");
+	printf("txP     : Switching threshold in # of tx packets.\n");
+	printf("txrxP   : Switching threshold in # of combined tx+rx packets.\n");
+	printf("rxB     : Switching threshold in # of rx bytes.\n");
+	printf("txB     : Switching threshold in # of tx bytes.\n");
+	printf("txrxB   : Switching threshold in # of combined tx+rx bytes.\n");
+	return -1;
+}
+
+static int wl_stamon_sta_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	wlc_stamon_sta_config_t stamon_cfg;
+	struct maclist *maclist = (struct maclist *) buf;
+	uint i, max = (WLC_IOCTL_MAXLEN - sizeof(int)) / ETHER_ADDR_LEN;
+	struct ether_addr *ea;
+
+	memset(&stamon_cfg, 0, sizeof(wlc_stamon_sta_config_t));
+	if (!*++argv) {
+		maclist->count = htod32(max);
+		err = wlu_iovar_get(wl, cmd->name, maclist,
+			WLC_IOCTL_MAXLEN);
+		if (!err) {
+			for (i = 0, ea = maclist->ea; i < maclist->count && i < max; i++, ea++)
+				printf("%s\n", wl_ether_etoa(ea));
+		}
+	} else {
+		if (!stricmp(*argv, "add")) {
+			stamon_cfg.cmd = STAMON_CFG_CMD_ADD;
+			if (!*++argv || !wl_ether_atoe(*argv, &stamon_cfg.ea)) {
+				printf(" ERROR: no valid ether addr provided\n");
+				err = -1;
+			}
+		} else if (!stricmp(*argv, "del")) {
+			stamon_cfg.cmd = STAMON_CFG_CMD_DEL;
+			if (!*++argv || !wl_ether_atoe(*argv, &stamon_cfg.ea)) {
+				printf(" ERROR: no valid ether addr provided\n");
+				err = -1;
+			}
+		} else if (!stricmp(*argv, "enable"))
+			stamon_cfg.cmd = STAMON_CFG_CMD_ENB;
+		else if (!stricmp(*argv, "disable"))
+			stamon_cfg.cmd = STAMON_CFG_CMD_DSB;
+		else if (!stricmp(*argv, "counters")) {
+			const char *cmdname = "sta_monitor_cnt";
+			uint32 cnt = 0;
+			if ((err = wlu_iovar_getint(wl, cmdname, (int *)&cnt) < 0)) {
+				return err;
+			}
+			printf("stamon cnt=%u\n", cnt);
+			return err;
+		} else if (!stricmp(*argv, "reset_cnts"))
+			stamon_cfg.cmd = STAMON_CFG_CMD_RSTCNT;
+		else if (!stricmp(*argv, "stats")) {
+			stamon_info_t *pbuf;
+
+			stamon_cfg.cmd = STAMON_CFG_CMD_GET_STATS;
+			if (!*++argv || !wl_ether_atoe(*argv, &stamon_cfg.ea)) {
+				printf(" ERROR: no valid ether addr provided\n");
+				err = -1;
+			}
+
+			memset(buf, 0, WLC_IOCTL_MAXLEN);
+			if (!err) {
+				err = wlu_iovar_getbuf(wl, cmd->name, &stamon_cfg,
+					sizeof(wlc_stamon_sta_config_t), buf, WLC_IOCTL_MAXLEN);
+			}
+			pbuf = (stamon_info_t*)buf;
+			if (!err) {
+				if (pbuf->count != 0) {
+					/* Success case: Found the mac in STAMON and
+					 * read the stats
+					 */
+					printf(""MACF" : RSSI :%d \n",
+						ETHER_TO_MACF(pbuf->sta_data[0].ea),
+						pbuf->sta_data[0].rssi);
+				} else if (pbuf->count == 0) {
+					/* Failed case, Didn't Found the Mac
+					 * read the stats
+					 */
+					printf("STAMON not monitoring "MACF" \n",
+						ETHER_TO_MACF(stamon_cfg.ea));
+				}
+			}
+
+			return err;
+		} else {
+			printf("error: unknown operation option%s\n", *argv);
+			err = -1;
+		}
+
+		if (!err)
+			err = wlu_iovar_set(wl, cmd->name,
+				&stamon_cfg, sizeof(wlc_stamon_sta_config_t));
+
+	}
+
+	return err;
+}
+
+static monitor_promisc_level_msg_t wl_monpromisc_level_msgs[] = {
+	{WL_MONPROMISC_PROMISC,	"promisc"},
+	{WL_MONPROMISC_CTRL, "ctrl"},
+	{WL_MONPROMISC_FCS, "fcs"},
+	{0,		NULL}
+};
+
+static int
+wl_monitor_promisc_level(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint val = 0, last_val = 0;
+	uint promiscbitmap = 0, promiscbitmap_add = 0, promiscbitmap_del = 0;
+	char *endptr;
+	const char *cmdname = "monitor_promisc_level";
+
+	UNUSED_PARAMETER(cmd);
+	if ((ret = wlu_iovar_getint(wl, cmdname, (int *)&promiscbitmap) < 0)) {
+		return ret;
+	}
+	promiscbitmap = dtoh32(promiscbitmap);
+	if (!*++argv) {
+		printf("0x%x ", promiscbitmap);
+		for (i = 0; (val = wl_monpromisc_level_msgs[i].value); i++) {
+			if ((promiscbitmap & val) && (val != last_val))
+				printf(" %s", wl_monpromisc_level_msgs[i].string);
+			last_val = val;
+		}
+		printf("\n");
+		return (0);
+	}
+	while (*argv) {
+		char *s = *argv;
+		if (*s == '+' || *s == '-')
+			s++;
+		else
+			promiscbitmap_del = ~0; /* make the whole list absolute */
+		val = strtoul(s, &endptr, 0);
+		if (val == 0xFFFFFFFF) {
+			fprintf(stderr,
+				"Bits >32 are not supported on this driver version\n");
+			val = 1;
+		}
+		/* not an integer if not all the string was parsed by strtoul */
+		if (*endptr != '\0') {
+			for (i = 0; (val = wl_monpromisc_level_msgs[i].value); i++)
+				if (stricmp(wl_monpromisc_level_msgs[i].string, s) == 0)
+					break;
+				if (!val)
+					goto usage;
+		}
+		if (**argv == '-')
+			promiscbitmap_del |= val;
+		else
+			promiscbitmap_add |= val;
+		++argv;
+	}
+	promiscbitmap &= ~promiscbitmap_del;
+	promiscbitmap |= promiscbitmap_add;
+	promiscbitmap = htod32(promiscbitmap);
+	return (wlu_iovar_setint(wl, cmdname, (int)promiscbitmap));
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+	for (i = 0; (val = wl_monpromisc_level_msgs[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, wl_monpromisc_level_msgs[i].string);
+		else
+			fprintf(stderr, ", %s", wl_monpromisc_level_msgs[i].string);
+		last_val = val;
+	}
+	fprintf(stderr, "\n");
+	return 0;
+}
+
+static int
+wl_bss_peer_info(void *wl, cmd_t *cmd, char **argv)
+{
+	bss_peer_list_info_t *info;
+	bss_peer_info_t *peer_info;
+	bss_peer_info_param_t param;
+	int err, i;
+	void *ptr;
+
+	memset(&param, 0, sizeof(bss_peer_info_param_t));
+	param.version = htod16(BSS_PEER_INFO_PARAM_CUR_VER);
+
+	if (*++argv) {
+		if (!wl_ether_atoe(*argv, &param.ea)) {
+			printf(" ERROR: no valid ether addr provided\n");
+			return -1;
+		}
+	}
+
+	if ((err = wlu_var_getbuf_med(wl, cmd->name, &param, sizeof(bss_peer_info_param_t),
+		&ptr)) < 0)
+		return err;
+
+	info = (bss_peer_list_info_t*)ptr;
+
+	if ((dtoh16(info->version) != BSS_PEER_LIST_INFO_CUR_VER) ||
+		(dtoh16(info->bss_peer_info_len) != sizeof(bss_peer_info_t))) {
+		printf("BSS peer info version/structure size mismatch driver %d firmware %d \r\n",
+			BSS_PEER_LIST_INFO_CUR_VER, dtoh16(info->version));
+		return -1;
+	}
+
+	if (WLC_IOCTL_MEDLEN < (BSS_PEER_LIST_INFO_FIXED_LEN +
+		(dtoh32(info->count) * sizeof(bss_peer_info_t)))) {
+		printf("ERROR : peer list received exceed the buffer size\r\n");
+	}
+
+	for (i = 0; i < (int)dtoh32(info->count); i++) {
+		peer_info = &info->peer_info[i];
+		peer_info->rateset.count = dtoh32(peer_info->rateset.count);
+		printf("PEER%d: MAC: %s: RSSI %d TxRate %d kbps RxRate %d kbps age : %ds\r\n",
+			i, wl_ether_etoa(&peer_info->ea), peer_info->rssi,
+			dtoh32(peer_info->tx_rate), dtoh32(peer_info->rx_rate),
+			dtoh32(peer_info->age));
+			printf("\t rateset ");
+			dump_rateset(peer_info->rateset.rates, peer_info->rateset.count);
+			printf("\r\n");
+	}
+
+	return 0;
+}
+
+static int
+wl_aibss_txfail_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = USAGE_ERROR;
+	aibss_txfail_config_t txfail_config;
+
+	if (!*++argv) {
+		memset(&txfail_config, 0, sizeof(txfail_config));
+		/* get current txfail configuration */
+		if ((ret = wlu_iovar_get(wl, cmd->name, &txfail_config,
+		        sizeof(txfail_config))) < 0)
+		        goto error;
+
+		printf("AIBSS TXFAIL config beacon timeout duration: %d \r\n"
+		                "Max consecutive Tx failure before TXFAIL event:%d \r\n",
+		                txfail_config.bcn_timeout, txfail_config.max_tx_retry);
+
+		if (txfail_config.version == AIBSS_TXFAIL_CONFIG_VER_1) {
+			printf("Max ATIM failures before TXFAIL event: %d \r\n",
+				txfail_config.max_atim_failure);
+		}
+	} else {
+		txfail_config.bcn_timeout = (uint32) strtoul(*argv, NULL, 0);
+
+
+		if (*++(argv) == NULL) {
+			printf("Incorrect number of arguments\n");
+			goto error;
+		}
+
+		txfail_config.max_tx_retry = (uint32) strtoul(*argv, NULL, 0);
+
+		if (*++(argv) == NULL) {
+			printf("Incorrect number of arguments\n");
+			goto error;
+		}
+
+		txfail_config.max_atim_failure = (uint32) strtoul(*argv, NULL, 0);
+
+		if (*++(argv)) {
+			printf("wrong extra arguments\n");
+			goto error;
+		}
+
+		txfail_config.version = AIBSS_TXFAIL_CONFIG_VER_1;
+		txfail_config.len = sizeof(txfail_config);
+		ret = wlu_iovar_set(wl, cmd->name, (void *) &txfail_config,
+		        sizeof(txfail_config));
+	}
+
+error:
+	return ret;
+}
+
+/* Returns the matching config table entry from the wl_config_iovar_list for the passed config
+ * iovar. If no matches are found, then returns the default (last) entry from the list
+ */
+static wl_config_iovar_t *get_config_iovar_entry(const char *iovar_name)
+{
+	int i = 0;
+
+	while (wl_config_iovar_list[i].iovar_name) {
+		if (!stricmp(iovar_name, wl_config_iovar_list[i].iovar_name))
+			break;
+		i++;
+	}
+
+	return &(wl_config_iovar_list[i]);
+}
+
+/* Print function for config iovar.
+ */
+static void wl_bcm_config_print(wl_config_iovar_t *cfg_iovar, wl_config_t *cfg)
+{
+	char *status_str = NULL;
+	int i = 0;
+	char *autostr = (cfg->config == (uint32) AUTO) ? "auto" : "";
+
+	while (cfg_iovar->params[i].name) {
+		if (cfg_iovar->params[i].value == cfg->status) {
+			status_str = cfg_iovar->params[i].name;
+			break;
+		}
+		i++;
+	}
+
+	if (status_str) {
+		printf("%s %d %s\n", status_str, cfg->status, autostr);
+	} else {
+		/* No matching entry found in the table. Just print the value received from
+		   the driver
+		*/
+		printf("%d %s\n", cfg->status, autostr);
+	}
+}
+
+int
+wl_bcm_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	int i = 0;
+	wl_config_iovar_t *config_iovar;
+
+	/* Get the config entry corresponding to this iovar */
+	config_iovar = get_config_iovar_entry((char *)cmd->name);
+
+	if (!config_iovar)
+		return BCME_ERROR;
+
+	if (*++argv == NULL) {
+		/* Get */
+		wl_config_t *cfg;
+		void *ptr = NULL;
+
+		if ((err = wlu_var_getbuf_sm(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return err;
+
+		cfg = (wl_config_t *) ptr;
+		cfg->config = dtoh32(cfg->config);
+		cfg->status = dtoh32(cfg->status);
+
+		/* Call the iovar's print function */
+		config_iovar->pfunc(config_iovar, cfg);
+	} else {
+		/* Set */
+		char *param = *argv++;
+		bool found = 0;
+		wl_config_t cfg;
+		i = 0;
+
+		/* Check if the passed param exist in the config_iovar table */
+		while (config_iovar->params[i].name) {
+			if (!stricmp(config_iovar->params[i].name, param)) {
+				cfg.config = config_iovar->params[i].value;
+				found = 1;
+				break;
+			}
+			i++;
+		}
+
+		if (!found) {
+			/* Check if an integer value is passed as the param */
+			char *endptr = NULL;
+			cfg.config = (uint32) strtol(param, &endptr, 0);
+			if (*endptr == '\0')
+				found = 1;
+		}
+		if (!found) {
+			printf("Unsupported parameter [%s]\n", param);
+			return -1;
+		}
+
+		cfg.config = htod32(cfg.config);
+
+		err = wlu_var_setbuf(wl, cmd->name, &cfg, sizeof(wl_config_t));
+	}
+	return err;
+}
+
+/* Set or Get the "desired_bssid" ioctl
+ */
+static int
+wl_desired_bssid(void *wl, cmd_t *cmd, char **argv)
+{
+	struct ether_addr ea;
+	int error = BCME_OK;
+
+	UNUSED_PARAMETER(cmd);
+	argv++;
+
+	if (*argv == NULL) {
+		if ((error = wlu_get(wl, WLC_GET_DESIRED_BSSID, &ea, ETHER_ADDR_LEN)) < 0) {
+			return error;
+		}
+		printf("%s\n", wl_ether_etoa(&ea));
+	} else {
+		if (!wl_ether_atoe(*argv, &ea))
+			return BCME_USAGE_ERROR;
+
+		error = wlu_set(wl, WLC_SET_DESIRED_BSSID, &ea, ETHER_ADDR_LEN);
+	}
+	return error;
+}
+
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+static int wl_dump_modesw_dyn_bwsw(void *wl, cmd_t *cmd, char **argv)
+{
+	char *ptr;
+	int err = 0;
+
+	if (*++argv != NULL) {
+		return BCME_UNSUPPORTED;
+	}
+
+	if ((err = wlu_iovar_getbuf(wl, cmd->name, NULL, 0,
+		buf, WLC_IOCTL_MAXLEN)) < 0) {
+		return err;
+	}
+
+	ptr = (char *) buf;
+	fputs(ptr, stdout);
+
+	return err;
+}
+#endif 
+
+static int
+wl_dfs_channel_forced(void *wl, cmd_t *cmd, char **argv)
+{
+	uint i;
+	int err = -1;
+	char *p;
+	chanspec_t chanspec;
+	wl_dfs_forced_t *dfs_frcd;
+	wl_dfs_forced_t inp;
+	uint32 ioctl_size;
+
+	dfs_frcd = (wl_dfs_forced_t *)buf;
+	memset(buf, 0, WL_DFS_FORCED_PARAMS_MAX_SIZE);
+	memset(&inp, 0, sizeof(wl_dfs_forced_t));
+
+	/* Get the existing configuration first. We need this for
+	 * set operations also
+	 */
+	inp.version = DFS_PREFCHANLIST_VER;
+	if ((err = wlu_iovar_getbuf(wl, cmd->name, &inp, sizeof(wl_dfs_forced_t),
+		dfs_frcd, WL_DFS_FORCED_PARAMS_MAX_SIZE)) < 0) {
+		return err;
+	}
+
+	if (!argv[1]) {
+		/* Get Operation */
+		char chanbuf[CHANSPEC_STR_LEN];
+		/* List configuration shouldn't be there if we are operating on
+		 * old version of driver
+		 */
+		if ((dfs_frcd->version == DFS_PREFCHANLIST_VER) && (dfs_frcd->chspec_list.num)) {
+			printf("DFS Preferred channel list:: \n");
+			for (i = 0; i < dfs_frcd->chspec_list.num; i++) {
+				chanspec =
+					wl_chspec32_from_driver(dfs_frcd->chspec_list.list[i]);
+				/* wf_chspec_ntoa will return NULL when N mode is disabled */
+				if (wf_chspec_ntoa(chanspec, chanbuf))
+					printf("%s(0x%x) ", chanbuf, chanspec);
+				else
+					printf("(0x%x) ", chanspec);
+			}
+			printf("\n");
+		} else {
+			if (dfs_frcd->version == DFS_PREFCHANLIST_VER) {
+				/* Not configured since new driver works on list */
+				printf("DFS Preferred Channel:: 0x0 (None)\n");
+			} else {
+				chanspec = wl_chspec32_from_driver(dfs_frcd->chspec);
+				/* wf_chspec_ntoa will return NULL when N mode is disabled */
+				if (chanspec && wf_chspec_ntoa(chanspec, chanbuf)) {
+					printf("DFS Preferred Channel:: %s (0x%x)\n",
+							chanbuf, chanspec);
+				} else {
+					printf("DFS Preferred Channel:: 0x%x\n", chanspec);
+				}
+			}
+		}
+		return err;
+	}
+	if (!strcmp(argv[1], "-l")) {
+		/* List configuration */
+		if (!argv[2]) {
+			printf("Please provide channel list\n");
+			err = BCME_USAGE_ERROR;
+			return err;
+		}
+
+		if (dfs_frcd->version != DFS_PREFCHANLIST_VER) {
+			printf("List Configuration is not supported in this version of driver\n");
+			return err;
+		}
+		p = strtok(argv[2], ", ");
+		while (p) {
+			if ((*p != '+') && (*p != '-')) {
+				printf("channel should be prefixed with +/-\n");
+				err = BCME_USAGE_ERROR;
+				return err;
+			}
+			if (!(chanspec = wf_chspec_aton(p + 1))) {
+				printf("Invalid channel specified\n");
+				err = BCME_USAGE_ERROR;
+				return err;
+			}
+			if (!CHSPEC_IS5G(chanspec)) {
+				printf("Invalid channel specified\n");
+				err = BCME_USAGE_ERROR;
+				return err;
+			}
+			dfs_frcd->chspec = 0;
+			if (*p == '+') {
+				/* check if exists */
+				for (i = 0; i < dfs_frcd->chspec_list.num; i++) {
+					if (chanspec == dfs_frcd->chspec_list.list[i]) {
+						printf("Ignoring chanspec 0x%x\n", chanspec);
+						goto next_token;
+					}
+				}
+				chanspec = wl_chspec32_to_driver(chanspec);
+				dfs_frcd->chspec_list.list[dfs_frcd->chspec_list.num++] = chanspec;
+			} else if (*p == '-') {
+				/* check if exists */
+				for (i = 0; i < dfs_frcd->chspec_list.num; i++) {
+					if (chanspec == dfs_frcd->chspec_list.list[i]) {
+						dfs_frcd->chspec_list.num--;
+						break;
+					}
+				}
+				while (i < dfs_frcd->chspec_list.num) {
+					dfs_frcd->chspec_list.list[i] =
+						dfs_frcd->chspec_list.list[i+1];
+					i++;
+				}
+			}
+next_token:
+			p = strtok(NULL, ", ");
+		}
+		if (dfs_frcd->chspec_list.num > WL_NUMCHANNELS) {
+			printf("Maximum %d channels supported\n", WL_NUMCHANNELS);
+			err = BCME_USAGE_ERROR;
+			return err;
+		}
+		ioctl_size = WL_DFS_FORCED_PARAMS_FIXED_SIZE +
+			(dfs_frcd->chspec_list.num * sizeof(chanspec_t));
+		dfs_frcd->version = DFS_PREFCHANLIST_VER;
+		err = wlu_iovar_set(wl, cmd->name, dfs_frcd, ioctl_size);
+	} else {
+		/* No list provided. Either single channel or clear list */
+		if (dfs_frcd->version == DFS_PREFCHANLIST_VER) {
+			/* Clear configuration */
+			dfs_frcd->chspec = 0;
+			dfs_frcd->chspec_list.num = 0;
+
+			ioctl_size = WL_DFS_FORCED_PARAMS_FIXED_SIZE +
+				(dfs_frcd->chspec_list.num * sizeof(chanspec_t));
+			err = wlu_iovar_set(wl, cmd->name, dfs_frcd, ioctl_size);
+		}
+		/* Single channel configuration. Continue as we were doing earlier */
+		if (strcmp(argv[1], "0"))
+			err = wl_chanspec(wl, cmd, argv);
+	}
+	return err;
+}
+#ifdef WIN32
+#pragma warning(pop)
+#endif
+
+static int
+wl_setiproute(void *wl, cmd_t *cmd, char **argv)
+{
+	uint route_tbl_len;
+	wlc_ipfo_route_tbl_t *route_tbl = NULL;
+	uint32 entries;
+	char *endptr;
+	uint32 i = 0;
+	struct ipv4_addr dipaddr;
+	struct ether_addr ea;
+	int argc;
+	int ret = BCME_OK;
+	int buflen = sprintf(buf, "%s", *argv) + 1;
+
+	UNUSED_PARAMETER(cmd);
+	argv++;
+	route_tbl_len = WL_IPFO_ROUTE_TBL_FIXED_LEN +
+		WL_MAX_IPFO_ROUTE_TBL_ENTRY * sizeof(wlc_ipfo_route_entry_t);
+
+	/* allocate the max storage */
+	if ((route_tbl = malloc(route_tbl_len)) == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for route table\n", route_tbl_len);
+		return BCME_NOMEM;
+	}
+
+	memset(route_tbl, 0, route_tbl_len);
+
+	if (*argv == NULL) {
+		if ((ret = wlu_iovar_get(wl, buf, route_tbl, route_tbl_len)) == BCME_OK) {
+			if (route_tbl->num_entry == 0) {
+				printf("No entries present\n");
+			} else {
+				for (i = 0; i < route_tbl->num_entry; i++) {
+					printf("entry%d", i);
+					printf("\t%s",
+						wl_iptoa(&route_tbl->route_entry[i].ip_addr));
+					printf("\t%s\n",
+						wl_ether_etoa(&route_tbl->route_entry[i].nexthop));
+				}
+			}
+		}
+	} else {
+
+		argc = ARGCNT(argv);
+
+		if (argc <= 0)
+			goto usage;
+
+		entries = strtoul(argv[0], &endptr, 0);
+
+		if (*endptr != '\0')
+			goto usage;
+
+		if ((uint32)argc != (entries * 2 + 1))
+			goto usage;
+
+		route_tbl->num_entry = entries;
+		argv++;
+
+		for (i = 0; i < entries; i++) {
+			if (!wl_atoip(argv[i*2], &dipaddr))
+				goto usage;
+
+			if (!wl_ether_atoe(argv[(i * 2 + 1)], &ea))
+				goto usage;
+
+			memcpy(&route_tbl->route_entry[i].ip_addr, &dipaddr, IPV4_ADDR_LEN);
+			memcpy(&route_tbl->route_entry[i].nexthop, &ea, ETHER_ADDR_LEN);
+		}
+		route_tbl_len = (entries * sizeof(wlc_ipfo_route_entry_t)) + IPV4_ADDR_LEN;
+		memcpy(&buf[buflen], route_tbl, route_tbl_len);
+		ret = wlu_set(wl, WLC_SET_VAR, &buf[0], buflen + route_tbl_len);
+	}
+
+	free(route_tbl);
+	return ret;
+
+usage:
+	fprintf(stderr, "wrong command format\n");
+	if (route_tbl != NULL)
+		free(route_tbl);
+	return ret;
+}
+
+static int
+wl_modesw_timecal(void *wl, cmd_t *cmd, char **argv)
+{
+	int val;
+	int err = 0;
+	char *ptr = NULL;
+	if (*++argv == NULL) {
+		/* retrieving the results */
+		if ((err = wlu_iovar_getbuf(wl, cmd->name, NULL, 0,
+			buf, WLC_IOCTL_MAXLEN)) < 0) {
+			return err;
+		}
+		ptr = buf;
+		fputs(ptr, stdout);
+	}
+	else
+	{
+		val = htod32(atoi(*argv));
+		if ((err = wlu_iovar_setbuf(wl, cmd->name, &val, sizeof(val),
+			buf, WLC_IOCTL_MAXLEN)) < 0) {
+			return err;
+		}
+	}
+	return err;
+}
+
+static int
+wl_pcie_bus_throughput_params(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0, opt_err;
+	miniopt_t to;
+	pcie_bus_tput_params_t *params = NULL;
+	pcie_bus_tput_stats_t *stats = NULL;
+	UNUSED_PARAMETER(cmd);
+
+	argv++; /* toss the command name */
+	if (!*argv) { /* Get the pcie bus throughput stats */
+		void *ptr = NULL;
+		uint32 tput = 0;
+
+		if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0) {
+			fprintf(stderr, "Failed to get stats.\n");
+			return err;
+		}
+		stats = (pcie_bus_tput_stats_t *)ptr;
+		if (stats->count) {
+			tput = (stats->count * stats->nbytes_per_descriptor) /
+				stats->time_taken;
+			tput = (tput * 8) / (1024 * 1024); /* convert to Mega bits */
+			fprintf(stdout, "Seconds test run %d\nNo of dma completed %d\n"
+				"Bytes transfered per dma %d\nBus throughput: %d mbps\n",
+				stats->time_taken, stats->count,
+				stats->nbytes_per_descriptor, tput);
+		}
+	}
+	if (*argv) { /* Set the bus throughput params */
+		params = (pcie_bus_tput_params_t *)malloc(sizeof(pcie_bus_tput_params_t));
+		if (params == NULL) {
+			fprintf(stderr, "Failed to allocate buffer.\n");
+			return BCME_NOMEM;
+		}
+		memset(params, 0, sizeof(*params));
+
+		miniopt_init(&to, __FUNCTION__, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			argv += to.consumed;
+			if (to.opt == 'n') {
+				if (!to.good_int) {
+					fprintf(stderr, "%s: could not parse \"%s\" as an int for"
+						" max_dma_descriptors \n", __FUNCTION__, to.valstr);
+					err = BCME_BADARG;
+					goto fail;
+				}
+				params->max_dma_descriptors = to.val;
+			}
+		}
+
+		if (params->max_dma_descriptors == 0)
+			params->max_dma_descriptors = 64; /* set default as 64 */
+
+		if ((err = wlu_var_setbuf(wl, cmd->name, params,
+			sizeof(*params)) < 0)) {
+			fprintf(stderr, "failed to trigger measurement %d\n", err);
+		}
+	}
+fail:
+	if (params)
+		free(params);
+	return err;
+}
+
+static int
+wl_interface_create_action(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_interface_create_t wlif;
+	wl_interface_info_t *pwlif_info;
+	int count, val;
+	int err;
+	char opt, *p, *valstr, *endptr = NULL;
+
+	memset(&wlif, 0, sizeof(wlif));
+	wlif.ver = WL_INTERFACE_CREATE_VER;
+
+	argv++;
+	count = ARGCNT(argv);
+
+	/*
+	 * We should have atleast one argument for the create command,
+	 * whether to start it as AP or STA.
+	 */
+	if (count < 1)
+		return BCME_USAGE_ERROR;
+	/*
+	 * First Argument:
+	 * Find the interface that user need to create and update the flag/iftype
+	 * flags field is still used along with iftype inorder to support the old version of the
+	 * FW work with the latest app changes.
+	 */
+	if (stricmp(argv[0], "sta") == 0) {
+		wlif.iftype = WL_INTERFACE_TYPE_STA;
+		wlif.flags |= WL_INTERFACE_CREATE_STA;
+	} else if (stricmp(argv[0], "ap") == 0) {
+		wlif.iftype = WL_INTERFACE_TYPE_AP;
+		wlif.flags |= WL_INTERFACE_CREATE_AP;
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+
+	while ((p = *argv) != NULL) {
+		argv++;
+		opt = '\0';
+		valstr = NULL;
+
+		if (!strncmp(p, "-", 1)) {
+			opt = p[1];
+			if (strlen(p) > 2) {
+				fprintf(stderr,
+				"%s: only single char options, error on param \"%s\"\n",
+				__FUNCTION__, p);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (*argv == NULL) {
+				fprintf(stderr,
+				"%s: missing value parameter after \"%s\"\n",
+				__FUNCTION__, p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			valstr = *argv;
+			argv++;
+		} else {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		/* The mac address is optional, if its passed and valid use it. */
+		if (opt == 'm') {
+			if (wl_ether_atoe(valstr, &wlif.mac_addr)) {
+				wlif.flags |= WL_INTERFACE_MAC_USE;
+			}
+		}
+
+		/* The wlc_index is optional, if its passed and valid use it. */
+		if (opt == 'c') {
+			/* parse valstr as int */
+			val = (int)strtol(valstr, &endptr, 0);
+			if (*endptr == '\0') {
+				wlif.flags |= WL_INTERFACE_WLC_INDEX_USE;
+				wlif.wlc_index = val;
+			} else {
+				fprintf(stderr,
+				"wl_interface_create_action: could not parse \"%s\" as an int",
+				valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+	}
+
+
+	err = wlu_var_getbuf(wl, cmd->name, &wlif, sizeof(wlif), (void *)&pwlif_info);
+	if (err < 0) {
+		printf("%s(): wlu_var_getbuf failed %d \r\n", __FUNCTION__, err);
+	} else {
+		printf("ifname: %s bsscfgidx: %d mac_addr %s\r\n",
+			pwlif_info->ifname, pwlif_info->bsscfgidx,
+			wl_ether_etoa(&pwlif_info->mac_addr));
+	}
+
+exit:
+	return err;
+}
+
+static int
+wl_interface_remove_action(void *wl, cmd_t *cmd, char **argv)
+{
+	int bsscfg_idx = 0;
+	int consumed;
+	int error;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "interface_remove", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	/*
+	 * This command supports both "bss" method and "-i" method. First
+	 * check if "bss" options is present, and if yes, use the index
+	 * otherwise use the normal path.
+	 */
+	if (consumed != 0)
+		error = wl_bssiovar_set(wl, "interface_remove", bsscfg_idx, NULL, 0);
+	else
+		error = wlu_var_setbuf(wl, cmd->name, NULL, 0);
+
+	return error;
+}
+
+static int
+wl_phy_txpwrcap_tbl(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_txpwrcap_tbl_t txpwrcap_tbl;
+	wl_txpwrcap_tbl_t *txpwrcap_tbl_ptr;
+	uint8 num_antennas = 0;
+
+	void *ptr = NULL;
+	int err = 0;
+	uint8 i, j, k;
+
+	if (!(*++argv)) {		/* Get */
+		if ((err = wlu_var_getbuf_med(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return err;
+		txpwrcap_tbl_ptr = ptr;
+
+		for (i = 0; i < TXPWRCAP_MAX_NUM_CORES; i++) {
+			if (txpwrcap_tbl_ptr->num_antennas_per_core[i]) {
+				printf("Num Antennas on Core %d = %d\n",
+					i, txpwrcap_tbl_ptr->num_antennas_per_core[i]);
+				num_antennas += txpwrcap_tbl_ptr->num_antennas_per_core[i];
+			}
+		}
+
+		printf("Pwr Caps with Cell On:\n");
+		for (i = 0; i < num_antennas; i++) {
+			printf("\t%d", txpwrcap_tbl_ptr->pwrcap_cell_on[i]);
+		}
+		printf("\n");
+
+
+		printf("Pwr Caps with Cell Off:\n");
+		for (i = 0; i < num_antennas; i++) {
+			printf("\t%d", txpwrcap_tbl_ptr->pwrcap_cell_off[i]);
+		}
+		printf("\n");
+
+		return err;
+	} else { /* Set */
+		txpwrcap_tbl.num_antennas_per_core[0] = strtol(*argv, NULL, 0);
+		num_antennas = txpwrcap_tbl.num_antennas_per_core[0];
+
+		for (i = 1; i < TXPWRCAP_MAX_NUM_CORES; i++) {
+			if (*++argv) {
+				txpwrcap_tbl.num_antennas_per_core[i] = strtol(*argv, NULL, 0);
+				num_antennas += txpwrcap_tbl.num_antennas_per_core[i];
+			} else {
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		if (*++argv) {
+			memset(txpwrcap_tbl.pwrcap_cell_on, 127,
+			        TXPWRCAP_MAX_NUM_ANTENNAS *
+			        sizeof(txpwrcap_tbl.pwrcap_cell_on[0]));
+			memset(txpwrcap_tbl.pwrcap_cell_off, 127,
+			        TXPWRCAP_MAX_NUM_ANTENNAS *
+			        sizeof(txpwrcap_tbl.pwrcap_cell_off[0]));
+
+			i = 0;
+			j = 0;
+			k = 0;
+			do {
+				if (k >= 2 * num_antennas) {
+					printf("Entries exceeded max allowed\n");
+					return BCME_ERROR;
+				}
+				if (k >= num_antennas)
+					txpwrcap_tbl.pwrcap_cell_off[j++] = strtoul(*argv, NULL, 0);
+				else
+					txpwrcap_tbl.pwrcap_cell_on[i++] = strtoul(*argv, NULL, 0);
+				k++;
+			} while (*++argv);
+
+			if ((k != 2* num_antennas) &&
+				(k != num_antennas)) {
+				printf("Incorrect Number of Entries. Expected %d/%d, Entered %d\n",
+					num_antennas, 2 * num_antennas, k);
+				return BCME_ERROR;
+			}
+
+			if ((err = wlu_var_setbuf(wl, cmd->name, &txpwrcap_tbl,
+			        sizeof(txpwrcap_tbl))) < 0) {
+				printf("Unable to set the txpwrcaps.\n");
+				printf("Check number of antennas for this board.\n");
+				return BCME_ERROR;
+			}
+		}
+		else
+			return BCME_USAGE_ERROR;
+
+	}
+	return err;
+}
+
+
+/*
+ * Get Beacon Trim Stats
+ *	wl bcntrim_stats
+ */
+static int
+wl_bcntrim_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint16 op_buffer[BCNTRIMST_NUM];
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	if (*argv == NULL) {
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) op_buffer,
+			(BCNTRIMST_NUM * 2))) < 0)
+			return (err);
+
+		printf("- Beacon Trim Statistics -\n");
+		printf("BCNTRIM_PER : %d\n", op_buffer[BCNTRIMST_PER]);
+		printf("BCNTRIM_TIMEND : %d\n", op_buffer[BCNTRIMST_TIMEND]);
+		printf("BCNTRIM_TSFLMT : %d\n", op_buffer[BCNTRIMST_TSFLMT]);
+
+		printf("BCNTRIM_CUR : %d\n", op_buffer[BCNTRIMST_CUR]);
+		printf("BCNTRIM_PREVLEN : %d\n", op_buffer[BCNTRIMST_PREVLEN]);
+		printf("BCNTRIM_TIMLEN : %d\n", op_buffer[BCNTRIMST_TIMLEN]);
+		printf("BCNTRIM_RSSI : %d\n", op_buffer[BCNTRIMST_RSSI]);
+		printf("BCNTRIM_CHAN : %d\n", op_buffer[BCNTRIMST_CHAN]);
+
+		printf("BCNTRIM_DUR : %d\n", op_buffer[BCNTRIMST_DUR]);
+		printf("BCNTRIM_RXMBSS : %d\n", op_buffer[BCNTRIMST_RXMBSS]);
+		printf("BCNTRIM_CANTRIM : %d\n", op_buffer[BCNTRIMST_CANTRIM]);
+		printf("BCNTRIM_LENCHG : %d\n", op_buffer[BCNTRIMST_LENCHG]);
+		printf("BCNTRIM_TSFDRF : %d\n", op_buffer[BCNTRIMST_TSFDRF]);
+		printf("BCNTRIM_NOTIM : %d\n", op_buffer[BCNTRIMST_NOTIM]);
+	} else {
+		/* Set not supported */
+		return USAGE_ERROR;
+	}
+	return err;
+}
+
+#ifdef ATE_BUILD
+static int
+wl_gpaio(void *wl, cmd_t *cmd, char **argv)
+{
+	char **p = argv;
+	int counter = 0;
+	wl_gpaio_option_t option;
+	BCM_REFERENCE(cmd);
+	while (*p) {
+		counter++;
+		p++;
+	}
+	if (counter != 2) {
+		return USAGE_ERROR;
+	}
+	if (strcmp("pmu_afeldo", argv[1]) == 0) {
+		option = GPAIO_PMU_AFELDO;
+	} else if (strcmp("pmu_txldo", argv[1]) == 0) {
+		option = GPAIO_PMU_TXLDO;
+	} else if (strcmp("pmu_vcoldo", argv[1]) == 0) {
+		option = GPAIO_PMU_VCOLDO;
+	} else if (strcmp("pmu_lnaldo", argv[1]) == 0) {
+		option = GPAIO_PMU_LNALDO;
+	} else if (strcmp("pmu_adcldo", argv[1]) == 0) {
+		option = GPAIO_PMU_ADCLDO;
+	} else if (strcmp("clear", argv[1]) == 0) {
+		option = GPAIO_PMU_CLEAR;
+	} else {
+		return USAGE_ERROR;
+	}
+	return (wlu_iovar_setint(wl, argv[0], (int)option));
+}
+#endif /* ATE_BUILD */
+
+
+static int
+wl_macdbg_pmac(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_macdbg_pmac_param_t pmac;
+	int err = BCME_OK;
+	char *p, opt;
+	char *retbuf;
+
+	memset(&pmac, 0, sizeof(pmac));
+	retbuf = malloc(WL_DUMP_BUF_LEN);
+	if (retbuf == NULL) {
+		printf("No memory to allocate return buffer\n");
+		return BCME_NOMEM;
+	}
+
+	/* skip the command name */
+	argv++;
+
+	/* Get the selection */
+	if ((p = *argv) == NULL) {
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	strncpy(pmac.type, p, MIN(strlen(p), sizeof(pmac.type)));
+	pmac.type[sizeof(pmac.type) - 1] = '\0';
+	/* skip the type */
+	argv++;
+
+	pmac.step = (uint8)(-1);
+	pmac.num = 0;
+	pmac.bitmap = 0;
+	pmac.addr_raw = FALSE;
+	pmac.w_en = FALSE;
+
+	while ((p = *argv)) {
+		argv++;
+		if (!strncmp(p, "-", 1)) {
+			if (strlen(p) > 2 || (p[1] != 'r' && *argv == NULL)) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			opt = p[1];
+
+			switch (opt) {
+				case 's':
+					pmac.step = strtol(*argv, NULL, 0);
+					argv++;
+					break;
+				case 'n':
+					pmac.num = strtol(*argv, NULL, 0);
+					argv++;
+					break;
+				case 'b':
+					pmac.bitmap = strtoul(*argv, NULL, 0);
+					argv++;
+					break;
+				case 'r':
+					pmac.addr_raw = TRUE;
+					break;
+				case 'w':
+					pmac.w_val = strtoul(*argv, NULL, 0);
+					pmac.w_en = TRUE;
+					argv++;
+					break;
+				default:
+					printf("Invalid option!!\n");
+					err = BCME_USAGE_ERROR;
+					goto exit;
+			}
+		} else {
+			pmac.addr[pmac.addr_num++] = strtol(p, NULL, 0);
+			if (pmac.addr_num >= MACDBG_PMAC_ADDR_INPUT_MAXNUM) {
+				printf("Reached input limitation!!\n");
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+	}
+
+	if ((err = wlu_iovar_getbuf(wl, cmd->name, &pmac,
+		sizeof(pmac), retbuf, WL_DUMP_BUF_LEN) < 0)) {
+		goto exit;
+	}
+
+	if (!pmac.w_en) {
+		fputs(retbuf, stdout);
+	}
+exit:
+	if (retbuf) {
+		free(retbuf);
+	}
+	return err;
+}
+
+static int wl_mu_rate(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	uint32 i = 0;
+	char *endptr = NULL;
+	mu_rate_t mu;
+	BCM_REFERENCE(cmd);
+
+	memset(&mu, 0x0, sizeof(mu));
+	if (!argv[1]) {
+		if ((err = wlu_iovar_getbuf(wl, cmd->name, NULL,
+		     0, &mu, sizeof(mu))) < 0) {
+			fprintf(stderr, "Error reading svmp memory %s %d\n", argv[0], err);
+			goto exit;
+		}
+
+		for (i = 0; i < 4; i++) {
+			printf("0x%04x ", mu.rate_user[i]);
+		}
+		printf("%s\n", mu.auto_rate ? "(Auto)" : "(Fixed)");
+		return err;
+	}
+
+	/* auto rate */
+	if (!stricmp(argv[1], "auto") || (!stricmp(argv[1], "-1"))) {
+		/* turn on auto rate */
+		/* wl svmp_mem 0x20060 1 0 */
+		mu.auto_rate = 1;
+		err = wlu_var_setbuf(wl, cmd->name, &mu, sizeof(mu));
+	} else {
+		for (i = 0; i < 4; i++) {
+			mu.rate_user[i] = 0xffff;
+		}
+
+		/* set rates */
+		mu.auto_rate = 0;
+		for (i = 1; i < 5; i++) {
+			if (!argv[i])
+				break;
+
+			mu.rate_user[i-1] = strtol(argv[i], &endptr, 0);
+		}
+
+		err = wlu_var_setbuf(wl, cmd->name, &mu, sizeof(mu));
+
+		/* barf if set mu_rate but blocked by mu_group */
+		if (err != BCME_OK) {
+			printf("Set fix rate failed!!!\n");
+			printf("Check if blocked by mu_group setting or other error\n");
+		}
+	}
+
+exit:
+	return err;
+}
+
+static int wl_mu_group(void *wl, cmd_t *cmd, char **argv)
+{
+	int m, n, ret = 0;
+	int16 temp;
+
+	mu_group_t mu_group;
+
+	mu_group.version = WL_MU_GROUP_PARAMS_VERSION;
+	mu_group.forced = WL_MU_GROUP_ENTRY_EMPTY;
+	mu_group.forced_group_mcs = WL_MU_GROUP_ENTRY_EMPTY;
+	mu_group.forced_group_num = 0;
+	mu_group.auto_group_num   = 0;
+	mu_group.group_method = WL_MU_GROUP_ENTRY_EMPTY;
+	mu_group.group_number = WL_MU_GROUP_ENTRY_EMPTY;
+	for (m = 0; m < WL_MU_GROUP_NGROUP_MAX; m++) {
+		for (n = 0; n < WL_MU_GROUP_NUSER_MAX; n++) {
+			mu_group.group_option[m][n] = WL_MU_GROUP_ENTRY_EMPTY;
+		}
+		mu_group.group_GID[m] = WL_MU_GROUP_ENTRY_EMPTY;
+	}
+
+	if (!argv[1]) {
+		/* read mode */
+		ret = wlu_iovar_getbuf(wl, cmd->name, NULL, 0, &mu_group, sizeof(mu_group));
+		if (mu_group.version != WL_MU_GROUP_PARAMS_VERSION) {
+			printf("\tIncorrect version "
+			    "of mu_group struct: expect %d but get %d\n",
+			    WL_MU_GROUP_PARAMS_VERSION, mu_group.version);
+			return BCME_BADARG;
+		}
+		printf("mu_group: ");
+		if (mu_group.forced == WL_MU_GROUP_MODE_FORCED) {
+			if (mu_group.forced_group_mcs == WL_MU_GROUP_MODE_FORCED) {
+				printf("forced (fixed MCS)\n");
+			} else {
+				printf("forced (auto MCS)\n");
+			}
+			for (m = 0; m < mu_group.forced_group_num; m++) {
+				printf("  Group %d: ", m);
+				for (n = 0; n < WL_MU_GROUP_NUSER_MAX; n++) {
+					if (mu_group.group_option[m][n]
+							!= WL_MU_GROUP_ENTRY_EMPTY) {
+						printf("0x%03x ",
+							mu_group.group_option[m][n]);
+					}
+				}
+				printf("\n");
+			}
+		} else {
+			printf("auto\n");
+			printf("VASIP grouping method: ");
+			if (mu_group.group_method > 0) {
+				printf("new method %d (%s)\n",
+					mu_group.group_method, mu_group.group_method_name);
+			} else {
+				printf("old method ");
+				printf("(one group for all admitted users with GID=9)\n");
+			}
+			printf("      group    number: %d\n", mu_group.group_number);
+			if (mu_group.auto_group_num > 0) {
+				printf("Latest recommended groups:\n");
+			}
+			for (m = 0; m < mu_group.auto_group_num; m++) {
+				printf("  Group %d: ", m);
+				for (n = 0; n < WL_MU_GROUP_NUSER_MAX; n++) {
+					if (mu_group.group_option[m][n]
+							!= WL_MU_GROUP_ENTRY_EMPTY) {
+						printf("0x%03x ",
+							mu_group.group_option[m][n]);
+					} else {
+						printf(" ---  ");
+					}
+				}
+				printf("(GID=%d)\n", mu_group.group_GID[m]);
+			}
+
+		}
+	} else {
+		argv++;
+		do {
+			char *s = *argv++;
+			if (!strcmp(s, "-h")) {
+				ret = BCME_USAGE_ERROR;
+				goto exit_mu_group;
+			} else if (!strcmp(s, "-m")) {
+				mu_group.group_method = (int16)strtol(*argv++, NULL, 0);
+				if (mu_group.group_method < WL_MU_GROUP_METHOD_MIN) {
+					ret = BCME_USAGE_ERROR;
+					printf("Incorrect -m: M<%d\n", WL_MU_GROUP_METHOD_MIN);
+					goto exit_mu_group;
+				}
+			} else if (!strcmp(s, "-n")) {
+				mu_group.group_number = (int16)strtol(*argv++, NULL, 0);
+				if ((mu_group.group_number < WL_MU_GROUP_NUMBER_AUTO_MIN) ||
+						(mu_group.group_number >
+							WL_MU_GROUP_NUMBER_AUTO_MAX)) {
+					ret = BCME_USAGE_ERROR;
+					printf("Incorrect '-n': N is not in the range %d~%d\n",
+						WL_MU_GROUP_NUMBER_AUTO_MIN,
+						WL_MU_GROUP_NUMBER_AUTO_MAX);
+					goto exit_mu_group;
+				}
+			} else if (!strcmp(s, "-f")) {
+				temp = (int)strtol(*argv++, NULL, 0);
+				if ((temp == WL_MU_GROUP_MODE_AUTO) ||
+						(temp == WL_MU_GROUP_MODE_FORCED)) {
+					mu_group.forced_group_mcs = temp;
+				}
+			} else if ((!strcmp(s, "-g")) && (mu_group.forced != 0)) {
+				temp = (int)strtol(*argv++, NULL, 0);
+				if (temp == WL_MU_GROUP_AUTO_COMMAND) {
+					mu_group.forced = WL_MU_GROUP_MODE_AUTO;
+					mu_group.forced_group_num = 0;
+				} else if ((temp < WL_MU_GROUP_NUMBER_FORCED_MAX) &&
+						(temp == mu_group.forced_group_num)) {
+					mu_group.forced = WL_MU_GROUP_MODE_FORCED;
+					mu_group.forced_group_num += 1;
+					m = temp;
+					n = 0;
+				} else {
+					ret = BCME_USAGE_ERROR;
+					printf("Incorrect to set froced group options: ");
+					if (temp != mu_group.forced_group_num) {
+						printf("group index should be successive\n");
+					}
+					if (mu_group.forced_group_num >=
+							WL_MU_GROUP_NUMBER_FORCED_MAX) {
+						printf("support up to %d forced options\n",
+							WL_MU_GROUP_NUMBER_FORCED_MAX);
+					}
+					goto exit_mu_group;
+				}
+			} else if (((mu_group.forced_group_num > 0)) && (n < 4)) {
+				mu_group.group_option[m][n] = (int16)strtol(s, NULL, 0);
+				n += 1;
+			}
+		} while (*argv);
+
+		if ((mu_group.forced == WL_MU_GROUP_MODE_FORCED) &&
+				((mu_group.group_method != WL_MU_GROUP_ENTRY_EMPTY) ||
+				(mu_group.group_number != WL_MU_GROUP_ENTRY_EMPTY))) {
+			ret = BCME_USAGE_ERROR;
+			printf("Incorrect to set forced grouping options "
+					"with auto grouping parameters\n");
+			goto exit_mu_group;
+		}
+
+		/* default is forced mcs for forced grouping */
+		/* if not specified forced_group_mcs when forced grouping, set forced_group_mcs=1 */
+		if ((mu_group.forced == WL_MU_GROUP_MODE_FORCED) &&
+				(mu_group.forced_group_mcs == WL_MU_GROUP_ENTRY_EMPTY)) {
+			mu_group.forced_group_mcs = WL_MU_GROUP_MODE_FORCED;
+		}
+
+		/* set mode */
+		ret = wlu_var_setbuf(wl, cmd->name, &mu_group, sizeof(mu_group));
+	}
+
+exit_mu_group:
+	return ret;
+}
+
+static int wl_mu_policy(void *wl, cmd_t *cmd, char **argv)
+{
+	mu_policy_t policy;
+	int err = -1;
+	uint32 val;
+
+	memset(&policy, 0, sizeof(mu_policy_t));
+	policy.version = WL_MU_POLICY_PARAMS_VERSION;
+	policy.length = sizeof(mu_policy_t);
+	if ((err = wlu_iovar_getbuf(wl, cmd->name, NULL, 0, &policy, sizeof(mu_policy_t))) < 0) {
+		return err;
+	}
+	/* Check the iovar version */
+	if (policy.version != WL_MU_POLICY_PARAMS_VERSION) {
+		err = BCME_BADARG;
+		goto exit_mu_policy;
+	}
+	if (!argv[1]) {
+		/* read mode */
+		printf("Current MU policy settings:\n");
+		printf("  scheduler: %s", policy.sched_timer? "ON":"OFF");
+		if (policy.sched_timer)
+			printf(", timer: %u seconds\n", policy.sched_timer);
+		else
+			printf(" \n");
+		printf("  performance monitors: %s\n", policy.pfmon? "ON":"OFF");
+		printf("  gpos performance monitors: %s\n", policy.pfmon_gpos? "ON":"OFF");
+		printf("  forced the same BW check: %s\n", policy.samebw? "ON":"OFF");
+		printf("  max number of rx streams in the clients: %u\n", policy.nrx);
+		printf("  max number of admitted clients: %u\n", policy.max_muclients);
+	} else {
+		argv++;
+		do {
+			char *s = *argv++;
+			if (!strcmp(s, "-h")) {
+				err = BCME_USAGE_ERROR;
+				goto exit_mu_policy;
+			} else if (!strcmp(s, "-sched_timer")) {
+				if (!*argv) {
+					err = BCME_USAGE_ERROR;
+					goto exit_mu_policy;
+				}
+				val = strtoul(*argv++, NULL, 0);
+				policy.sched_timer = val;
+			} else if (!strcmp(s, "-pfmon")) {
+				if (!*argv) {
+					err = BCME_USAGE_ERROR;
+					goto exit_mu_policy;
+				}
+				val = strtoul(*argv++, NULL, 0);
+				if ((val == WL_MU_POLICY_DISABLED) ||
+					(val == WL_MU_POLICY_ENABLED)) {
+					policy.pfmon = val;
+				} else {
+					err = BCME_USAGE_ERROR;
+					goto exit_mu_policy;
+				}
+			} else if (!strcmp(s, "-pfmon_gpos")) {
+				if (!*argv) {
+					err = BCME_USAGE_ERROR;
+					goto exit_mu_policy;
+				}
+				val = strtoul(*argv++, NULL, 0);
+				if ((val == WL_MU_POLICY_DISABLED) ||
+					(val == WL_MU_POLICY_ENABLED)) {
+					policy.pfmon_gpos = val;
+				} else {
+					err = BCME_USAGE_ERROR;
+					goto exit_mu_policy;
+				}
+			} else if (!strcmp(s, "-samebw")) {
+				if (!*argv) {
+					err = BCME_USAGE_ERROR;
+					goto exit_mu_policy;
+				}
+				val = strtoul(*argv++, NULL, 0);
+				if ((val == WL_MU_POLICY_DISABLED) ||
+					(val == WL_MU_POLICY_ENABLED)) {
+					policy.samebw = val;
+				} else {
+					err = BCME_USAGE_ERROR;
+					goto exit_mu_policy;
+				}
+			} else if (!strcmp(s, "-nrx")) {
+				if (!*argv) {
+					err = BCME_USAGE_ERROR;
+					goto exit_mu_policy;
+				}
+				val = strtoul(*argv++, NULL, 0);
+				if ((val >= WL_MU_POLICY_NRX_MIN) &&
+					(val <= WL_MU_POLICY_NRX_MAX)) {
+					policy.nrx = val;
+				} else {
+					err = BCME_USAGE_ERROR;
+					goto exit_mu_policy;
+				}
+			} else if (!strcmp(s, "-max_muclients")) {
+				if (!*argv) {
+					err = BCME_USAGE_ERROR;
+					goto exit_mu_policy;
+				}
+				val = strtoul(*argv++, NULL, 0);
+				policy.max_muclients = val;
+			}
+		} while (*argv);
+
+		/* set mode */
+		err = wlu_var_setbuf(wl, cmd->name, &policy, sizeof(policy));
+	}
+
+exit_mu_policy:
+	return err;
+}
+
+static int wl_svmp_mem(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	svmp_mem_t mem;
+	uint16 *svmp_buf;
+	uint32 i;
+	char *endptr = NULL;
+
+	if (!argv[1]) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	mem.addr = strtol(argv[1], &endptr, 0);
+
+	if (!argv[2]) {
+		fprintf(stderr, "%s: Length must be specified\n", cmd->name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	mem.len = strtol(argv[2], &endptr, 0);
+
+	if (argv[3]) {
+		mem.val = strtol(argv[3], &endptr, 0);
+		err = wlu_var_setbuf(wl, cmd->name, &mem, sizeof(mem));
+		goto exit;
+	}
+
+	if ((err = wlu_iovar_getbuf(wl, cmd->name, &mem,
+	     sizeof(mem), buf, WLC_IOCTL_MAXLEN)) < 0) {
+		fprintf(stderr, "Error reading svmp memory %s %d\n", argv[0], err);
+		goto exit;
+	}
+
+	svmp_buf = (uint16 *)buf;
+	for (i = 0; i < mem.len; i++) {
+		if (!(i&1) && (i+1 < mem.len))
+			printf("0x%04x", svmp_buf[i+1]);
+		else {
+			if ((i%2 != 0) || (i+1 < mem.len))
+				printf("%04x", svmp_buf[i-1]);
+			else
+				printf("0x%04x", svmp_buf[i]);
+		}
+		if (i && (i%2))
+			printf("\n");
+	}
+	printf("\n");
+exit:
+	return err;
+}
+
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+static void
+wl_svmp_sampcol_printf_configs(wl_svmp_sampcol_t *psampcol, uint16 mode)
+{
+	char *str_phy1mux[] = {"gpioOut", "fftOut", "dbgHx", "rx1mux"};
+	char *str_rx1mux[] = {"farrowOut", "iqCompOut", "dcFilterOut",
+	                          "rxFilterOut", "aciFilterOut"};
+	char *str_packmode[] = {"dual", "4-cores", "2-cores", "single-core"};
+	char *str_packorder[] = {"big", "little"};
+
+	printf("version of svmp sample collect params: %d\n", psampcol->version);
+	printf("  enable:     %d\n", psampcol->enable);
+	printf("  trigger:    %d", psampcol->trigger_mode);
+	if (psampcol->trigger_mode == SVMP_SAMPCOL_TRIGGER_PKTPROC_TRANSITION) {
+		printf(", %d -> %d\n", psampcol->trigger_mode_s[0], psampcol->trigger_mode_s[1]);
+	} else {
+		printf("\n");
+	}
+	printf("  waitcnt:    %d\n", psampcol->waitcnt);
+	printf("  caplen:     %d\n", psampcol->caplen);
+	printf("  samplerate: %dx\n", (psampcol->data_samplerate + 1));
+	printf("  data:       %s", str_phy1mux[psampcol->data_sel_phy1]);
+	if (psampcol->data_sel_phy1 == SVMP_SAMPCOL_PHY1MUX_RX1MUX) {
+		printf(" with %s\n",
+		           str_rx1mux[psampcol->data_sel_rx1-SVMP_SAMPCOL_RX1MUX_FARROWOUT]);
+	} else {
+		printf("\n");
+	}
+	printf("  dualcap:    ");
+	if (psampcol->data_sel_dualcap >= SVMP_SAMPCOL_RX1MUX_FARROWOUT) {
+		printf("%s\n",
+		           str_rx1mux[psampcol->data_sel_dualcap-SVMP_SAMPCOL_RX1MUX_FARROWOUT]);
+	} else {
+		printf("OFF\n");
+	}
+	printf("  pack:       %s, %s-endian",
+	           str_packmode[psampcol->pack_mode], str_packorder[psampcol->pack_order]);
+	if (psampcol->pack_mode == SVMP_SAMPCOL_PACK_1CORE) {
+		printf(" core%d\n", psampcol->pack_1core_sel);
+	} else {
+		printf("\n");
+	}
+	printf("  buf_addr:   0x%05x~0x%05x\n", psampcol->buff_addr_start, psampcol->buff_addr_end);
+	if (mode == 0) {
+		printf("  status:     overflow=%d, running=%d\n",
+		           psampcol->status&0x1, (psampcol->status&0x2)>>1);
+	}
+}
+
+static int
+wl_svmp_sampcol(void *wl, cmd_t *cmd, char **argv)
+{
+	int n;
+	int ret;
+
+	wl_svmp_sampcol_t sampcol;
+
+	uint16 cmd_nparam;
+	uint16 cmd_enable;
+
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint32 phyrev;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	if ((ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+		return ret;
+
+	phytype = dtoh32(revinfo.phytype);
+	phyrev = dtoh32(revinfo.phyrev);
+
+	if ((phytype != WLC_PHY_TYPE_AC) || ((phyrev != 32) && (phyrev != 33))) {
+		return BCME_USAGE_ERROR;
+	}
+
+	sampcol.version           = WL_SVMP_SAMPCOL_PARAMS_VERSION;
+	sampcol.enable            = 0;
+	sampcol.trigger_mode      = SVMP_SAMPCOL_TRIGGER_PKTPROC_TRANSITION;
+	sampcol.trigger_mode_s[0] = SVMP_SAMPCOL_PKTPROC_OFDM_PHY;
+	sampcol.trigger_mode_s[1] = SVMP_SAMPCOL_PKTPROC_TIMING_SEARCH;
+	sampcol.waitcnt           = 0;
+	sampcol.caplen            = 128;
+	sampcol.data_samplerate   = SVMP_SAMPCOL_SAMPLERATE_2XBW;
+	sampcol.data_sel_phy1     = SVMP_SAMPCOL_PHY1MUX_RX1MUX;
+	sampcol.data_sel_rx1      = SVMP_SAMPCOL_RX1MUX_FARROWOUT;
+	sampcol.data_sel_dualcap  = 0;
+	sampcol.pack_mode         = SVMP_SAMPCOL_PACK_4CORE;
+	sampcol.pack_order        = 0;
+	sampcol.pack_cfix_fmt     = 0;
+	sampcol.pack_1core_sel    = 0;
+	sampcol.buff_addr_start   = 0x25800;
+	sampcol.buff_addr_end     = 0x26800;
+	sampcol.int2vasip         = 1;
+
+	ret = -1;
+	cmd_nparam = 0;
+	cmd_enable = 0;
+
+	argv++;
+	while (*argv) {
+		char *s = *argv++;
+		if (*argv == NULL) {
+			ret = BCME_USAGE_ERROR;
+			goto exit_svmp_sampcol;
+		}
+		if (!strcmp(s, "-h")) {
+			ret = BCME_USAGE_ERROR;
+			goto exit_svmp_sampcol;
+		} else if (!strcmp(s, "-e")) {
+			cmd_nparam++;
+			sampcol.enable = (uint8)strtol(*argv++, NULL, 0);
+			cmd_enable = 1;
+		} else if (!strcmp(s, "-t")) {
+			cmd_nparam++;
+			sampcol.trigger_mode = (uint8)strtol(*argv++, NULL, 0);
+			if (sampcol.trigger_mode == SVMP_SAMPCOL_TRIGGER_PKTPROC_TRANSITION) {
+				for (n = 0; n < 2; n++) {
+					if (*argv == NULL) {
+						ret = BCME_USAGE_ERROR;
+						goto exit_svmp_sampcol;
+					} else {
+						sampcol.trigger_mode_s[n]
+						    = (uint8)strtol(*argv++, NULL, 0);
+					}
+				}
+			}
+		} else if (!strcmp(s, "-w")) {
+			cmd_nparam++;
+			sampcol.waitcnt = (uint16)strtol(*argv++, NULL, 0);
+		} else if (!strcmp(s, "-l")) {
+			cmd_nparam++;
+			sampcol.caplen = (uint16)strtol(*argv++, NULL, 0);
+		} else if (!strcmp(s, "-s")) {
+			cmd_nparam++;
+			sampcol.data_sel_phy1 = (uint8)strtol(*argv++, NULL, 0);
+			if ((sampcol.data_sel_phy1 == SVMP_SAMPCOL_PHY1MUX_RX1MUX) &&
+			        strncmp(*argv, "-", 1)) {
+				sampcol.data_sel_rx1 = (uint8)strtol(*argv++, NULL, 0);
+			}
+		} else if (!strcmp(s, "-d")) {
+			cmd_nparam++;
+			sampcol.data_sel_dualcap = (uint8)strtol(*argv++, NULL, 0);
+		} else if (!strcmp(s, "-r")) {
+			cmd_nparam++;
+			sampcol.data_samplerate = (uint8)strtol(*argv++, NULL, 0);
+		} else if (!strcmp(s, "-p")) {
+			cmd_nparam++;
+			sampcol.pack_mode     = (uint8)strtol(*argv++, NULL, 0);
+			if (strncmp(*argv, "-", 1)) {
+				sampcol.pack_order    = (uint8)strtol(*argv++, NULL, 0);
+			}
+			if (strncmp(*argv, "-", 1)) {
+				sampcol.pack_cfix_fmt = (uint8)strtol(*argv++, NULL, 0);
+			}
+			if ((phytype == WLC_PHY_TYPE_AC) && (phyrev == 33) &&
+			        (sampcol.pack_mode == SVMP_SAMPCOL_PACK_1CORE)) {
+				if (strncmp(*argv, "-", 1)) {
+					sampcol.pack_1core_sel = (uint8)strtol(*argv++, NULL, 0);
+				}
+			}
+		} else if (!strcmp(s, "-a")) {
+			cmd_nparam++;
+			sampcol.buff_addr_start = (uint32)strtol(*argv++, NULL, 0);
+			if (strncmp(*argv, "-", 1)) {
+				sampcol.buff_addr_end   = (uint32)strtol(*argv++, NULL, 0);
+			}
+		} else {
+			argv++;
+		}
+	}
+
+	if ((cmd_nparam == 0) || ((cmd_enable == 1) && (cmd_nparam == 1))) {
+		cmd_enable = sampcol.enable;
+		ret = wlu_iovar_get(wl, cmd->name, &sampcol, sizeof(wl_svmp_sampcol_t));
+		if (sampcol.version != WL_SVMP_SAMPCOL_PARAMS_VERSION) {
+			printf("\tIncorrect version "
+			"of SVMP_SAMPCOL_PARAMS struct: expect %d but get %d\n",
+			WL_SVMP_SAMPCOL_PARAMS_VERSION, sampcol.version);
+			return BCME_BADARG;
+		}
+		if (cmd_nparam == 1) {
+			sampcol.enable = cmd_enable;
+		} else {
+			wl_svmp_sampcol_printf_configs(&sampcol, 0);
+		}
+	}
+	if (cmd_nparam > 0) {
+		wl_svmp_sampcol_printf_configs(&sampcol, 1);
+		ret = wlu_var_setbuf(wl, cmd->name, &sampcol, sizeof(wl_svmp_sampcol_t));
+	}
+
+exit_svmp_sampcol:
+	return ret;
+}
+#endif 
+
+static int
+wl_scanmac(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	char *subcmd;
+	int subcmd_len;
+
+	/* skip iovar */
+	argv++;
+
+	/* must have subcommand */
+	subcmd = *argv++;
+	if (!subcmd) {
+		return BCME_USAGE_ERROR;
+	}
+	subcmd_len = strlen(subcmd);
+
+	if (!*argv) {
+		/* get */
+		uint8 buffer[OFFSETOF(wl_scanmac_t, data)];
+		wl_scanmac_t *sm = (wl_scanmac_t *)buffer;
+		int len = OFFSETOF(wl_scanmac_t, data);
+
+		memset(sm, 0, len);
+		if (!strncmp(subcmd, "enable", subcmd_len)) {
+			sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
+		} else if (!strncmp(subcmd, "bsscfg", subcmd_len)) {
+			sm->subcmd_id = WL_SCANMAC_SUBCMD_BSSCFG;
+		} else if (!strncmp(subcmd, "config", subcmd_len)) {
+			sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+		/* invoke GET iovar */
+		sm->subcmd_id = dtoh16(sm->subcmd_id);
+		sm->len = dtoh16(sm->len);
+		if ((err = wlu_iovar_getbuf(wl, cmd->name, sm, len, buf, WLC_IOCTL_SMLEN)) < 0) {
+			return err;
+		}
+
+		/* process and print GET results */
+		sm = (wl_scanmac_t *)buf;
+		sm->subcmd_id = dtoh16(sm->subcmd_id);
+		sm->len = dtoh16(sm->len);
+
+		switch (sm->subcmd_id) {
+		case WL_SCANMAC_SUBCMD_ENABLE:
+		{
+			wl_scanmac_enable_t *sm_enable = (wl_scanmac_enable_t *)sm->data;
+			if (sm->len >= sizeof(*sm_enable)) {
+				printf("%d\n", sm_enable->enable);
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		case WL_SCANMAC_SUBCMD_BSSCFG:
+		{
+			wl_scanmac_bsscfg_t *sm_bsscfg = (wl_scanmac_bsscfg_t *)sm->data;
+			if (sm->len >= sizeof(*sm_bsscfg)) {
+				sm_bsscfg->bsscfg = dtoh32(sm_bsscfg->bsscfg);
+				printf("%d\n", sm_bsscfg->bsscfg);
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		case WL_SCANMAC_SUBCMD_CONFIG:
+		{
+			wl_scanmac_config_t *sm_config = (wl_scanmac_config_t *)sm->data;
+			if (sm->len >= sizeof(*sm_config)) {
+				sm_config->scan_bitmap = dtoh16(sm_config->scan_bitmap);
+				printf("mac:         %s\n", wl_ether_etoa(&sm_config->mac));
+				printf("random mask: %s\n", wl_ether_etoa(&sm_config->random_mask));
+				printf("scan bitmap: 0x%02X\n", sm_config->scan_bitmap);
+				if (sm_config->scan_bitmap & WL_SCANMAC_SCAN_UNASSOC) {
+					printf("             unassoc\n");
+				}
+				if (sm_config->scan_bitmap & WL_SCANMAC_SCAN_ASSOC_ROAM) {
+					printf("             assoc roam\n");
+				}
+				if (sm_config->scan_bitmap & WL_SCANMAC_SCAN_ASSOC_PNO) {
+					printf("             assoc PNO\n");
+				}
+				if (sm_config->scan_bitmap & WL_SCANMAC_SCAN_ASSOC_HOST) {
+					printf("             assoc host\n");
+				}
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		default:
+			break;
+		}
+	}
+	else {
+		/* set */
+		uint8 buffer[OFFSETOF(wl_scanmac_t, data) +
+			MAX(sizeof(wl_scanmac_enable_t), sizeof(wl_scanmac_config_t))];
+		wl_scanmac_t *sm = (wl_scanmac_t *)buffer;
+		int len = OFFSETOF(wl_scanmac_t, data);
+
+		if (!strncmp(subcmd, "enable", subcmd_len) &&
+			(*argv[0] == '0' || *argv[0] == '1')) {
+			wl_scanmac_enable_t *sm_enable = (wl_scanmac_enable_t *)sm->data;
+			sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
+			sm->len = sizeof(*sm_enable);
+			sm_enable->enable = atoi(argv[0]);
+		} else if (!strncmp(subcmd, "config", subcmd_len) &&
+			argv[0] && argv[1] && argv[2]) {
+			wl_scanmac_config_t *sm_config = (wl_scanmac_config_t *)sm->data;
+			char *mac = argv[0];
+			char *mask = argv[1];
+			char *bitmap = argv[2];
+			sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
+			sm->len = sizeof(*sm_config);
+			if (!wl_ether_atoe(mac, &sm_config->mac) ||
+				!wl_ether_atoe(mask, &sm_config->random_mask)) {
+				return BCME_USAGE_ERROR;
+			}
+			sm_config->scan_bitmap = (uint16)strtoul(bitmap, NULL, 0);
+			sm_config->scan_bitmap = htod16(sm_config->scan_bitmap);
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+		/* invoke SET iovar */
+		len = OFFSETOF(wl_scanmac_t, data) + sm->len;
+		sm->subcmd_id = htod16(sm->subcmd_id);
+		sm->len = htod16(sm->len);
+		err = wlu_iovar_set(wl, cmd->name, sm, len);
+	}
+
+	return err;
+}
+
+static int wl_winver(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	wl_winver_t wv;
+
+	UNUSED_PARAMETER(argv);
+
+	memset(&wv, 0, sizeof(wv));
+	err = wlu_iovar_get(wl, cmd->name, &wv, sizeof(wv));
+
+	if ((err == BCME_OK) && (wv.struct_version >= WL_WINVER_STRUCT_VER_1)) {
+		printf("\n"
+			"Windows OS ver= %d.%d.%d\n"
+			"NDIS Runtime  = %d.%d\n"
+			"NDIS Driver   = %d.%d\n"
+			"WDI UE version= %d.%d_%X\n"
+			"WDI LE version= %d.%d_%X\n",
+			wv.os_runtime.major_ver, wv.os_runtime.minor_ver, wv.os_runtime.build,
+			wv.ndis_runtime.major_ver, wv.ndis_runtime.minor_ver,
+			wv.ndis_driver.major_ver, wv.ndis_driver.minor_ver,
+			wv.wdi_ue.major_ver, wv.wdi_ue.minor_ver, wv.wdi_ue.suffix,
+			wv.wdi_le.major_ver, wv.wdi_le.minor_ver, wv.wdi_le.suffix);
+	}
+
+	return err;
+}
+
+#define TCMS_MAX_CORES		(8)
+#define TCMS_INPUT_BUFSIZE	(1 + 1 + 1)
+
+static int
+wl_get_tcmstbl_entry(void *wl, cmd_t *cmd, char **argv)
+{
+	int32 wl_tcmsarg[TCMS_INPUT_BUFSIZE] = {0, 0, 0};
+	int32* obuf = (int32 *)buf;
+	int err, opt_err;
+	miniopt_t to;
+	const char* fn_name = "wl_get_tcmstbl_entry";
+	int argc = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* counting the number of arguments */
+	while (argv[argc])
+		argc++;
+
+	if (argc < 2)
+		return BCME_USAGE_ERROR;
+
+	memset(buf, 0, WLC_IOCTL_MEDLEN);
+
+	/* toss the command name */
+	argv++;
+
+	/* Validate arguments if any */
+	if (*argv) {
+		miniopt_init(&to, fn_name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 'c') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int for core\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if (to.val > (TCMS_MAX_CORES-1)) {
+					fprintf(stderr,
+						"%s: invalid core %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				wl_tcmsarg[0] = to.val;
+			}
+			if (to.opt == 'a') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as"
+						" an int for antenna map\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				wl_tcmsarg[1] = to.val;
+			}
+			if (to.opt == 's') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as"
+						" an int for cell status\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val < 0) | (to.val > 1)) {
+					fprintf(stderr,
+						"%s: invalid cell status %d\n",
+						fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				wl_tcmsarg[2] = to.val;
+			}
+		}
+	} else {
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	if ((err = wlu_iovar_getbuf(wl, "tcmstbl", wl_tcmsarg, sizeof(wl_tcmsarg),
+			buf, WLC_IOCTL_MEDLEN)) < 0) {
+		printf("\n Incorrect option \n");
+		err = BCME_BADOPTION;
+		goto exit;
+	}
+
+	printf("(Nsts {4..1}) { %d hdBm  0x%02x } { %d hdBm  0x%02x }"
+		"{ %d hdBm  0x%02x } { %d hdBm  0x%02x }\n",
+		obuf[10], obuf[11], obuf[8], obuf[9],
+		obuf[6], obuf[7], obuf[4], obuf[5]);
+	printf("OFDM { %d hdBm  0x%02x }  CCK { %d hdBm  0x%02x }\n",
+		obuf[2], obuf[3], obuf[0], obuf[1]);
+exit:
+	return err;
+}
+
+/*
+ *  get/set IPv6 RA rate limit interval
+ */
+static int
+wl_nd_ra_limit_intv(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0, opt_err;
+	miniopt_t to;
+	nd_ra_ol_limits_t *ra_limit = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((err = wlu_var_getbuf(wl,
+		"nd_ra_limit_intv", NULL, 0, (void *)&ra_limit) < 0)) {
+		printf("nd_ra_limit_intv: getbuf ioctl failed\n");
+		return err;
+	}
+
+	if (*++argv) {
+		/* set */
+		if (argv[0][0] == 'h' ||
+				argv[0][0] == '?') {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		ra_limit = calloc(1, sizeof(nd_ra_ol_limits_t));
+		if (ra_limit == NULL) {
+			return BCME_NOMEM;
+		}
+
+		miniopt_init(&to, __FUNCTION__, NULL, FALSE);
+
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+			if (to.opt == 't') {
+				if (!to.good_int) {
+					fprintf(stderr, "could not parse %s as an int for"
+						" type\n", to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				ra_limit->type = to.val;
+			}
+
+			if (to.opt == 'p') {
+				if (!to.good_int) {
+					fprintf(stderr, "could not parse %s as an int for"
+						" percentage value\n", to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				ra_limit->limits.lifetime_relative.lifetime_percent = to.val;
+			}
+
+			if (to.opt == 'm') {
+				if (!to.good_int) {
+					fprintf(stderr, "could not parse %s as an int for"
+						" min_time\n", to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				ra_limit->limits.lifetime_relative.min_time = to.val;
+			}
+		}
+
+		ra_limit->version = ND_RA_OL_LIMITS_VER;
+
+		if (ra_limit->type == ND_RA_OL_LIMITS_REL_TYPE) {
+			printf("type %d, lifetime_percent %d, min_time %d\n",
+				ra_limit->type,
+				ra_limit->limits.lifetime_relative.lifetime_percent,
+				ra_limit->limits.lifetime_relative.min_time);
+			ra_limit->length = ND_RA_OL_LIMITS_REL_TYPE_LEN;
+		} else if (ra_limit->type == ND_RA_OL_LIMITS_FIXED_TYPE) {
+			printf("type %d, min_time %d\n",
+				ra_limit->type,
+				ra_limit->limits.fixed.hold_time);
+			ra_limit->length = ND_RA_OL_LIMITS_FIXED_TYPE_LEN;
+		} else {
+			printf("Invalid nd_ra_limit_intv type %d\n",
+				ra_limit->type);
+			err = BCME_BADARG;
+			goto exit;
+		}
+
+		if ((err = wlu_var_setbuf(wl, "nd_ra_limit_intv", ra_limit,
+				sizeof(nd_ra_ol_limits_t)) < 0)) {
+			printf("%s: failed to set %d\n", cmd->name, err);
+		}
+	} else {
+		/* get */
+		if (ra_limit->version != ND_RA_OL_LIMITS_VER) {
+			printf("Invalid nd_ra_limit_intv version %d\n",
+				ra_limit->version);
+			err = BCME_VERSION;
+			goto exit;
+		}
+
+		if (ra_limit->type == ND_RA_OL_LIMITS_REL_TYPE) {
+			printf(" type %d, percentage %d, fixed time %d\n",
+				ra_limit->type,
+				ra_limit->limits.lifetime_relative.lifetime_percent,
+				ra_limit->limits.lifetime_relative.min_time);
+		} else if (ra_limit->type == ND_RA_OL_LIMITS_FIXED_TYPE) {
+			printf(" type %d, fixed time %d\n",
+				ra_limit->type,
+				ra_limit->limits.fixed.hold_time);
+		} else {
+			printf("Invalid nd_ra_limit_intv type %d\n",
+				ra_limit->type);
+			err = BCME_BADARG;
+			goto exit;
+		}
+	}
+
+exit:
+	if (ra_limit) {
+		free(ra_limit);
+	}
+
+	return err;
+}
+
+int
+wl_ccode_info(void *wl, cmd_t *cmd, char **argv)
+{
+	int error, i;
+	void *ptr;
+	const char* abbrev;
+	wl_ccode_info_t *ci;
+	wl_ccode_entry_t *ce;
+	cntry_name_t *cntry;
+	const char *band_type[] = {"2G", "5G"};
+	const char *ccode_type[] = {"accode", "hdcode", "11dassoccode", "11dscancode", "defccode"};
+
+	/* skip the command name */
+	argv++;
+
+	if ((error = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return (error);
+
+	ci = (wl_ccode_info_t *)ptr;
+	if (dtoh16(ci->version) != CCODE_INFO_VERSION) {
+		printf("\tIncorrect version of ccode_info IOVAR expected %d; got %d\n",
+				CCODE_INFO_VERSION, dtoh16(ci->version));
+		return -1;
+	}
+	if (dtoh16(ci->count) > 2 * WLC_NUM_CCODE_INFO) {
+		printf("\tBigger than expected country codes. Expected:%d; got %d\n",
+				2 * WLC_NUM_CCODE_INFO, dtoh16(ci->count));
+		return -1;
+	}
+	for (i = 0; i < dtoh16(ci->count); i++) {
+		ce = &ci->ccodelist[i];
+		abbrev = ce->ccode;
+		cntry = wlc_cntry_abbrev_to_country(abbrev);
+		printf("%s\t%s:%s\t%s\n",
+				band_type[ce->band],
+				ccode_type[ce->role],
+				abbrev, cntry ? cntry->name : "");
+	}
+	return 0;
+}
+
+#if defined(linux)
+int
+wl_wait_for_event(void *wl, char **argv, uint event_id, uint evbuf_size,
+	void (*event_cb_fn)(int event_type, bcm_event_t *bcm_event))
+{
+	int err = BCME_OK;
+	int fd, octets;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	char ifnames[IFNAMSIZ] = {"eth1"};
+	uint8 event_buf[WL_EVENTINT_MAX_GET_SIZE];
+	eventmsgs_ext_t *eventmsgs;
+	char *data;
+
+	/* Override default ifname explicitly or implicitly */
+	if (*++argv) {
+		if (strlen(*argv) >= IFNAMSIZ) {
+			printf("Interface name %s too long\n", *argv);
+			return -1;
+		}
+		strncpy(ifnames, *argv, IFNAMSIZ);
+	} else if (wl) {
+		strncpy(ifnames, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	}
+	ifnames[IFNAMSIZ - 1] = '\0';
+
+	/* set event bit using 'event_msgs_ext' */
+	if ((event_id / 8) >= WL_EVENTING_MASK_MAX_LEN) {
+		printf("Event Id %d exceeds max %d event bytes\n",
+			event_id, WL_EVENTING_MASK_MAX_LEN);
+		goto exit2;
+	}
+	memset(event_buf, 0, sizeof(event_buf));
+	eventmsgs = (eventmsgs_ext_t *)event_buf;
+	eventmsgs->ver = EVENTMSGS_VER;
+	eventmsgs->command = EVENTMSGS_SET_BIT;
+	eventmsgs->len = WL_EVENTING_MASK_MAX_LEN;
+	eventmsgs->mask[event_id / 8] |= 1 << (event_id % 8);
+	if ((err = wlu_var_setbuf(wl, "event_msgs_ext", eventmsgs,
+		EVENTMSGS_EXT_STRUCT_SIZE + eventmsgs->len)) < 0) {
+		printf("Failed to set event mask\n");
+		goto exit2;
+	}
+
+	/* Open a socket to read driver WLC_E_* events */
+	memset(&ifr, 0, sizeof(ifr));
+	if (wl)
+		strncpy(ifr.ifr_name, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	else
+		strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		err = -1;
+		goto exit2;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("%s: Cannot get index %d\n", __FUNCTION__, err);
+		goto exit1;
+	}
+
+	/* bind the socket first before starting so we won't miss any event */
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		goto exit1;
+	}
+
+	data = (char*)malloc(evbuf_size);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %u bytes for events receive buffer\n",
+			evbuf_size);
+		err = -1;
+		goto exit1;
+	}
+
+	/* Loop forever to receive driver events */
+	while (1) {
+		bcm_event_t *bcm_event;
+		int event_type;
+
+		octets = recv(fd, data, evbuf_size, 0);
+		bcm_event = (bcm_event_t *)data;
+		event_type = ntoh32(bcm_event->event.event_type);
+		if (octets >= (int)sizeof(bcm_event_t)) {
+			event_cb_fn(event_type, bcm_event);
+		}
+	}
+
+	free(data);
+exit1:
+	close(fd);
+exit2:
+	return err;
+}
+#endif	/* linux */
+
+#define SIM_PM_MAX_CYCLE 10000
+#define SIM_PM_MAX_UP 1000
+#define SIM_PM_DEF_CYCLE 100
+#define SIM_PM_DEF_UP 5
+
+static int
+wl_sim_pm(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_OK, opt_err;
+	miniopt_t to;
+	const char* fn_name = "wl_sim_pm";
+	sim_pm_params_t *params = (sim_pm_params_t *)buf;
+
+	if ((err = wlu_iovar_getbuf(wl, cmd->name, NULL, 0, buf, WLC_IOCTL_SMLEN)) < 0) {
+		printf("Get %s got error %d\n", cmd->name, err);
+		goto exit;
+	}
+
+	if (!*++argv) {
+		printf("%sabled, Cycle time: %u TUs, Up time: %u TUs\n", params->enabled ? "En" :
+			"Dis", params->cycle, params->up);
+		goto exit;
+	}
+	miniopt_init(&to, fn_name, NULL, FALSE);
+	while ((opt_err = miniopt(&to, argv)) != -1) {
+		if (opt_err == 1) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv += to.consumed;
+
+		if (to.opt == '\0') {
+			if (!to.good_int) {
+				fprintf(stderr, "%s: could not parse \"%s\" as an int for enable\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (to.val != 0 && to.val != 1) {
+				fprintf(stderr, "%s: invalid enable parameter. [0|1]\n", fn_name);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->enabled = to.val;
+		}
+		if (to.opt == 'c') {
+			if (!to.good_int) {
+				fprintf(stderr, "%s: could not parse \"%s\" as an int for cycle\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (to.val <= 0 || to.val > SIM_PM_MAX_CYCLE) {
+				fprintf(stderr, "%s: invalid cycle time. Max. %d\n", fn_name,
+					SIM_PM_MAX_CYCLE);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->cycle = to.val;
+		}
+		if (to.opt == 'u') {
+			if (!to.good_int) {
+				fprintf(stderr, "%s: could not parse \"%s\" as an int for up\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (to.val <= 0 || to.val > SIM_PM_MAX_UP) {
+				fprintf(stderr, "%s: invalid up time. Max. %d\n", fn_name,
+					SIM_PM_MAX_UP);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->up = to.val;
+		}
+	}
+	params->cycle = params->cycle ? params->cycle : SIM_PM_DEF_CYCLE;
+	params->up = params->up ? params->up : SIM_PM_DEF_UP;
+	if (params->up >= params->cycle) {
+		fprintf(stderr, "%s: cycle time (%d) should be greater than up time (%d).\n",
+				fn_name, params->cycle, params->up);
+		err = BCME_BADARG;
+		goto exit;
+	}
+	if ((err = wlu_iovar_set(wl, cmd->name, params, sizeof(*params))) < 0) {
+		printf("Error setting variable %s\n", cmd->name);
+		return err;
+	}
+exit:
+	return err;
+}
+
+/*
+ * Health Check "hc" iovar support
+ */
+
+/* hc command information structure, forward decl. */
+struct hc_sub_cmd_ent;
+
+/* hc sub-command handler function, used in the hc command tables */
+typedef int (*hc_cmd_fn_t)(void *wl, uint16 category, struct hc_sub_cmd_ent *hc_cmd, char **argv);
+
+/* hc command information structure, definition
+ * Used to dispatch action based on a sub-command name
+ */
+struct hc_sub_cmd_ent {
+	const char *name;	/* sub-command name for command line */
+	uint16 id;			/* cmd id for the handler fn */
+	hc_cmd_fn_t fn;		/* sub-command handler fn */
+};
+typedef struct hc_sub_cmd_ent hc_sub_cmd_table_t[];
+
+static struct hc_sub_cmd_ent* wl_hc_cmd_lookup(hc_sub_cmd_table_t tbl, char* cmd);
+static void wl_hc_subcommand_list_dump(void *wl, const char *category, hc_sub_cmd_table_t tbl);
+static int wl_hc_int(void *wl, uint16 category, struct hc_sub_cmd_ent *hc_cmd, char** argv);
+static int wl_hc_exclude_bitmap(void *wl, uint16 category, struct hc_sub_cmd_ent *hc_cmd,
+	char** argv);
+static int wl_hc_setints(void *wl, uint16 category, struct hc_sub_cmd_ent *hc_cmd,
+	int int_count, char **argv);
+static int wl_hc_getints(void *wl, uint16 category, struct hc_sub_cmd_ent *hc_cmd,
+	int int_count, char **argv);
+
+/* HC Tx category commands */
+struct hc_sub_cmd_ent hc_tx_cmds[] = {
+	{"stall_threshold",   WL_HC_TX_XTLV_ID_VAL_STALL_THRESHOLD,   wl_hc_int},
+	{"stall_sample_size", WL_HC_TX_XTLV_ID_VAL_STALL_SAMPLE_SIZE, wl_hc_int},
+	{"stall_timeout",     WL_HC_TX_XTLV_ID_VAL_STALL_TIMEOUT,     wl_hc_int},
+	{"stall_force",       WL_HC_TX_XTLV_ID_VAL_STALL_FORCE,       wl_hc_int},
+	{"stall_exclude",     WL_HC_TX_XTLV_ID_VAL_STALL_EXCLUDE,     wl_hc_exclude_bitmap},
+	{"fc_timeout",        WL_HC_TX_XTLV_ID_VAL_FC_TIMEOUT,        wl_hc_int},
+	{"fc_force",          WL_HC_TX_XTLV_ID_VAL_FC_FORCE,          wl_hc_int},
+	/* NUL terminated table */
+	{NULL, 0, NULL},
+};
+
+/* HC Rx category commands */
+hc_sub_cmd_table_t hc_rx_cmds = {
+	{"dma_stall_timeout", WL_HC_RX_XTLV_ID_VAL_DMA_STALL_TIMEOUT, wl_hc_int},
+	{"dma_stall_force",   WL_HC_RX_XTLV_ID_VAL_DMA_STALL_FORCE,   wl_hc_int},
+	{"stall_threshold",   WL_HC_RX_XTLV_ID_VAL_STALL_THRESHOLD,   wl_hc_int},
+	{"stall_sample_size", WL_HC_RX_XTLV_ID_VAL_STALL_SAMPLE_SIZE, wl_hc_int},
+	{"stall_force",       WL_HC_RX_XTLV_ID_VAL_STALL_FORCE,       wl_hc_int},
+	/* NUL terminated table */
+	{NULL, 0, NULL},
+};
+
+/* Main command line handler for Health Check 'hc' iovar */
+static int
+wl_hc(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	char *sub_cmd_name;
+	struct hc_sub_cmd_ent *sub_cmd;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* Skip the command name */
+	argv++;
+
+	sub_cmd_name = *argv++;
+
+	if (sub_cmd_name == NULL) {
+		/* usage */
+		printf("hc: missing category\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!strcmp(sub_cmd_name, "tx")) {
+		char* attr_name;
+
+		attr_name = *argv++;
+
+		if (attr_name == NULL) {
+			/* usage */
+			printf("hc tx: missing attribute\n");
+			wl_hc_subcommand_list_dump(wl, sub_cmd_name, hc_tx_cmds);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* grab the command info from the sub-command table */
+		sub_cmd = wl_hc_cmd_lookup(hc_tx_cmds, attr_name);
+
+		if (sub_cmd == NULL) {
+			/* usage */
+			printf("hc tx: unknown sub-command \"%s\"\n", attr_name);
+			wl_hc_subcommand_list_dump(wl, sub_cmd_name, hc_tx_cmds);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* execute the sub command */
+		ret = (*sub_cmd->fn)(wl, WL_HC_XTLV_ID_CAT_DATAPATH_TX, sub_cmd, argv);
+
+	} else if (!strcmp(sub_cmd_name, "rx")) {
+		char* attr_name;
+
+		attr_name = *argv++;
+
+		if (attr_name == NULL) {
+			/* usage */
+			printf("hc rx: missing attribute\n");
+			wl_hc_subcommand_list_dump(wl, sub_cmd_name, hc_rx_cmds);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* grab the command info from the sub-command table */
+		sub_cmd = wl_hc_cmd_lookup(hc_rx_cmds, attr_name);
+
+		if (sub_cmd == NULL) {
+			/* usage */
+			printf("hc rx: unknown sub-command \"%s\"\n", attr_name);
+			wl_hc_subcommand_list_dump(wl, sub_cmd_name, hc_rx_cmds);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* execute the sub command */
+		ret = (*sub_cmd->fn)(wl, WL_HC_XTLV_ID_CAT_DATAPATH_RX, sub_cmd, argv);
+
+	} else {
+		/* usage */
+		printf("unknown hc category \"%s\"\n", sub_cmd_name);
+		return BCME_USAGE_ERROR;
+	}
+
+	return ret;
+}
+
+/* Generic set/get of an integer attribute.
+ * Just issue a wl_hc_setints() if there is a 2nd arg, or wl_hc_getints() otherwise.
+ */
+static int
+wl_hc_int(void *wl, uint16 category, struct hc_sub_cmd_ent *hc_cmd, char** argv)
+{
+	if (argv[0] != NULL)
+		return (wl_hc_setints(wl, category, hc_cmd, 1, argv));
+	else
+		return (wl_hc_getints(wl, category, hc_cmd, 1, argv));
+}
+
+/* Set/Get of the "exclude" bitmap.
+ * Just issue a wl_hc_setints() for 2 ints if there is a 2nd arg,
+ * or wl_hc_getints() for 2 ints otherwise.
+ */
+static int
+wl_hc_exclude_bitmap(void *wl, uint16 category, struct hc_sub_cmd_ent *hc_cmd, char** argv)
+{
+	if (argv[0] != NULL)
+		return (wl_hc_setints(wl, category, hc_cmd, 2, argv));
+	else
+		return (wl_hc_getints(wl, category, hc_cmd, 2, argv));
+}
+
+static int
+wl_hc_setints(void *wl, uint16 category, struct hc_sub_cmd_ent *hc_cmd, int int_count, char **argv)
+{
+	char *valstr;
+	char *endptr = NULL;
+	bcm_xtlv_t *hc_tlv;
+	struct {
+		uint16 id;
+		uint16 len;
+		uint32 value[1];
+	} *val_xtlv;
+	uint32 words[2];
+	int i;
+	uint out_len;
+	uint16 val_payload_len;
+	uint16 container_payload_len;
+	uint32 val;
+	int ret = 0;
+
+	for (i = 0; i < int_count; i++) {
+		valstr = *argv++;
+
+		if (!valstr || valstr[0] == '\0') {
+			printf("hc set: missing value argument for set of \"%s\"\n", hc_cmd->name);
+			return BCME_USAGE_ERROR;
+		}
+
+		val = strtoul(valstr, &endptr, 0);
+		if (*endptr != '\0') {
+			/* not all the value string was parsed by strtol */
+			printf("set: error parsing value \"%s\" as an integer for set of \"%s\"\n",
+			       valstr, hc_cmd->name);
+			return BCME_USAGE_ERROR;
+		}
+		words[i] = val;
+	}
+
+	/* total output buffer will be an hc sub-category xtlv holding
+	 * an xtvl of 1 or 2 uint32s.
+	 */
+	val_payload_len = (int_count * sizeof(val_xtlv->value[0]));
+	container_payload_len = bcm_xtlv_size_for_data(val_payload_len,
+		BCM_XTLV_OPTION_NONE);
+	out_len = bcm_xtlv_size_for_data(container_payload_len,
+		BCM_XTLV_OPTION_NONE);
+
+	/* init the wrapper hc category XTLV in the IO buffer */
+	hc_tlv = (bcm_xtlv_t*)(&buf[0]);
+	hc_tlv->id = htol16(category);
+	hc_tlv->len = htol16(container_payload_len);
+
+	val_xtlv = (void*)hc_tlv->data;
+	val_xtlv->id = htol16(hc_cmd->id);
+	val_xtlv->len = htol16(val_payload_len);
+	for (i = 0; i < int_count; i++) {
+		val_xtlv->value[i] = htol32(words[i]);
+	}
+
+	ret = wlu_iovar_set(wl, "hc", hc_tlv, out_len);
+
+	return ret;
+}
+
+static int
+wl_hc_getints(void *wl, uint16 category, struct hc_sub_cmd_ent *hc_cmd, int int_count, char **argv)
+{
+	int ret = 0;
+	bcm_xtlv_t *hc_tlv;
+	bcm_xtlv_t *val_xtlv;
+	uint16 hc_len, hc_id;
+	uint16 val_len, val_id;
+	struct {
+		uint16 id;
+		uint16 len;
+		uint16 ids[1];
+	} id_list;
+	uint param_len;
+	const bcm_xtlv_opts_t no_pad = BCM_XTLV_OPTION_NONE;
+
+	if (*argv) {
+		printf("hc get: error, extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* total param buffer will be an hc sub-category xtlv holding
+	 * an xtvl ID list of one element.
+	 * no padding since the id_list is the last element.
+	 */
+	param_len = bcm_xtlv_size_for_data(sizeof(id_list), no_pad);
+
+	/* init an XTLV ID list with the desired attribute ID */
+	bcm_xtlv_pack_xtlv((bcm_xtlv_t *)&id_list, WL_HC_XTLV_ID_IDLIST, sizeof(uint16),
+		NULL, no_pad);
+	id_list.ids[0] = htol16(hc_cmd->id);
+
+	/* init the wrapper hc category XTLV in the IO buffer and copy to it */
+	hc_tlv = (bcm_xtlv_t *)&buf[0];
+	bcm_xtlv_pack_xtlv(hc_tlv, category, sizeof(id_list), (const uint8 *)&id_list, no_pad);
+
+	/* issue the 'hc' get with the one-item id list */
+	if ((ret = wlu_iovar_getbuf(wl, "hc", buf, param_len, buf, WLC_IOCTL_SMLEN)))
+		return ret;
+
+	hc_len = ltoh16(hc_tlv->len);
+	hc_id = ltoh16(hc_tlv->id);
+
+	/* make sure the return xtlv is valid for the iobuffer */
+	if (!bcm_valid_xtlv(hc_tlv, WLC_IOCTL_SMLEN, no_pad)) {
+		printf("hc get: return XTLV specifies length %u too long for iobuffer len %u\n",
+		       hc_len, WLC_IOCTL_SMLEN);
+		return BCME_ERROR;
+	}
+
+	/* the return buf should start with the HC xtlv container */
+	if (hc_id != category) {
+		printf("hc get: return category %u did not match %u\n",
+		       hc_id, category);
+		return BCME_ERROR;
+	}
+
+	/* make sure the container has enough room for an XTLV header */
+	if (hc_len < BCM_XTLV_HDR_SIZE) {
+		printf("hc get: return XTLV container specifies length %u too small "
+		       "to hold any values\n",
+		       hc_len);
+		return BCME_ERROR;
+	}
+
+	val_xtlv = (bcm_xtlv_t*)hc_tlv->data;
+	val_len = ltoh16(val_xtlv->len);
+	val_id = ltoh16(val_xtlv->id);
+
+	/* make sure the value xtlv is valid xtlv container */
+	if (!bcm_valid_xtlv(val_xtlv, hc_len, no_pad)) {
+		printf("hc get: return XTLV specifies length %u too long "
+		       "for containing xtlv len %u\n",
+		       val_len, hc_len);
+		return BCME_ERROR;
+	}
+
+	if (val_len == 0) {
+		printf("hc get: return value XTLV (id:%u) empty\n", val_id);
+		return BCME_ERROR;
+	} else if (val_len != int_count * sizeof(int32)) {
+		printf("hc get: WARNING: return value XTLV (id:%u len:%u) was not "
+		       "the expected len %u\n",
+		       val_id, val_len, (uint)(int_count * sizeof(int32)));
+		ret = BCME_ERROR;
+	}
+
+	/* print as words if multiple of word size, otherwise hexdump */
+	if (val_len % sizeof(uint32) == 0) {
+		uint32 *w = (uint32*)val_xtlv->data;
+		int i;
+		for (i = 0; i * sizeof(uint32) < val_len; i++) {
+			wl_printint((int)ltoh32(w[i]));
+		}
+	} else {
+		wl_hexdump((uint8*)val_xtlv->data, val_len);
+	}
+
+	return (ret);
+}
+
+static struct hc_sub_cmd_ent*
+wl_hc_cmd_lookup(hc_sub_cmd_table_t tbl, char* cmd)
+{
+	struct hc_sub_cmd_ent* entry;
+
+	for (entry = tbl; entry->name != NULL; entry++) {
+		if (!strcmp(entry->name, cmd)) {
+			break;
+		}
+	}
+
+	if (entry->name == NULL) {
+		entry = NULL;
+	}
+
+	return entry;
+}
+
+static void
+wl_hc_subcommand_list_dump(void *wl, const char *category, hc_sub_cmd_table_t tbl)
+{
+	struct hc_sub_cmd_ent* entry;
+
+	BCM_REFERENCE(wl);
+
+	printf("Sub-Commands for \"%s\":\n", category);
+
+	for (entry = tbl; entry->name != NULL; entry++) {
+		printf("  %s %s\n", category, entry->name);
+	}
+}
+
+static int
+wl_idauth(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	char *sub_cmd_name;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* Skip the command name */
+	argv++;
+
+	sub_cmd_name = *argv++;
+
+	if (sub_cmd_name == NULL) {
+		/* usage */
+		printf("idauth: missing category\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!strcmp(sub_cmd_name, "config")) {
+		char* attr_name;
+
+		attr_name = *argv;
+
+		if (attr_name == NULL) {
+			/* GET IDAUTH CONFIG */
+			ret = wl_idauth_config_get(wl, WL_IDAUTH_CMD_CONFIG, argv);
+		}
+		else {
+			/* SET AUTH Config */
+			ret = wl_idauth_config_set(wl, WL_IDAUTH_CMD_CONFIG, argv);
+		}
+	} else if (!strcmp(sub_cmd_name, "peer_info")) {
+		if (*argv == NULL) {
+			ret = wl_idauth_dump_peer_info(wl, WL_IDAUTH_CMD_PEER_INFO, argv);
+		} else {
+			printf("auth peer_info get: error, extra arg \"%s\"\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+	} else if (!strcmp(sub_cmd_name, "counters")) {
+		if (*argv == NULL) {
+			ret = wl_idauth_dump_counters(wl, WL_IDAUTH_CMD_COUNTERS, argv);
+		} else {
+			printf("auth counters get: error, extra arg \"%s\"\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+	} else {
+		/* usage */
+		printf("unknown idauth sub-commands \"%s\"\n", sub_cmd_name);
+		return BCME_USAGE_ERROR;
+	}
+	return ret;
+}
+static int
+wl_idauth_config_set(void *wl, uint16 category, char **argv)
+{
+	char *valstr;
+	char *endptr = NULL;
+	bcm_xtlv_t *auth_tlv;
+	bcm_xtlv_t *val_tlv_ptr;
+	uint out_len;
+	uint32 temp;
+	uint16 count;
+	uint16 container_payload_len = 0;
+	int ret = 0;
+
+	char *p;
+	/* total output buffer will be an hc sub-category xtlv holding
+	 * an xtvl of 1 or 2 uint32s.
+	 */
+	auth_tlv = (bcm_xtlv_t*)(&buf[0]);
+	auth_tlv->id = htol16(category);
+	val_tlv_ptr = (bcm_xtlv_t *)auth_tlv->data;
+	while (*argv) {
+		p = *argv++;
+		switch (p[1]) {
+			case 'a':
+				valstr = *argv++;
+				if (!valstr || valstr[0] == '\0') {
+					printf("idauth config set: missing value for set of %d\n",
+						WL_IDAUTH_XTLV_AUTH_ENAB);
+					return BCME_USAGE_ERROR;
+				}
+				val_tlv_ptr->data[0] = (uint8)strtoul(valstr, &endptr, 0);
+				val_tlv_ptr->id = htol16(WL_IDAUTH_XTLV_AUTH_ENAB);
+				val_tlv_ptr->len = htol16(sizeof(uint8));
+				container_payload_len += bcm_xtlv_size_for_data(sizeof(uint8),
+					BCM_XTLV_OPTION_NONE);
+				break;
+			case 'b':
+				valstr = *argv++;
+				if (!valstr || valstr[0] == '\0') {
+					printf("idauth config set: missing value for set of %d\n",
+						WL_IDAUTH_XTLV_BLKLIST_AGE);
+					return BCME_USAGE_ERROR;
+				}
+				temp = htol32(strtoul(valstr, &endptr, 0));
+				memcpy(&val_tlv_ptr->data[0], &temp, sizeof(uint32));
+				val_tlv_ptr->id = htol16(WL_IDAUTH_XTLV_BLKLIST_AGE);
+				val_tlv_ptr->len = htol16(sizeof(uint32));
+				container_payload_len += bcm_xtlv_size_for_data(sizeof(uint32),
+					BCM_XTLV_OPTION_NONE);
+				break;
+			case 'c':
+				valstr = *argv++;
+				if (!valstr || valstr[0] == '\0') {
+					printf("idauth config set: missing value for set of %d\n",
+						WL_IDAUTH_XTLV_EAPOL_COUNT);
+					return BCME_USAGE_ERROR;
+				}
+				count = htol16(strtoul(valstr, &endptr, 0));
+				memcpy(&val_tlv_ptr->data[0], &count, sizeof(uint16));
+				val_tlv_ptr->id = htol16(WL_IDAUTH_XTLV_EAPOL_COUNT);
+				val_tlv_ptr->len = htol16(sizeof(uint16));
+				container_payload_len += bcm_xtlv_size_for_data(sizeof(uint16),
+					BCM_XTLV_OPTION_NONE);
+				break;
+			case 'e':
+				valstr = *argv++;
+				if (!valstr || valstr[0] == '\0') {
+					printf("idauth config set: missing value for set of %d\n",
+						WL_IDAUTH_XTLV_EAPOL_INTRVL);
+					return BCME_USAGE_ERROR;
+				}
+				temp = htol32(strtoul(valstr, &endptr, 0));
+				memcpy(&val_tlv_ptr->data[0], &temp, sizeof(uint32));
+				val_tlv_ptr->id = htol16(WL_IDAUTH_XTLV_EAPOL_INTRVL);
+				val_tlv_ptr->len = htol16(sizeof(uint32));
+				container_payload_len += bcm_xtlv_size_for_data(sizeof(uint32),
+					BCM_XTLV_OPTION_NONE);
+				break;
+			case 'g':
+				valstr = *argv++;
+				if (!valstr || valstr[0] == '\0') {
+					printf("idauth config set: missing value for set of %d\n",
+						WL_IDAUTH_XTLV_GTK_ROTATION);
+					return BCME_USAGE_ERROR;
+				}
+				temp = htol32(strtoul(valstr, &endptr, 0));
+				memcpy(&val_tlv_ptr->data[0], &temp, sizeof(uint32));
+				val_tlv_ptr->id = htol16(WL_IDAUTH_XTLV_GTK_ROTATION);
+				val_tlv_ptr->len = htol16(sizeof(uint32));
+				container_payload_len += bcm_xtlv_size_for_data(sizeof(uint32),
+					BCM_XTLV_OPTION_NONE);
+				break;
+			case 'm':
+				valstr = *argv++;
+				if (!valstr || valstr[0] == '\0') {
+					printf("idauth config set: missing value for set of %d\n",
+						WL_IDAUTH_XTLV_BLKLIST_COUNT);
+					return BCME_USAGE_ERROR;
+				}
+				count = htol16(strtoul(valstr, &endptr, 0));
+				memcpy(&val_tlv_ptr->data[0], &count, sizeof(uint16));
+				val_tlv_ptr->id = htol16(WL_IDAUTH_XTLV_BLKLIST_COUNT);
+				val_tlv_ptr->len = htol16(sizeof(uint16));
+				container_payload_len += bcm_xtlv_size_for_data(sizeof(uint16),
+					BCM_XTLV_OPTION_NONE);
+				break;
+			default:
+				break;
+		}
+		val_tlv_ptr = (bcm_xtlv_t *)(&auth_tlv->data[container_payload_len]);
+	}
+	auth_tlv->len = htol16(container_payload_len);
+	out_len = bcm_xtlv_size_for_data(container_payload_len,
+		BCM_XTLV_OPTION_NONE);
+	ret = wlu_iovar_set(wl, "idauth", auth_tlv, out_len);
+	return ret;
+}
+static int
+wl_idauth_config_get(void *wl, uint16 category, char **argv)
+{
+	int ret = 0;
+	bcm_xtlv_t *auth_tlv;
+	bcm_xtlv_t *val_xtlv;
+	uint16 hc_len, hc_id;
+	uint16 val_len, val_id;
+	void *val_tlv_ptr;
+	uint16 len_of_tlvs;
+	const bcm_xtlv_opts_t no_pad = BCM_XTLV_OPTION_NONE;
+
+	if (*argv) {
+		printf("idauth config get: error, extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* init the wrapper hc category XTLV in the IO buffer and copy to it */
+	auth_tlv = (bcm_xtlv_t *)&buf[0];
+	auth_tlv->id = htol16(category);
+	auth_tlv->len = 0;
+	bcm_xtlv_pack_xtlv(auth_tlv, category, 0, 0, no_pad);
+
+	/* issue the 'hc' get with the one-item id list */
+	if ((ret = wlu_iovar_getbuf(wl, "idauth", buf, BCM_XTLV_HDR_SIZE, buf, WLC_IOCTL_SMLEN)))
+		return ret;
+
+	hc_len = ltoh16(auth_tlv->len);
+	hc_id = ltoh16(auth_tlv->id);
+
+	/* make sure the return xtlv is valid for the iobuffer */
+	if (!bcm_valid_xtlv(auth_tlv, WLC_IOCTL_SMLEN, no_pad)) {
+		printf("idauth config get:XTLV specifies length %u too long for iobuffer len %u\n",
+		       hc_len, WLC_IOCTL_SMLEN);
+		return BCME_ERROR;
+	}
+
+	/* the return buf should start with the HC xtlv container */
+	if (hc_id != category) {
+		printf("idauth config get: return category %u did not match %u\n",
+		       hc_id, category);
+		return BCME_ERROR;
+	}
+
+	/* make sure the container has enough room for an XTLV header */
+	if (hc_len < BCM_XTLV_HDR_SIZE) {
+		printf("idauth config get: return XTLV container specifies length %u too small"
+		       "to hold any values\n",
+		       hc_len);
+		return BCME_ERROR;
+	}
+	val_xtlv = (bcm_xtlv_t*)auth_tlv->data;
+	val_len = ltoh16(val_xtlv->len);
+	val_id = ltoh16(val_xtlv->id);
+
+	/* make sure the value xtlv is valid xtlv container */
+	if (!bcm_valid_xtlv(val_xtlv, hc_len, no_pad)) {
+		printf("idauth config get: return XTLV specifies length %u too long "
+		       "for containing xtlv len %u\n",
+		       val_len, hc_len);
+		return BCME_ERROR;
+	}
+
+	if (val_len == 0) {
+		printf("idauth config get: return value XTLV (id:%u) empty\n", val_id);
+		return BCME_ERROR;
+	}
+
+	/* print as words if multiple of word size, otherwise hexdump */
+	val_tlv_ptr = auth_tlv->data;
+	len_of_tlvs = auth_tlv->len;
+	while (len_of_tlvs && len_of_tlvs > BCM_XTLV_HDR_SIZE) {
+		val_xtlv = (bcm_xtlv_t *)val_tlv_ptr;
+		switch (val_xtlv->id) {
+			case WL_IDAUTH_XTLV_AUTH_ENAB:
+				printf("%s:%d\n", "auth_enab", *((uint8*)val_xtlv->data));
+				len_of_tlvs -= BCM_XTLV_HDR_SIZE +sizeof(uint8);
+				break;
+			case WL_IDAUTH_XTLV_GTK_ROTATION:
+				printf("%s:%d\n", "gtk_rot_interval", *((uint32*)val_xtlv->data));
+				len_of_tlvs -= BCM_XTLV_HDR_SIZE + sizeof(uint32);
+				break;
+			case WL_IDAUTH_XTLV_EAPOL_COUNT:
+				printf("%s:%d\n", "eapol_count", *((uint16*)val_xtlv->data));
+				len_of_tlvs -= BCM_XTLV_HDR_SIZE + sizeof(uint16);
+				break;
+			case WL_IDAUTH_XTLV_EAPOL_INTRVL:
+				printf("%s:%d\n", "eapol_interval", *((uint32*)val_xtlv->data));
+				len_of_tlvs -= BCM_XTLV_HDR_SIZE + sizeof(uint32);
+				break;
+			case WL_IDAUTH_XTLV_BLKLIST_COUNT:
+				printf("%s:%d\n", "mic_fail_cnt_blacklist",
+					*((uint16*)val_xtlv->data));
+				len_of_tlvs -= BCM_XTLV_HDR_SIZE + sizeof(uint16);
+				break;
+			case WL_IDAUTH_XTLV_BLKLIST_AGE:
+				printf("%s:%d\n", "blacklist_age", *((uint32*)val_xtlv->data));
+				len_of_tlvs -= BCM_XTLV_HDR_SIZE + sizeof(uint32);
+				break;
+		}
+		val_tlv_ptr = (uint8 *)val_tlv_ptr + bcm_xtlv_size((bcm_xtlv_t *)val_tlv_ptr,
+			BCM_XTLV_OPTION_NONE);
+	}
+	return (ret);
+}
+static int
+wl_idauth_dump_counters(void *wl, uint16 category, char **argv)
+{
+	int ret = 0;
+	bcm_xtlv_t *auth_tlv;
+	bcm_xtlv_t *val_xtlv;
+	uint16 hc_len, hc_id;
+	uint16 val_len, val_id;
+	uint32 *w;
+	const bcm_xtlv_opts_t no_pad = BCM_XTLV_OPTION_NONE;
+
+	if (*argv) {
+		printf("idauth counters get: error, extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* init the wrapper hc category XTLV in the IO buffer and copy to it */
+	auth_tlv = (bcm_xtlv_t *)&buf[0];
+	auth_tlv->id = htol16(category);
+	auth_tlv->len = 0;
+	bcm_xtlv_pack_xtlv(auth_tlv, category, 0, 0, no_pad);
+
+	/* issue the 'hc' get with the one-item id list */
+	if ((ret = wlu_iovar_getbuf(wl, "idauth", buf, BCM_XTLV_HDR_SIZE, buf, WLC_IOCTL_SMLEN)))
+		return ret;
+
+	hc_len = ltoh16(auth_tlv->len);
+	hc_id = ltoh16(auth_tlv->id);
+
+	/* make sure the return xtlv is valid for the iobuffer */
+	if (!bcm_valid_xtlv(auth_tlv, WLC_IOCTL_SMLEN, no_pad)) {
+		printf("idauth counter get:XTLV specifies length %u too long for iobuffer len %u\n",
+		       hc_len, WLC_IOCTL_SMLEN);
+		return BCME_ERROR;
+	}
+
+	/* the return buf should start with the HC xtlv container */
+	if (hc_id != category) {
+		printf("idauth counter get: return category %u did not match %u\n",
+		       hc_id, category);
+		return BCME_ERROR;
+	}
+
+	/* make sure the container has enough room for an XTLV header */
+	if (hc_len < BCM_XTLV_HDR_SIZE) {
+		printf("idauth counter get: return XTLV container specifies length %u too small"
+		       "to hold any values\n",
+		       hc_len);
+		return BCME_ERROR;
+	}
+	val_xtlv = (bcm_xtlv_t*)auth_tlv->data;
+	val_len = ltoh16(val_xtlv->len);
+	val_id = ltoh16(val_xtlv->id);
+
+	/* make sure the value xtlv is valid xtlv container */
+	if (!bcm_valid_xtlv(val_xtlv, hc_len, no_pad)) {
+		printf("idauth counter: return XTLV specifies length %u too long "
+		       "for containing xtlv len %u\n",
+		       val_len, hc_len);
+		return BCME_ERROR;
+	}
+
+	if (val_len == 0) {
+		printf("idauth counter get: return value XTLV (id:%u) empty\n", val_id);
+		return BCME_ERROR;
+	}
+
+	/* print as words if multiple of word size, otherwise hexdump */
+	w = (uint32*)val_xtlv->data;
+	if (val_xtlv->len < sizeof(wl_idauth_counters_t))
+		printf("Auth counter length lesser than expected\n");
+	else
+		printf("%s %d\t %s %d\t%s %d\n", "authreq", w[0],
+			"micfail", w[1], "4wayhsfail", w[2]);
+	return (ret);
+}
+
+static int
+wl_idauth_dump_peer_info(void *wl, uint16 category, char **argv)
+{
+	int ret = 0;
+	bcm_xtlv_t *auth_tlv;
+	bcm_xtlv_t *val_xtlv;
+	uint16 hc_len, hc_id;
+	uint16 val_len, val_id;
+	auth_peer_t *w;
+	int idx;
+	const bcm_xtlv_opts_t no_pad = BCM_XTLV_OPTION_NONE;
+
+	if (*argv) {
+		printf("idauth peer_info: error, extra arg \"%s\"\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* init the wrapper hc category XTLV in the IO buffer and copy to it */
+	auth_tlv = (bcm_xtlv_t *)&buf[0];
+	auth_tlv->id = htol16(category);
+	auth_tlv->len = 0;
+	bcm_xtlv_pack_xtlv(auth_tlv, category, 0, 0, no_pad);
+
+	/* issue the 'hc' get with the one-item id list */
+	if ((ret = wlu_iovar_getbuf(wl, "idauth", buf, BCM_XTLV_HDR_SIZE, buf, WLC_IOCTL_SMLEN)))
+		return ret;
+
+	hc_len = ltoh16(auth_tlv->len);
+	hc_id = ltoh16(auth_tlv->id);
+	/* make sure the return xtlv is valid for the iobuffer */
+	if (!bcm_valid_xtlv(auth_tlv, WLC_IOCTL_SMLEN, no_pad)) {
+		printf("idauth peer_info:XTLV specifies length %u too long for iobuffer len %u\n",
+		       hc_len, WLC_IOCTL_SMLEN);
+		return BCME_ERROR;
+	}
+
+	/* the return buf should start with the HC xtlv container */
+	if (hc_id != category) {
+		printf("idauth peer_info: return category %u did not match %u\n",
+		       hc_id, category);
+		return BCME_ERROR;
+	}
+
+	/* make sure the container has enough room for an XTLV header */
+	if (hc_len < BCM_XTLV_HDR_SIZE) {
+		if (hc_len == 0) {
+			printf("idauth peer_info: No peer present\n");
+			return ret;
+		} else {
+			printf("idauth peer_info: return XTLV container specifies"
+				"length %u too small"
+				"to hold any values\n",
+				hc_len);
+			return BCME_ERROR;
+		}
+	}
+	val_xtlv = (bcm_xtlv_t*)auth_tlv->data;
+	val_len = ltoh16(val_xtlv->len);
+	val_id = ltoh16(val_xtlv->id);
+
+	/* make sure the value xtlv is valid xtlv container */
+	if (!bcm_valid_xtlv(val_xtlv, hc_len, no_pad)) {
+		printf("idauth peer_info: return XTLV specifies length %u too long "
+		       "for containing xtlv len %u\n",
+		       val_len, hc_len);
+		return BCME_ERROR;
+	}
+
+	if (val_len == 0) {
+		printf("idauth peer_info: return value XTLV (id:%u) empty\n", val_id);
+		return BCME_OK;
+	}
+
+	/* print as words if multiple of word size, otherwise hexdump */
+	w = (auth_peer_t*)val_xtlv->data;
+	for (idx = 0; idx * sizeof(auth_peer_t) < val_xtlv->len; idx++) {
+		switch (w[idx].state) {
+			case WL_AUTH_PEER_STATE_AUTHORISED:
+				printf("STA %s\tState:%s\tBlacklist Age:%d\n",
+					wl_ether_etoa(&w[idx].peer_addr), "AUTHORIZED", 0);
+				break;
+			case WL_AUTH_PEER_STATE_BLACKLISTED:
+				printf("STA %s\tState:%s\tBlacklist Age:%d\n",
+					wl_ether_etoa(&w[idx].peer_addr), "BLACKLISTED",
+					w[idx].blklist_end_time);
+				break;
+			case WL_AUTH_PEER_STATE_4WAY_HS_ONGOING:
+				printf("STA %s\tState:%s\tBlacklist Age:%d\n",
+					wl_ether_etoa(&w[idx].peer_addr), "4WAY_HS_ONGOING", 0);
+				break;
+			default:
+				printf("idauth peer info: unknown state\n");
+		}
+	}
+	return (ret);
+}
+
+static int
+fsize(void *fp)
+{
+	long size = BCME_ERROR;
+	long cur_offset  = BCME_ERROR;
+
+	if ((cur_offset = ftell(fp)) < 0) {
+		fprintf(stderr, "Could not determine current file offset : %s\n", strerror(errno));
+		return BCME_ERROR;
+	}
+
+	if (!fseek(fp, 0, SEEK_END)) {
+	    if ((size = ftell(fp)) < 0)
+			fprintf(stderr, "Could not determine file size : %s\n", strerror(errno));
+
+		fseek(fp, cur_offset, SEEK_SET);
+	}
+	else
+		fprintf(stderr, "Error in performing fseek: %s\n", strerror(errno));
+
+	return (int)size;
+}
+
+static int
+wl_wake_timer(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wake_timer_t *w_timer;
+	char *endptr;
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	if (*++(argv) == NULL) {
+		buf[buflen] = '\0';
+		err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_SMLEN);
+		if (err < 0)
+			return err;
+		w_timer = (wake_timer_t *)buf;
+		if (dtoh16(w_timer->ver) != WAKE_TIMER_VERSION) {
+			err = BCME_VERSION;
+			return err;
+		}
+		printf("Status:%s\n", dtoh16(w_timer->limit) ? "ENABLED": "DISABLED");
+		printf("Num of events delivered:%d\n", dtoh16(w_timer->count));
+		return 0;
+	} else {
+		w_timer =  (wake_timer_t *) (buf + buflen);
+		buflen += sizeof(wake_timer_t);
+
+		w_timer->period = htod16(strtoul(*argv, &endptr, 0));
+
+		if (*endptr != '\0') {
+			fprintf(stderr, "Type '%s' not a number?\n", *argv);
+			return BCME_ERROR;
+		}
+		if (*++(argv) == NULL) {
+			printf("Missing arg <limit>\n");
+			goto usage;
+		}
+		w_timer->limit = htod16(strtoul(*argv, &endptr, 0));
+		if (*endptr != '\0') {
+			fprintf(stderr, "Type '%s' not a number?\n", *argv);
+			return BCME_ERROR;
+		}
+		if (*++(argv)) {
+			printf("extra arguments\n");
+			goto usage;
+		}
+		w_timer->ver = htod16(WAKE_TIMER_VERSION);
+		w_timer->len = htod16(sizeof(wake_timer_t));
+		err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+		return err;
+	}
+usage:
+		printf("Usage: wl wake_timer <period> <limit>\n");
+	return 0;
+}
+
+static int
+wl_utrace_capture(void *wl, cmd_t *cmd, char **argv)
+{
+	void *buff = NULL;
+	uint16 *ptr = NULL;
+	uint j;
+	FILE *fptr = NULL;
+	uint32 capture_args_size = 0;
+	uchar rev_2 = FALSE;
+	int err = BCME_ERROR;
+	uint32 flag = WLC_UTRACE_MORE_DATA;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	/* Use _v1 version of structure for DINGO and other legacy chips and _v2 for newer chips. */
+	if (wlc_ver_major(wl) <= 5) {
+		/* Handle Legacy chips and chips from DINGO2 */
+		capture_args_size = sizeof(wl_utrace_capture_args_v1_t);
+		rev_2 = FALSE;
+	} else {
+		capture_args_size = sizeof(wl_utrace_capture_args_v2_t);
+		rev_2 = TRUE;
+	}
+
+	fptr = fopen("utrace.txt", "w");
+	if (fptr == NULL) {
+		return BCME_NORESOURCE;
+	}
+	buff = malloc(WLC_UTRACE_LEN + capture_args_size);
+	if (buff == NULL) {
+		fclose(fptr);
+		return BCME_NOMEM;
+	}
+	memset(buff, 0, WLC_UTRACE_LEN + capture_args_size);
+
+	do {
+		if ((err = wlu_iovar_getbuf(wl, cmd->name,
+			buff, 0, buff, (WLC_UTRACE_LEN + capture_args_size))) < 0)
+		{
+			goto exit;
+		}
+		if (rev_2 == TRUE) {
+			wl_utrace_capture_args_v2_t *capture_args;
+			capture_args = (wl_utrace_capture_args_v2_t *) buff;
+			flag = capture_args->flag;
+			/* Check the structure rev */
+			if (capture_args->version == UTRACE_CAPTURE_VER_2) {
+				capture_args->length -= capture_args_size;
+				ptr = (uint16 *) ((uchar*)buff + capture_args_size);
+				for (j = 0; j < capture_args->length/sizeof(uint32); j++) {
+					fprintf(fptr, "%04x %04x \n", ptr[j*2 + 1], ptr[j*2]);
+				}
+			} else {
+				err = BCME_VERSION;
+				flag = WLC_UTRACE_READ_END;
+				printf("Error:Version Mismatch App:%d FW:%d\n",
+					UTRACE_CAPTURE_VER_2, capture_args->version);
+				break;
+			}
+		} else {
+			wl_utrace_capture_args_v1_t *capture_args;
+			capture_args = (wl_utrace_capture_args_v1_t *) buff;
+			flag = capture_args->flag;
+			ptr = (uint16 *) ((uchar*)buff + capture_args_size);
+			for (j = 0; j < capture_args->length/sizeof(uint32); j++) {
+				fprintf(fptr, "%04x %04x \n", ptr[j*2 + 1], ptr[j*2]);
+			}
+
+		}
+	} while (flag == WLC_UTRACE_MORE_DATA);
+
+exit:
+	free(buff);
+	fclose(fptr);
+	return err;
+
+}
+
+static int
+wl_wds_ap_ifname(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+
+	UNUSED_PARAMETER(argv);
+
+	memset(buf, 0, WLC_IOCTL_SMLEN);
+
+	/* query for 'wds_ap_ifname' to get ap ifname */
+	ret = wlu_iovar_get(wl, cmd->name, buf, WLC_IOCTL_SMLEN);
+	buf[WLC_IOCTL_SMLEN -1] = '\0';
+
+	/* if the query is successful, continue on and print the result. */
+	if (ret) {
+		return ret;
+	}
+
+	printf("%s\n", buf);
+	return ret;
+}
+static int
+wl_netx_ifconfig(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct ipv4_addr ipa_set;
+	netx_ifconfig_t ifconfig;
+	uint8 *bufptr;
+
+	int i;
+	int argc;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc == 4) {
+		/* Add host addresses, a list of ip, netmask, gateway */
+		bufptr = (uint8*)&ifconfig;
+
+		for (i = 1; i < argc; i++)
+		{
+			if (!wl_atoip(argv[i], &ipa_set))
+				return BCME_USAGE_ERROR;
+			memcpy(bufptr, &ipa_set.addr[0], IPV4_ADDR_LEN);
+			bufptr += IPV4_ADDR_LEN;
+		}
+		return wlu_var_setbuf(wl, cmd->name, &ifconfig, sizeof(ifconfig));
+	}
+	else {
+		void *ptr = NULL;
+		netx_ifconfig_t *if_get;
+		if ((ret = wlu_var_getbuf(wl, cmd->name, &ifconfig, sizeof(ifconfig), &ptr)) < 0)
+			return ret;
+
+		if_get = (netx_ifconfig_t *)ptr;
+		printf("ip: %s ", wl_iptoa((struct ipv4_addr *)&if_get->ipaddr));
+		printf("netmask: %s ", wl_iptoa((struct ipv4_addr *)&if_get->ipaddr_netmask));
+		printf("gw: %s\n", wl_iptoa((struct ipv4_addr *)&if_get->ipaddr_gateway));
+	}
+
+	return 0;
+}
+
+#ifdef TBTT_OFFSET_STAT
+static int
+wl_tbtt_offset_stat(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	tbtt_offset_stat_t *tbtt_offset_stat = NULL;
+
+	UNUSED_PARAMETER(argv);
+
+	/* Get only */
+	if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, (void **)(&tbtt_offset_stat))) < 0)
+		return (ret);
+
+	printf("avg: %d\nmin: %d\nmax: %d\n",
+	       dtoh32(tbtt_offset_stat->tbtt_offset_avg),
+	       dtoh32(tbtt_offset_stat->tbtt_offset_min),
+	       dtoh32(tbtt_offset_stat->tbtt_offset_max));
+
+	return 0;
+}
+#endif /* TBTT_OFFSET_STAT */
diff --git a/wl/src/wl/exe/wlu.h b/wl/src/wl/exe/wlu.h
new file mode 100644
index 0000000..bd4721a
--- /dev/null
+++ b/wl/src/wl/exe/wlu.h
@@ -0,0 +1,371 @@
+/*
+ * Common code for wl command line utility
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied or
+ * duplicated in any form, in whole or in part, without the prior written
+ * permission of Broadcom Corporation.
+ *
+ * $Id: wlu.h 660248 2016-09-19 21:45:03Z $
+ */
+
+#ifndef _wlu_h_
+#define _wlu_h_
+
+#include <proto/bcmipv6.h>
+#include "wlu_cmd.h"
+
+#if defined(__FreeBSD__)
+#define stricmp   strcasecmp
+#define strnicmp  strncasecmp
+#endif
+
+typedef struct {
+	uint value;
+	const char *string;
+} dbg_msg_t;
+
+typedef struct {
+	int8 pwr2p5;
+	int8 pwr5;
+	int8 pwr10;
+	int8 pwr20;
+	int8 pwr40;
+	int8 pwr20in40;
+	int8 pwr80;
+	int8 pwr20in80;
+	int8 pwr40in80;
+	int8 pwr160;
+	int8 pwr20in160;
+	int8 pwr40in160;
+	int8 pwr80in160;
+	int8 pwr8080;
+	int8 pwr8080chan2;
+	int8 pwr20in8080;
+	int8 pwr40in8080;
+	int8 pwr80in8080;
+} txpwr_row_t;
+
+extern const char *wlu_av0;
+extern int g_wlc_idx;
+
+struct escan_bss {
+	struct escan_bss *next;
+	wl_bss_info_t bss[1];
+};
+
+/* parse common option */
+extern int wl_option(char ***pargv, char **pifname, int *phelp);
+extern void wl_cmd_init(void);
+extern void wlu_init(void);
+
+/* print usage */
+extern void wl_cmd_usage(FILE *fid, cmd_t *cmd);
+extern void wl_usage(FILE *fid, cmd_t *port_cmds);
+extern void wl_cmds_usage(FILE *fid, cmd_t *port_cmds);
+
+/* print helpers */
+extern void wl_printlasterror(void *wl);
+extern void wl_printint(int val);
+
+/* pretty print an SSID */
+extern int wl_format_ssid(char* buf, uint8* ssid, int ssid_len);
+
+/* pretty hex print a contiguous buffer */
+extern void wl_hexdump(uchar *buf, uint nbytes);
+
+/* check driver version */
+extern int wl_check(void *wl);
+
+/* returns major version from "wlc_ver" command */
+extern int wlc_ver_major(void * wl);
+
+extern int wlu_bssiovar_setbuf(void* wl, const char *iovar, int bssidx,
+	void *param, int paramlen, void *bufptr, int buflen);
+extern int wlu_var_getbuf(void *wl, const char *iovar,
+	void *param, int param_len, void **bufptr);
+extern int wlu_var_getbuf_sm(void *wl, const char *iovar,
+	void *param, int param_len, void **bufptr);
+extern int wlu_var_getbuf_med(void *wl, const char *iovar,
+	void *param, int param_len, void **bufptr);
+extern int wlu_var_setbuf_sm(void *wl, const char *iovar,
+		void *param, int param_len);
+extern int wl_parse_ssid_list(char* list_str, wlc_ssid_t* ssid, int idx, int max);
+extern void dump_bss_info(wl_bss_info_t *bi);
+extern cmd_func_t wl_void;
+extern cmd_func_t wl_var_void;
+extern cmd_func_t wl_var_setint;
+extern cmd_func_t wl_var_get;
+extern cmd_func_t wl_var_getandprintstr;
+extern cmd_func_t wl_reg;
+extern cmd_func_t wl_phy_rate;
+extern cmd_func_t wl_ssid;
+extern cmd_func_t wl_iov_mac;
+extern cmd_func_t wl_sta_info;
+extern cmd_func_t wl_seq_start;
+extern cmd_func_t wl_seq_stop;
+extern cmd_func_t wl_hostip;
+extern cmd_func_t wl_hostipv6;
+extern cmd_func_t wl_offload_cmpnt;
+extern cmd_func_t wl_mkeep_alive;
+extern cmd_func_t wl_bsscfg_int;
+extern cmd_func_t wlu_srwrite;
+extern cmd_func_t wlu_reg2args;
+extern cmd_func_t wl_macaddr;
+extern cmd_func_t wl_maclist;
+extern cmd_func_t wl_bcm_config;
+
+extern int ARGCNT(char **argv);
+
+/* return global ioctl_version */
+extern int wl_get_ioctl_version(void);
+/* return the address of bufstruct_wlu, global buf */
+extern char *wl_get_buf(void);
+
+extern int wl_cfg_option(char **argv, const char *fn_name, int *bsscfg_idx, int *consumed);
+extern int wl_scan_prep(void *wl, cmd_t *cmd, char **argv,
+	wl_scan_params_t *params, int *params_size);
+extern chanspec_t wl_chspec_to_driver(chanspec_t chanspec);
+extern chanspec_t wl_chspec_from_driver(chanspec_t chanspec);
+extern uint32 wl_chspec32_to_driver(chanspec_t chanspec);
+extern chanspec_t wl_chspec32_from_driver(uint32 chanspec32);
+extern int wl_parse_channel_list(char* list_str, uint16* channel_list, int channel_num);
+/* return TRUE if all the values in the array are uniformly the same */
+extern int wl_array_uniform(uint8 *pwr, int start, int count);
+extern void wl_txpwr_print_header(int8 channel_bandwidth, bool verbose);
+extern void wl_txpwr_print_row(const char *label, uint8 chains, txpwr_row_t powers,
+	int8 unsupported_rate, int8 channel_bandwidth, bool verbose);
+extern int get_ie_data(uchar *data_str, uchar *ie_data, int len);
+extern int get_oui_bytes(uchar *oui_str, uchar *oui);
+
+
+/* Format a ratespec for output of any of the wl_rate() iovars */
+extern char* wl_rate_print(char *rate_buf, uint32 rspec);
+/* convert rate string in Mbit/s format, like "11", "5.5", to internal 500 Kbit/s units */
+extern int rate_string2int(char *s);
+/* convert rate internal 500 Kbits/s units to string in Mbits/s format, like "11", "5.5" */
+extern char* rate_int2string(char *rate_buf, int val);
+extern void wl_print_mcsset(char *mcsset);
+
+extern int wl_parse_chanspec_list(char* list_str, chanspec_t *chanspec_list, int chanspec_num);
+extern int hexstr2hex(char *str);
+extern char* find_pattern(char **argv, const char *pattern, uint *val);
+extern char* find_pattern2(char **argv, const char *pattern, uint *val, int vnum);
+extern int wl_atoipv6(const char *a, struct ipv6_addr *n);
+extern char * wl_ipv6toa(const void *ipv6);
+extern int wlu_reg3args(void *wl, cmd_t *cmd, char **argv);
+extern int parse_wep(char **argv, wl_wsec_key_t *key, bool options);
+
+/* Convert user's input in hex pattern to byte-size mask */
+extern int wl_pattern_atoh(char *src, char *dst);
+
+/* register commands for a module */
+extern void wl_module_cmds_register(cmd_t *cmds);
+
+extern cmd_t *wlu_find_cmd(char *name);
+
+/* wluc_module init functions */
+extern void wluc_phy_module_init(void);
+extern void wluc_wnm_module_init(void);
+extern void wluc_cac_module_init(void);
+extern void wluc_rmc_module_init(void);
+extern void wluc_rrm_module_init(void);
+extern void wluc_wowl_module_init(void);
+extern void wluc_nan_module_init(void);
+extern void wluc_ap_module_init(void);
+extern void wluc_ampdu_module_init(void);
+extern void wluc_ampdu_cmn_module_init(void);
+extern void wluc_bmac_module_init(void);
+extern void wluc_ht_module_init(void);
+extern void wluc_wds_module_init(void);
+extern void wluc_keymgmt_module_init(void);
+extern void wluc_scan_module_init(void);
+extern void wluc_obss_module_init(void);
+extern void wluc_prot_obss_module_init(void);
+extern void wluc_lq_module_init(void);
+extern void wluc_seq_cmds_module_init(void);
+extern void wluc_btcx_module_init(void);
+extern void wluc_led_module_init(void);
+extern void wluc_interfere_module_init(void);
+extern void wluc_ltecx_module_init(void);
+extern void wluc_extlog_module_init(void);
+extern void wluc_pkt_filter_module_init(void);
+extern void wluc_mfp_module_init(void);
+extern void wluc_ota_module_init(void);
+extern void wluc_bssload_module_init(void);
+extern void wluc_sdio_module_init(void);
+extern void wluc_stf_module_init(void);
+extern void wluc_offloads_module_init(void);
+extern void wluc_tpc_module_init(void);
+extern void wluc_toe_module_init(void);
+extern void wluc_arpoe_module_init(void);
+extern void wluc_ndoe_module_init(void);
+extern void wluc_keep_alive_module_init(void);
+extern void wluc_pfn_module_init(void);
+extern void wluc_tbow_module_init(void);
+extern void wluc_p2p_module_init(void);
+extern void wluc_tdls_module_init(void);
+extern void wluc_trf_mgmt_module_init(void);
+extern void wluc_proxd_module_init(void);
+extern void wluc_p2po_module_init(void);
+extern void wluc_anqpo_module_init(void);
+extern void wluc_btcdyn_module_init(void);
+extern void wluc_mesh_module_init(void);
+extern void wluc_msch_module_init(void);
+extern void wluc_bdo_module_init(void);
+extern void wluc_randmac_module_init(void);
+extern void wluc_tko_module_init(void);
+extern void wluc_natoe_module_init(void);
+extern void wluc_rsdb_module_init(void);
+extern void wluc_he_module_init(void);
+extern void wluc_mbo_module_init(void);
+extern void wluc_hoffload_module_init(void);
+
+extern void wluc_ecounters_module_init(void);
+extern int hexstrtobitvec(const char *cp, uchar *bitvec, int veclen);
+
+extern int get_counter_offset(char *name, uint32 *offset, uint8 counter_ver);
+extern int print_counter_help(uint8 counter_ver);
+
+/* wl functions used by the ndis wl. */
+extern void dump_rateset(uint8 *rates, uint count);
+extern uint freq2channel(uint freq);
+extern int wl_ether_atoe(const char *a, struct ether_addr *n);
+extern char *wl_ether_etoa(const struct ether_addr *n);
+struct ipv4_addr;	/* forward declaration */
+extern int wl_atoip(const char *a, struct ipv4_addr *n);
+extern char *wl_iptoa(const struct ipv4_addr *n);
+extern cmd_func_t wl_int;
+extern cmd_func_t wl_varint;
+extern void wl_dump_raw_ie(bcm_tlv_t *ie, uint len);
+extern int wl_mk_ie_setbuf(const char *command, uint32 pktflag_ok, char **argv,
+	vndr_ie_setbuf_t **buf, int *buf_len);
+extern cmd_func_t wl_list_ie;
+
+extern void wl_printlasterror(void *wl);
+extern bool wc_cmd_check(const char *cmd);
+
+#if defined(WL_NAN)
+extern int wl_nan_do_get_ioctl(void *wl, void *nanioc, uint16 iocsz);
+#endif
+
+#define WL_IOV_BATCH_DELIMITER		"+"
+
+
+/* functions for downloading firmware to a device via serial or other transport */
+#ifdef SERDOWNLOAD
+extern int dhd_init(void *dhd, cmd_t *cmd, char **argv);
+extern int dhd_download(void *dhd, cmd_t *cmd, char **argv);
+extern int rwl_download(void *dhd, cmd_t *cmd, char **argv);
+#endif /* SERDOWNLOAD */
+
+#ifdef BCMDLL
+#ifdef LOCAL
+extern FILE *dll_fd;
+#else
+extern void * dll_fd_out;
+extern void * dll_fd_in;
+#endif
+#undef printf
+#undef fprintf
+#define printf printf_to_fprintf	/* printf to stdout */
+#define fprintf fprintf_to_fprintf	/* fprintf to stderr */
+extern void fprintf_to_fprintf(FILE * stderror, const char *fmt, ...);
+extern void printf_to_fprintf(const char *fmt, ...);
+extern void raw_puts(const char *buf, void *dll_fd_out);
+#define	fputs(buf, stdout) raw_puts(buf, dll_fd_out)
+#endif /* BCMDLL */
+
+#define	PRNL()		pbuf += sprintf(pbuf, "\n")
+
+#define RAM_SIZE_4325  0x60000
+#define RAM_SIZE_4329  0x48000
+#define RAM_SIZE_43291 0x60000
+#define RAM_SIZE_4330_a1  0x3c000
+#define RAM_SIZE_4330_b0  0x48000
+
+#define SROM_PAVAR		21
+
+/* useful macros */
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a)  (sizeof(a)/sizeof(a[0]))
+#endif /* ARRAYSIZE */
+
+/* buffer length needed for wl_format_ssid
+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL
+ */
+#ifndef SSID_FMT_BUF_LEN
+#define SSID_FMT_BUF_LEN (4*32+1)	/* Length for SSID format string */
+#endif
+
+/* some OSes (FC4) have trouble allocating (kmalloc) 128KB worth of memory,
+ * hence keeping WL_DUMP_BUF_LEN below that
+ */
+#if !defined(WL_DUMP_BUF_LEN)
+#if defined(BWL_SMALL_WLU_DUMP_BUF)
+#define WL_DUMP_BUF_LEN (4 * 1024)
+#else
+#define WL_DUMP_BUF_LEN (127 * 1024)
+#endif 
+#endif /* WL_DUMP_BUF_LEN */
+
+#ifdef linux
+#define ESCAN_EVENTS_BUFFER_SIZE 2048
+#endif /* linux */
+
+#define CMDLINESZ		80
+#define USAGE_ERROR  -1		/* Error code for Usage */
+#define CMD_DEPRECATED -4 /* Commands that are functionally deprecated or don't provide
+			   * a useful value to a specific OS port of wl
+			   */
+
+/* integer output format */
+#define INT_FMT_DEC	0	/* signed integer */
+#define INT_FMT_UINT	1	/* unsigned integer */
+#define INT_FMT_HEX	2	/* hexdecimal */
+
+#define DIV_QUO(num, div) ((num)/div)  /* Return the quotient of division to avoid floats */
+#define DIV_REM(num, div) (((num%div) * 100)/div) /* Return the remainder of division */
+
+/* command line argument usage */
+#define CMD_ERR	-1	/* Error for command */
+#define CMD_OPT	0	/* a command line option */
+#define CMD_WL	1	/* the start of a wl command */
+
+#define LED_MAX_INDEX	16	/* index limitation for cmd ledbh */
+
+#define SCAN_USAGE	"" \
+"\tDefault to an active scan across all channels for any SSID.\n" \
+"\tOptional arg: SSIDs, list of [up to 10] SSIDs to scan (comma or space separated).\n" \
+"\tOptions:\n" \
+"\t-s S, --ssid=S\t\tSSIDs to scan\n" \
+"\t-t ST, --scan_type=ST\t[active|passive|prohibit|offchan|hotspot] scan type\n" \
+"\t--bss_type=BT\t\t[bss/infra|ibss/adhoc] bss type to scan\n" \
+"\t-b MAC, --bssid=MAC\tparticular BSSID MAC address to scan, xx:xx:xx:xx:xx:xx\n" \
+"\t-n N, --nprobes=N\tnumber of probes per scanned channel\n" \
+"\t-a N, --active=N\tdwell time per channel for active scanning\n" \
+"\t-p N, --passive=N\tdwell time per channel for passive scanning\n" \
+"\t-h N, --home=N\t\tdwell time for the home channel between channel scans\n" \
+"\t-c L, --chanspecs=L\tcomma or space separated list of chanspecs to scan" \
+
+#define WL_EVENT_TIMEOUT 10 /* Timeout in second for event from driver */
+#define MAX_SUBCOUNTER_SUPPORTED	64 /* Max subcounters supported. */
+
+#define DINGO_FW_REV 0x9000000
+
+int wl_wait_for_event(void *wl, char **argv, uint event_id, uint evbuf_size,
+	void (*event_cb_fn)(int event_type, bcm_event_t *bcm_event));
+
+#endif /* _wlu_h_ */
diff --git a/wl/src/wl/exe/wlu_avail_utils.c b/wl/src/wl/exe/wlu_avail_utils.c
new file mode 100644
index 0000000..a8d961c
--- /dev/null
+++ b/wl/src/wl/exe/wlu_avail_utils.c
@@ -0,0 +1,249 @@
+/*
+ * Availability support functions
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_avail_utils.c abhik$
+ */
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <bcmendian.h>
+#include <wlioctl.h>
+#if defined(__FreeBSD__)
+#include <machine/stdarg.h>
+#include <stdbool.h>
+#else
+#include <stdarg.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <bcmutils.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define stricmp strcmp
+#define strnicmp strncmp
+
+static bool
+wl_get_tmu_from_str(char *str, wl_tmu_t *p_tmu)
+{
+	if (stricmp(str, "tu") == 0)
+		*p_tmu = WL_TMU_TU;
+	else if (stricmp(str, "s") == 0)
+		*p_tmu = WL_TMU_SEC;
+	else if (stricmp(str, "ms") == 0)
+		*p_tmu = WL_TMU_MILLI_SEC;
+	else if (stricmp(str, "us") == 0)
+		*p_tmu = WL_TMU_MICRO_SEC;
+	else if (stricmp(str, "ns") == 0)
+		*p_tmu = WL_TMU_NANO_SEC;
+	else if (stricmp(str, "ps") == 0)
+		*p_tmu = WL_TMU_PICO_SEC;
+	else
+		return FALSE;
+
+	return TRUE;
+}
+
+/*
+* parse and pack 'chanspec' from a command-line argument
+* Input:
+*  arg_channel: a channel-string
+*  out_channel: buffer to store the result
+*/
+static int
+wl_parse_channel(char *arg_channel, uint32 *out_channel)
+{
+	int   status = BCME_OK;
+	uint32 src_data_channel = 0;  /* default: invalid */
+
+	/* note, chanespec_t is currently defined as 16-bit, however */
+	/* wl-interface use 'uint32' to allow future change for 32-bit */
+	if (arg_channel != (char *) NULL)
+		src_data_channel = (uint32) wf_chspec_aton(arg_channel);
+
+	if (src_data_channel == 0) {
+		printf("error: invalid chanspec\n");
+		status = BCME_BADARG;
+	}
+
+	*out_channel = htol32(src_data_channel);
+	return status;
+}
+
+/*
+* parse and pack 'intvl' param-value from a command-line argument
+* Input:
+*  arg_intvl: a time-intvl string
+*  out_intvl: buffer to store the result
+*/
+static int
+wl_avail_parse_intvl(char *arg_intvl, wl_time_interval_t *out_intvl)
+{
+	wl_time_interval_t  src_data_intvl;
+	char *p_end;
+
+	/* initialize */
+	memset(out_intvl, 0, sizeof(*out_intvl));
+
+	if (arg_intvl == (char *) NULL) {
+		printf("error: time-interval value is not specified\n");
+		return BCME_BADARG;
+	}
+
+	errno = 0;
+	memset(&src_data_intvl, 0, sizeof(src_data_intvl));
+	/* time interval e.g. 10ns */
+	/* get the number */
+	p_end = NULL;
+	src_data_intvl.intvl = htol32(strtoul(arg_intvl, &p_end, 10));
+	if (errno) {
+		printf("error: invalid time interval (errno=%d)\n", errno);
+		return BCME_BADARG;
+	}
+
+	/* get time-unit */
+	src_data_intvl.tmu = WL_TMU_TU; /* default */
+	if (*p_end != '\0') {
+		if (!wl_get_tmu_from_str(p_end, &src_data_intvl.tmu)) {
+			printf("error: invalid time-unit %s\n", p_end);
+			return BCME_BADARG;
+		}
+	}
+	src_data_intvl.tmu = htol16(src_data_intvl.tmu);
+
+	/* return to caller */
+	memcpy(out_intvl, &src_data_intvl, sizeof(*out_intvl));
+
+	return BCME_OK;
+}
+
+/*
+* parse and pack one 'slot' param-value from a command-line
+* Input:
+*  arg_slot: 'slot' param-value argument string
+*             in "channel:start-tmu:duration-tmu" format
+*  out_avail_slot: buffer to store the result
+*/
+int
+wl_avail_parse_slot(char *arg_slot, wl_avail_slot_t *out_avail_slot)
+{
+	int arg_idx;
+	const char *tmp_start, *tmp_end;
+	char tmpbuf[128];
+	int len;
+	int   status = BCME_OK;
+
+	if (arg_slot == (char *) NULL) {
+		printf("error: slot value is not specified\n");
+		return BCME_BADARG;
+	}
+
+	/* parse channel:start-tmu:duration-tmu */
+	tmp_start = arg_slot;
+	for (arg_idx = 0; arg_idx < 3; arg_idx++) {
+		tmp_end = strchr(tmp_start, ':');
+		if (tmp_end == NULL) {
+			if (arg_idx != 2 || *tmp_start == '\0') {
+				status = BCME_BADARG;
+				goto done;
+			}
+			/* for last 'duration intvl' */
+			tmp_end = tmp_start + strlen(tmp_start);
+		}
+
+		/* create a temp null-terminated substring */
+		if ((len = tmp_end - tmp_start) >= (int) sizeof(tmpbuf)) {
+			status = BCME_BADARG;
+			goto done;
+		}
+
+		memcpy(tmpbuf, tmp_start, len);
+		tmpbuf[len] = '\0';  /* null-terminate */
+
+		if (arg_idx == 0)
+			status = wl_parse_channel(tmpbuf, &out_avail_slot->chanspec);
+		else if (arg_idx == 1)
+			status = wl_avail_parse_intvl(tmpbuf, &out_avail_slot->start);
+		else /* arg_idx == 2 */
+			status = wl_avail_parse_intvl(tmpbuf, &out_avail_slot->duration);
+
+		if (status != BCME_OK)
+			goto done;
+		/* continue on next element */
+		tmp_start = tmp_end + 1;
+
+	}
+done:
+	if (status == BCME_BADARG)
+		printf("error: invalid value for slot\n");
+
+	return status;
+}
+
+/*
+* parse and pack one 'period' param-value from a command-line
+* Input:
+*  arg_slot: 'slot' param-value argument string
+*             in "channel:start-tmu:duration-tmu:period" format
+*  out_avail_slot: buffer to store the result
+*/
+int
+wl_avail_parse_period(char *arg_slot, wl_time_interval_t *out_intvl)
+{
+	int cnt = 0;
+	char *p = arg_slot;
+	int status = BCME_OK;
+	if (p == NULL) {
+		return BCME_BADARG;
+	}
+
+	/* channel:start-tmu:duration-tmu:period */
+	for (; cnt < 3; cnt++) {
+		p = strchr(p, ':');
+		if (!p) {
+			break;
+		}
+		p++;
+	}
+
+	if (p == NULL) {
+		return BCME_BADARG;
+	}
+	status = wl_avail_parse_intvl(p, out_intvl);
+
+	return status;
+}
+
+int
+wl_avail_validate_format(char *arg_slot)
+{
+	/* channel:start-tmu:duration-tmu:period OR
+	 * channel:start-tmu:duration-tmu
+	 */
+	char *p = arg_slot;
+	int cnt = 0;
+
+	while (p != NULL) {
+		p = strchr(p, ':');
+		if (p == NULL)
+			break;
+		p++;
+		cnt++;
+	}
+
+	if (cnt == 2 || cnt == 3) {
+		return BCME_OK;
+	}
+
+	return BCME_BADARG;
+}
diff --git a/wl/src/wl/exe/wlu_avail_utils.h b/wl/src/wl/exe/wlu_avail_utils.h
new file mode 100644
index 0000000..245edfc
--- /dev/null
+++ b/wl/src/wl/exe/wlu_avail_utils.h
@@ -0,0 +1,24 @@
+/*
+ * Availability support functions
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_avail_utils.h abhik$
+ */
+#ifndef __WLU_AVAIL_UTILS_H___
+#define __WLU_AVAIL_UTILS_H__
+int
+wl_avail_parse_slot(char *arg_slot, wl_avail_slot_t *out_avail_slot);
+int
+wl_avail_parse_period(char *arg_slot, wl_time_interval_t *out_intvl);
+int
+wl_avail_validate_format(char *arg_slot);
+#endif /* __WLU_AVAIL_UTILS_H___ */
diff --git a/wl/src/wl/exe/wlu_client_shared.c b/wl/src/wl/exe/wlu_client_shared.c
new file mode 100644
index 0000000..3113713
--- /dev/null
+++ b/wl/src/wl/exe/wlu_client_shared.c
@@ -0,0 +1,1264 @@
+/*
+ * Common code for remotewl client
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_client_shared.c 545578 2015-04-01 04:21:19Z $
+ */
+#ifdef WIN32
+#define NEED_IR_TYPES
+
+#include <winsock2.h>
+#include <windows.h>
+#include <ntddndis.h>
+#include <epictrl.h>
+#include <irelay.h>
+#include <winioctl.h>
+#include <nuiouser.h>
+#else /* LINUX */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <net/if.h>
+#include <unistd.h>
+#endif /* WIN32 */
+#include <stdio.h>
+#include <stdlib.h>
+#if !defined(__FreeBSD__)
+#include <malloc.h>
+#endif 
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <typedefs.h>
+#include <wlioctl.h>
+#include <proto/ethernet.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#include <bcmcdc.h>
+#include <proto/802.11.h>
+#include <signal.h>
+#if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)
+#include <rwl_wifi.h>
+#endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */
+#include "wlu.h"
+#include "wlu_remote.h"
+#include "wlu_pipe.h"
+#include "wlu_client_shared.h"
+
+char* remote_vista_cmds[] = {"join", "sup_wpa", "wsec", "set_pmk", "legacylink", "list",
+	"disassoc", "xlist", NULL};
+int vista_cmd_index;
+#define SHELL_CMD_LEN (256)
+
+#ifdef RWL_SOCKET
+extern int validate_server_address();
+static int rwl_socket_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf);
+#endif
+static int rwl_dongle_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf, int cmd);
+#ifdef RWL_WIFI
+static int rwl_wifi_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf);
+#endif
+#if defined(WIN32) || defined(LINUX)
+/* We don't want the server to allocate bigger buffers for some of the commands
+ * like scanresults. Server can still allocate 8K memory and send the response
+ * in fragments. This is used in case of Get commands only.
+ */
+#define SERVER_RESPONSE_MAX_BUF_LEN 8192
+#endif
+
+extern unsigned short g_rwl_servport;
+extern char *g_rwl_servIP;
+int g_child_pid;
+#ifdef RWL_WIFI
+/* dword align allocation */
+static union {
+	char bufdata[WLC_IOCTL_MAXLEN];
+	uint32 alignme;
+} bufstruct_wlu;
+static char *g_rwl_aligned_buf = (char*) &bufstruct_wlu.bufdata;
+
+extern char *g_rwl_buf_mac;
+#endif
+#ifdef RWL_SOCKET
+/* Make initial connection from client to server through sockets */
+static int
+rwl_connect_socket_server(void)
+{
+	int SockDes = -1;
+	struct sockaddr_in servAddr;
+	memset(&servAddr, 0, sizeof(servAddr));
+	if ((SockDes = (*(int *)rwl_open_pipe(remote_type, "\0", 0, 0))) == FAIL)
+		return FAIL;
+	if (!validate_server_address())
+		return FAIL;
+	DPRINT_DBG(OUTPUT, "ServerIP:%s,ServerPort:%d\n", g_rwl_servIP, g_rwl_servport);
+	servAddr.sin_family = AF_INET;
+	servAddr.sin_port = hton16(g_rwl_servport);
+	servAddr.sin_addr.s_addr = inet_addr(g_rwl_servIP);
+
+	if (rwl_sockconnect(SockDes, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) {
+		rwl_close_pipe(remote_type, (void*) &SockDes);
+		return FAIL;
+	}
+	return SockDes;
+}
+
+/* This routine is used for both Get and Set Ioctls for the socket */
+static int
+rwl_information_socket(void *wl, int cmd, void* input_buf, unsigned long *input_len,
+	unsigned long *tx_len, uint flags)
+{
+	int error, Sockfd;
+	rem_ioctl_t *rem_ptr = NULL;
+
+	if ((Sockfd = rwl_connect_socket_server()) < 0) {
+		DPRINT_ERR(ERR, "Error in getting the Socket Descriptor\n");
+		return FAIL;
+	}
+	wl = (void *)(&Sockfd);
+
+	if (remote_CDC_tx(wl, cmd, input_buf, *input_len,
+		*tx_len, flags, 0) < 0) {
+		DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
+		rwl_close_pipe(remote_type, wl);
+		return FAIL;
+	}
+
+	if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+		DPRINT_ERR(ERR, "query_info_fe: Reading CDC header 	failed\n");
+		rwl_close_pipe(remote_type, wl);
+		return FAIL;
+	}
+	rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
+
+	if (rem_ptr->msg.len > *input_len) {
+		DPRINT_ERR(ERR, "query_info_fe: needed size(%d) > "
+		           "actual size(%ld)\n", rem_ptr->msg.len, *input_len);
+		rwl_close_pipe(remote_type, wl);
+		return FAIL;
+	}
+
+	if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, 0) == FAIL) {
+		DPRINT_ERR(ERR, "query_info_fe: No results!\n");
+		rwl_close_pipe(remote_type, wl);
+		return FAIL;
+	}
+
+	if (rem_ptr->msg.flags & REMOTE_REPLY)
+		error = rem_ptr->msg.cmd;
+	else
+		error = 0;
+
+	rwl_close_pipe(remote_type, wl);
+
+	return error;
+}
+#endif /* RWL_SOCKET */
+/*
+ * Receives the fragmented response from serial server.
+ * Called from rwl_queryinformation_fe front end function for dongle case only when
+ * the client expects data in chunks more than DATA_FRAME_LEN * (960) bytes.
+ */
+static int
+rwl_serial_fragmented_response_fe(void *wl, rem_ioctl_t *rem_ptr, void* input_buf,
+unsigned long *bytes_to_read)
+{
+	int error = 0;
+	uint32 total_numread;
+	uchar *local_buf, *local_result;
+	uint frames_to_read, frame_count;
+
+	DPRINT_DBG(OUTPUT, "rem_ptr->msg.len=%d \t rem_ptr->data_len=%d\n",
+		rem_ptr->msg.len, rem_ptr->data_len);
+
+	/* Calculate the number of frames for the response */
+	if (rem_ptr->data_len == 0) {
+		DPRINT_ERR(ERR, "data_len is:%d\n", rem_ptr->data_len);
+		return (FAIL);
+	}
+	frames_to_read = (*bytes_to_read)/rem_ptr->data_len;
+	if ((*bytes_to_read) % rem_ptr->data_len > 0)
+		frames_to_read += 1;
+
+	DPRINT_DBG(OUTPUT, "No of frames=%d\n", frames_to_read);
+
+	if ((local_result = (uchar*)malloc(rem_ptr->msg.len)) == NULL) {
+		DPRINT_ERR(ERR, "Malloc failed for serial fragmented frame"
+		"local result \n");
+		return FAIL;
+	}
+
+	/* Response will come in DATA_FRAME_LEN + REMOTE_SIZE (960+16) bytes
+	 * packet with CDC header and then followed by response.
+	 */
+	total_numread = 0;
+	frame_count = 0;
+	while (total_numread != *bytes_to_read) {
+		error = FAIL;
+		local_buf = (uchar*)malloc(rem_ptr->data_len);
+		if (local_buf == NULL) {
+			free(local_result);
+			return FAIL;
+		}
+
+		DPRINT_DBG(OUTPUT, "Total bytes=%d\n", total_numread);
+		DPRINT_DBG(OUTPUT, "Frame (Reverse):%d\n", frames_to_read);
+
+		if (remote_CDC_rx(wl, rem_ptr, local_buf, rem_ptr->data_len, 0) == -1) {
+			free(local_buf);
+			free(local_result);
+			return FAIL;
+		}
+
+		/* Concatenate the response to loc_res. */
+		memcpy(&local_result[frame_count*DATA_FRAME_LEN], local_buf,
+			rem_ptr->data_len);
+
+		total_numread += rem_ptr->data_len;
+		frame_count++;
+		frames_to_read--;
+
+		DPRINT_DBG(OUTPUT, "Total bytes=%d\n", total_numread);
+
+		if (frames_to_read == 0) {
+			/* When all the frames are received copy the data to original buf */
+			memcpy(input_buf, local_result, total_numread);
+			if (rem_ptr->msg.flags & REMOTE_REPLY)
+				error = rem_ptr->msg.cmd;
+			else
+				error = 0;
+		}
+
+		if (total_numread != *bytes_to_read) {
+			/* Receive the next header */
+			if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+				DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed");
+			}
+		}
+		free(local_buf);
+	}
+	free(local_result);
+	return error;
+}
+
+/* This routine is common to both set and Get Ioctls for the dongle case */
+static int
+rwl_information_dongle(void *wl, int cmd, void* input_buf, unsigned long *input_len,
+	uint tx_len, uint flags)
+{
+	int error;
+	rem_ioctl_t *rem_ptr = NULL;
+
+	if (remote_CDC_tx(wl, cmd, input_buf, *input_len,
+		tx_len, flags, 0) < 0) {
+		DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
+		return FAIL;
+	}
+
+	/* Get the header */
+	if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+		DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed\n");
+		return BCME_SERIAL_PORT_ERR;
+	}
+
+	/* Make sure there is enough room */
+	if (rem_ptr->msg.len > *input_len) {
+		DPRINT_DBG(OUTPUT, "query_info_fe: needed size(%d) > actual"
+			"size(%ld)\n", rem_ptr->msg.len, *input_len);
+		return FAIL;
+	}
+
+	/*  We can grab short frames all at once.  Longer frames (> 960 bytes)
+	 *  come in fragments.
+	*/
+	if (rem_ptr->data_len < DATA_FRAME_LEN) {
+		if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, 0) == FAIL) {
+			DPRINT_ERR(ERR, "query_info_fe: No results!\n");
+			return FAIL;
+		}
+		if (rem_ptr->msg.flags & REMOTE_REPLY)
+			error = rem_ptr->msg.cmd;
+		else
+			error = 0;
+	} else {
+		/* rwl_serial_fragmented_response_fe returns either valid number or FAIL.
+		  * In any case return the same value to caller
+		*/
+		error = rwl_serial_fragmented_response_fe(wl, rem_ptr, input_buf, input_len);
+	}
+	return error;
+}
+/* Handler to signal the reader thread that ctrl-C is pressed */
+volatile sig_atomic_t g_sig_ctrlc = 1;
+void ctrlc_handler(int num)
+{
+	UNUSED_PARAMETER(num);
+	g_sig_ctrlc = 0;
+}
+
+/* Issue shell commands independent of transport type and return result */
+static int
+rwl_shell_information_fe(void *wl, int cmd, uchar* input_buf, unsigned long *input_len)
+{
+	int error = 0, remote_cmd;
+	uchar* resp_buf = NULL;
+	rem_ioctl_t *rem_ptr = NULL;
+
+#ifdef RWL_WIFI
+	char *cbuf, retry;
+	dot11_action_wifi_vendor_specific_t *list;
+#endif
+
+#ifdef RWL_SOCKET
+	int Sockfd;
+#endif
+
+	remote_cmd = REMOTE_SHELL_CMD;
+
+#ifdef RWLASD
+	if (cmd == ASD_CMD)
+		remote_cmd = REMOTE_ASD_CMD;
+#endif
+	if (cmd == VISTA_CMD)
+		remote_cmd = REMOTE_VISTA_CMD;
+
+	switch (remote_type) {
+		case REMOTE_SOCKET:
+#ifdef RWL_SOCKET
+			if ((Sockfd = rwl_connect_socket_server()) < 0) {
+				DPRINT_ERR(ERR, " Error in getting the SocDes\n");
+				return BCME_ERROR;
+			}
+
+			wl = (void *)(&Sockfd);
+			if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
+				remote_cmd, 0) < 0) {
+				DPRINT_ERR(ERR, "shell_info_fe: Send command failed\n");
+				rwl_close_pipe(remote_type, wl);
+				return BCME_ERROR;
+			}
+			/* For backward compatibility for ASD, async and kill commands do the
+			 * old way
+			 */
+			if (remote_cmd == REMOTE_SHELL_CMD && !strstr((char*)input_buf, "%") &&
+				!strstr((char*)input_buf, "kill"))
+				error = rwl_socket_shellresp(wl, rem_ptr, input_buf);
+			else {
+				if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+					DPRINT_ERR(ERR, "shell_info_fe: Receiving CDC"
+						"header failed\n");
+					rwl_close_pipe(remote_type, wl);
+					return FAIL;
+				}
+
+				if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
+					DPRINT_ERR(ERR, "Mem alloc fails\n");
+					rwl_close_pipe(remote_type, wl);
+					return FAIL;
+				}
+
+				if (remote_CDC_rx(wl, rem_ptr, resp_buf,
+					rem_ptr->msg.len, 0) == FAIL) {
+					DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
+					rwl_close_pipe(remote_type, wl);
+					free(resp_buf);
+					return FAIL;
+				}
+
+				/* print the shell result */
+				resp_buf[rem_ptr->msg.len] = '\0';
+				/* The return value of the shell command
+				 * will be stored in rem_ptr->msg.cmd
+				 * Return that value to the client process
+				 */
+				if (rem_ptr->msg.flags & REMOTE_REPLY)
+					error = rem_ptr->msg.cmd;
+				fputs((char*)resp_buf, stdout);
+			}
+			rwl_close_pipe(remote_type, wl);
+#endif /* RWL_SOCKET */
+			break;
+		case REMOTE_DONGLE:
+		case REMOTE_SERIAL:
+			if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
+			                  remote_cmd, 0) < 0) {
+				DPRINT_ERR(ERR, "shell_info_fe: Send command failed\n");
+				return FAIL;
+			}
+
+			/* For backward compatibility for ASD, async and kill commands do the
+			 * old way
+			 */
+			if (remote_cmd != REMOTE_ASD_CMD && !strstr((char*)input_buf, "%") &&
+				!strstr((char*)input_buf, "kill"))
+				error = rwl_dongle_shellresp(wl, rem_ptr, input_buf, cmd);
+			else {
+				if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+					DPRINT_ERR(ERR, "shell_info_fe:"
+					"Receiving CDC header failed\n");
+					return BCME_SERIAL_PORT_ERR;
+				}
+			rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
+			/* In case of shell or ASD commands the response
+			 * size is not known in advance
+			 * Hence based on response from the server memory is allocated
+			 */
+			if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
+				DPRINT_ERR(ERR, "Mem alloc fails for shell response buffer\n");
+				return FAIL;
+			}
+
+			if (rem_ptr->data_len < DATA_FRAME_LEN) {
+				/* Response comes in one shot not in fragments */
+				if (remote_CDC_rx(wl, rem_ptr, resp_buf,
+					rem_ptr->msg.len, 0) == FAIL) {
+					DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
+					free(resp_buf);
+					return FAIL;
+				}
+			} else {
+				error = rwl_serial_fragmented_response_fe(wl, rem_ptr,
+					resp_buf, (unsigned long *)&(rem_ptr->msg.len));
+			}
+			/* print the shell result */
+			resp_buf[rem_ptr->msg.len] = '\0';
+			/* The return value of the shell command will be stored in rem_ptr->msg.cmd
+			 * Return that value to the client process
+			 */
+				if (rem_ptr->msg.flags & REMOTE_REPLY)
+					error = rem_ptr->msg.cmd;
+			fputs((char*)resp_buf, stdout);
+			}
+			break;
+
+		case REMOTE_WIFI:
+#ifdef RWL_WIFI
+			/* Unlike dongle or UART case the response for wi-fi comes in single frame.
+			 * (CDC header + data). Hence the single read is called for header and data.
+			 * If any error in reading then we sleep for some time before retrying.
+			 */
+			if ((list = (dot11_action_wifi_vendor_specific_t *)
+				malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
+				return FAIL;
+			}
+			if ((rem_ptr = (rem_ioctl_t *)malloc(REMOTE_SIZE)) == NULL) {
+				free(list);
+				return FAIL;
+			}
+
+			if ((cbuf = (char*) malloc(*input_len)) == NULL) {
+				DPRINT_ERR(ERR, "Malloc failed for shell response\n");
+				free(rem_ptr);
+				free(list);
+				return FAIL;
+			}
+
+			/* copy of the original buf is required for retry */
+			memcpy(cbuf, (char*)input_buf, *input_len);
+			for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+
+				if ((error = rwl_wifi_purge_actionframes(wl)) < 0) {
+					break;
+				}
+
+				if (remote_CDC_tx(wl, cmd, input_buf, *input_len, *input_len,
+				remote_cmd, 0) < 0) {
+						DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
+							"Send command failed\n");
+						rwl_sleep(RWL_WIFI_RETRY_DELAY);
+						free(rem_ptr);
+						free(list);
+						return FAIL;
+				}
+				/* For backward compatibility for ASD,
+				 * async and kill commands do the
+				 * old way
+				 */
+				if (remote_cmd == REMOTE_SHELL_CMD &&
+					!strstr((char*)input_buf, "%") &&
+					!strstr((char*)input_buf, "kill")) {
+					error = rwl_wifi_shellresp(wl, rem_ptr, input_buf);
+						if (rem_ptr->msg.len == 0)
+						break;
+					}
+				else if (remote_cmd == REMOTE_VISTA_CMD) {
+					if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr, 0,
+					NULL, RWL_WIFI_SHELL_CMD)) < 0) {
+						DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
+						"error in reading shell response\n");
+						continue;
+					}
+					if (rem_ptr->msg.flags & REMOTE_REPLY) {
+						 error = rem_ptr->msg.cmd;
+						 break;
+					} else {
+						rwl_sleep(RWL_WIFI_RETRY_DELAY);
+						continue;
+					}
+				}
+				else {
+					/* ASD commands may take long time to give back
+					* the response (eg: file transfer)
+					*/
+					if (remote_cmd == REMOTE_ASD_CMD) {
+						for (;;) {
+						/* copy back the buffer to input buffer */
+						memcpy((char*)input_buf, cbuf, *input_len);
+
+							if ((error = remote_CDC_DATA_wifi_rx_frag(
+								wl, rem_ptr, 0, NULL,
+								RWL_WIFI_SHELL_CMD)) < 0) {
+								DPRINT_DBG(OUTPUT,
+								"rwl_shell_information_fe(wifi):"
+								"err in reading shell response\n");
+								continue;
+							}
+							if (rem_ptr->msg.flags & REMOTE_REPLY) {
+								error = rem_ptr->msg.cmd;
+								retry = RWL_WIFI_RETRY;
+								break;
+							} else {
+								rwl_sleep(RWL_WIFI_RETRY_DELAY);
+								continue;
+							}
+						}
+					}
+				}
+
+			}
+			free(rem_ptr);
+			free(list);
+			if (cbuf != NULL)
+				free(cbuf);
+#endif /* RWL_WIFI */
+			break;
+
+		default:
+			break;
+	} /* End of switch (remote_type) */
+
+	if (resp_buf)
+		free(resp_buf);
+
+	return error;
+}
+
+/* Prepare to issue shell command */
+int
+rwl_shell_cmd_proc(void *wl, char **argv, int cmd)
+{
+	uchar *buff;
+	unsigned long len = SHELL_CMD_LEN;
+	int err;
+	unsigned int cmdlen = 0;
+
+	if ((buff = malloc(SHELL_CMD_LEN)) == NULL) {
+		DPRINT_ERR(ERR, "\n Mem alloc fails for shell cmd buffer\n");
+		return FAIL;
+	}
+
+	memset(buff, 0, SHELL_CMD_LEN);
+	cmdlen = SHELL_CMD_LEN - 1;
+	while (*argv) {
+		strncat((char*)buff, *argv, cmdlen);
+		cmdlen -= strlen(*argv);
+		argv++;
+		if (*argv) {
+			strcat((char*)buff, " "); /* leave space between args */
+			cmdlen--;
+		}
+		if (*argv && cmdlen < (strlen(*argv)))
+		{
+			free(buff);
+			DPRINT_ERR(ERR, "\n Insufficient length for shell cmd buffer\n");
+			return FAIL;
+		}
+	}
+
+	err = rwl_shell_information_fe(wl, cmd, buff, &len);
+	free(buff);
+	return err;
+}
+
+/* transport independent entry point for GET ioctls */
+int
+rwl_queryinformation_fe(void *wl, int cmd, void* input_buf,
+	unsigned long *input_len, int debug, int rem_ioctl_select) {
+	int error = 0;
+	uint tx_len;
+#if defined(RWL_SERIAL) || RWL_WIFI
+	rem_ioctl_t *rem_ptr = NULL;
+#endif
+
+#ifdef RWL_WIFI
+	int retry;
+	char *cinput_buf;
+#endif
+
+	UNUSED_PARAMETER(debug);
+
+	switch (remote_type) {
+		case REMOTE_SOCKET:
+#ifdef RWL_SOCKET
+		/* We don't want the server to allocate bigger buffers
+		 * for some of the commands
+		 * like scanresults. Server can still allocate 8K memory
+		 * and send the response
+		 */
+		if ((int)(*input_len) > SERVER_RESPONSE_MAX_BUF_LEN)
+			*input_len = SERVER_RESPONSE_MAX_BUF_LEN;
+		error = rwl_information_socket(wl, cmd, input_buf, input_len,
+			input_len, rem_ioctl_select);
+#endif /* RWL_SOCKET */
+		break;
+
+#ifdef RWL_SERIAL
+		/* System serial transport is not supported in Linux. Only XP */
+		case REMOTE_SERIAL:
+#ifdef SERDOWNLOAD
+			tx_len = MIN(*input_len, SERVER_RESPONSE_MAX_BUF_LEN);
+#else
+			tx_len = MIN(*input_len, 1024);
+#endif
+			/* Time estimate assumes 115K baud */
+			if (*input_len > (1024 *10))
+				/* Multiply by 2. The buffer has to go there and back */
+				DPRINT_DBG(OUTPUT, "Wait time: %lu seconds\n",
+				((*input_len)+ tx_len) / (115200/8));
+
+			if (remote_CDC_tx(wl, cmd, input_buf, *input_len,
+			tx_len, rem_ioctl_select, debug) < 0) {
+				DPRINT_ERR(ERR, "query_info_fe: Send command failed\n");
+				return FAIL;
+			}
+
+			if ((rem_ptr = remote_CDC_rx_hdr(wl, debug)) == NULL) {
+				DPRINT_ERR(ERR, "query_info_fe: Reading CDC header failed\n");
+				return FAIL;
+			}
+
+			if (rem_ptr->msg.flags != REMOTE_REPLY) {
+				DPRINT_ERR(ERR, "query_info_fe: response format error.\n");
+				return FAIL;
+			}
+			if (rem_ptr->msg.len > *input_len) {
+				DPRINT_ERR(ERR, "query_info_fe: needed size(%d) greater than "
+				"actual size(%lu)\n", rem_ptr->msg.len, *input_len);
+				return FAIL;
+			}
+
+			error = rem_ptr->msg.cmd;
+			if (error != 0)
+				DPRINT_ERR(ERR, "query_info_fe: remote cdc header return "
+					   "error code %d\n", error);
+			if (remote_CDC_rx(wl, rem_ptr, input_buf, *input_len, debug) == -1) {
+				DPRINT_ERR(ERR, "query_info_fe: No results!\n");
+				return FAIL;
+			}
+			if (rem_ptr->msg.flags & REMOTE_REPLY)
+				error = rem_ptr->msg.cmd;
+			break;
+
+#endif /* RWL_SERIAL */
+		case REMOTE_DONGLE:
+			/* We don't want the server to allocate bigger buffers
+			 * for some of the commands
+			 * like scanresults. Server can still allocate 8K
+			 *memory and send the response
+			 * in fragments.
+			 */
+			if ((int)(*input_len) > SERVER_RESPONSE_MAX_BUF_LEN)
+				*input_len = SERVER_RESPONSE_MAX_BUF_LEN;
+
+			/* Actual buffer to be sent should be max 256 bytes as
+			 *UART input buffer
+			 * is 512 bytes
+			 */
+			tx_len = MIN(*input_len, 256);
+			error = rwl_information_dongle(wl, cmd, input_buf, input_len,
+				tx_len, rem_ioctl_select);
+
+			break;
+
+		case REMOTE_WIFI:
+#ifdef RWL_WIFI
+			/* We don't want the server to allocate bigger buffers
+			 * for some of the commands
+			 * like scanresults. Server can still allocate 8K memory
+			 * and send the response
+			 * in fragments.
+			 */
+			if ((int)(*input_len) > SERVER_RESPONSE_MAX_BUF_LEN)
+				*input_len = SERVER_RESPONSE_MAX_BUF_LEN;
+
+			/* Actual buffer to be sent should be max 960 bytes
+			 * as wifi max frame size if 960
+			 * and actual data for any command will not exceed 960 bytes
+			*/
+			tx_len = MIN(*input_len, RWL_WIFI_FRAG_DATA_SIZE);
+
+			if ((rem_ptr = (rem_ioctl_t *)malloc(REMOTE_SIZE)) == NULL) {
+				return FAIL;
+			}
+			if ((cinput_buf = (char*)malloc(tx_len)) == NULL) {
+				DPRINT_ERR(ERR, "Malloc failed for query information fe"
+				"character buf \n");
+				free(rem_ptr);
+				return FAIL;
+			}
+
+			memcpy(cinput_buf, (char*)input_buf, tx_len); /* Keep a copy of input_buf */
+
+			for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+
+				if ((error = rwl_wifi_purge_actionframes(wl)) < 0) {
+					break;
+				}
+
+				if (retry > 3)
+					DPRINT_INFO(OUTPUT, "ir_queryinformation_fe : retry %d"
+					"cmd %d\n", retry, cmd);
+
+				/* copy back the buffer to input buffer */
+				memcpy((char*)input_buf, cinput_buf, tx_len);
+
+				/* Issue the command */
+				if ((error = remote_CDC_wifi_tx(wl, cmd, input_buf,
+					*input_len, tx_len, rem_ioctl_select)) < 0) {
+					DPRINT_DBG(OUTPUT, "query_info_fe: Send command failed\n");
+						rwl_sleep(RWL_WIFI_RETRY_DELAY);
+						continue;
+				}
+
+				if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr,
+					*input_len, input_buf, RWL_WIFI_WL_CMD) < 0)) {
+					DPRINT_DBG(OUTPUT, "ir_queryinformation_fe :"
+					"Error in reading the frag bytes\n");
+					rwl_sleep(RWL_WIFI_RETRY_DELAY);
+					continue;
+				}
+
+				if (rem_ptr->msg.flags & REMOTE_REPLY) {
+					error = rem_ptr->msg.cmd;
+					break;
+				} else {
+					rwl_sleep(RWL_WIFI_RETRY_DELAY);
+				}
+			}
+
+			free(rem_ptr);
+			if (cinput_buf)
+				free(cinput_buf);
+			break;
+#endif /* RWL_WIFI */
+		default:
+			DPRINT_ERR(ERR, "rwl_queryinformation_fe: Unknown"
+				"remote_type %d\n", remote_type);
+		break;
+	}
+	return error;
+}
+
+/*
+* This is the front end query function for Set Ioctls. This is used by clients
+for executing Set Ioctls.
+*/
+int
+rwl_setinformation_fe(void *wl, int cmd, void* buf,
+	unsigned long *len, int debug, int rem_ioctl_select) {
+	int error = 0;
+	uint tx_len;
+#if defined(RWL_SERIAL) || RWL_WIFI
+	rem_ioctl_t *rem_ptr = NULL;
+#endif
+
+#ifdef RWL_WIFI
+	dot11_action_wifi_vendor_specific_t *list = NULL;
+	char *cbuf, retry;
+#endif
+
+	UNUSED_PARAMETER(debug);
+
+	switch (remote_type) {
+		case REMOTE_SOCKET:
+#ifdef RWL_SOCKET
+			error = rwl_information_socket(wl, cmd, buf, len, len, rem_ioctl_select);
+#endif
+			break;
+#ifdef RWL_SERIAL
+		case REMOTE_SERIAL:
+			if (*len > (1024 *10))
+				DPRINT_DBG(OUTPUT, "Wait time: %lu seconds\n", (*len)/(115200/8));
+
+			if (remote_CDC_tx(wl, cmd, buf, *len, *len, rem_ioctl_select, debug) < 0) {
+				DPRINT_ERR(ERR, "set_info_fe: Send command failed\n");
+				return FAIL;
+			}
+
+			if ((rem_ptr = remote_CDC_rx_hdr(wl, debug)) == NULL) {
+				DPRINT_ERR(ERR, "set_info_fe: Reading CDC header failed\n");
+				return FAIL;
+			}
+
+			if (rem_ptr->msg.flags != REMOTE_REPLY)	{
+				DPRINT_ERR(ERR, "set_info_fe: response format error.\n");
+				return FAIL;
+			}
+
+			if (rem_ptr->msg.len > *len) {
+				DPRINT_ERR(ERR, "set_info_fe: needed size (%d) greater than "
+					   "actual size (%lu)\n", rem_ptr->msg.len, *len);
+				return FAIL;
+			}
+
+			error = rem_ptr->msg.cmd;
+			if (error != 0) {
+				DPRINT_ERR(ERR, "set_info_fe: remote cdc header return "
+					   "error code (%d)\n", error);
+			}
+
+			if (remote_CDC_rx(wl, rem_ptr, buf, rem_ptr->msg.len, debug) == -1) {
+				DPRINT_ERR(ERR, "set_info_fe: fetching results failed\n");
+				return FAIL;
+			}
+
+			if (rem_ptr->msg.flags & REMOTE_REPLY)
+				error = rem_ptr->msg.cmd;
+			break;
+#endif /* RWL_SERIAL */
+		case REMOTE_DONGLE:
+			if ((int)(*len) > SERVER_RESPONSE_MAX_BUF_LEN)
+				*len = SERVER_RESPONSE_MAX_BUF_LEN;
+
+			/* Actual buffer to be sent should be max 256 bytes as
+			 *UART input buffer
+			 * is 512 bytes
+			 */
+			tx_len = MIN(*len, 512);
+			error = rwl_information_dongle(wl, cmd, buf, len, tx_len, rem_ioctl_select);
+			break;
+
+		case REMOTE_WIFI:
+#ifdef RWL_WIFI
+			if ((int)(*len) > SERVER_RESPONSE_MAX_BUF_LEN)
+				*len = SERVER_RESPONSE_MAX_BUF_LEN;
+
+			/* Actual buffer to be sent should be max 960 bytes
+			 * as wifi max frame size if 960
+			 * and actual data for any command will not exceed 960 bytes
+			*/
+			tx_len = MIN(*len, RWL_WIFI_FRAG_DATA_SIZE);
+
+			if ((cbuf = (char*) malloc(tx_len)) == NULL) {
+				DPRINT_ERR(ERR, "Malloc failed for set_info_fe character buf\n");
+				return FAIL;
+			}
+			if ((list = (dot11_action_wifi_vendor_specific_t *)
+					malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
+				free(cbuf);
+				return FAIL;
+			}
+
+			if ((rem_ptr = (rem_ioctl_t *)malloc(sizeof(rem_ioctl_t))) == NULL) {
+				free(list);
+				free(cbuf);
+				return FAIL;
+			}
+
+			memcpy(cbuf, (char*)buf, tx_len);
+
+			for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+
+				if ((error = rwl_wifi_purge_actionframes(wl)) < 0) {
+					break;
+				}
+
+				/* copy back the buffer to input buffer */
+				memcpy((char*)buf, (char*)cbuf, tx_len);
+
+				if (retry > 3)
+					DPRINT_INFO(OUTPUT, "retry %d cmd %d\n", retry, cmd);
+
+				if ((error = remote_CDC_wifi_tx(wl, cmd, buf, *len,
+				                                tx_len, rem_ioctl_select) < 0)) {
+					DPRINT_ERR(ERR, "ir_setinformation_fe: Send"
+					"command failed\n");
+					rwl_sleep(RWL_WIFI_RETRY_DELAY);
+					continue;
+				}
+
+				if ((char*)buf != NULL) {
+					/* In case cmd is findserver, response is not
+					 * required from the server
+					 */
+					if (!strcmp((char*)buf, RWL_WIFI_FIND_SER_CMD)) {
+						break;
+					}
+				}
+
+				/* Read the CDC header and data of for the sent cmd
+				 * resposne
+				 */
+				if ((error = remote_CDC_DATA_wifi_rx((void*)wl, list) < 0)) {
+					DPRINT_ERR(ERR, "ir_setinformation_fe: failed to read"
+						"the response\n");
+					rwl_sleep(RWL_WIFI_RETRY_DELAY);
+					continue;
+				}
+
+				memcpy((char*)rem_ptr,
+				(char*)&list->data[RWL_WIFI_CDC_HEADER_OFFSET],
+				REMOTE_SIZE);
+				rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
+
+				memcpy((char*)buf, (char*)&list->data[REMOTE_SIZE],
+				rem_ptr->msg.len);
+
+				if (rem_ptr->msg.flags & REMOTE_REPLY) {
+					error = rem_ptr->msg.cmd;
+					break;
+				} else {
+					rwl_sleep(RWL_WIFI_RETRY_DELAY);
+				}
+			}
+				free(rem_ptr);
+				free(list);
+			if (cbuf != NULL)
+				free(cbuf);
+			break;
+#endif /* RWL_WIFI */
+		default:
+			DPRINT_ERR(ERR, "rwl_setinformation_fe: Unknown remote_type:%d\n",
+			remote_type);
+		break;
+	}
+
+	return error;
+}
+
+#ifdef RWL_WIFI
+int
+rwl_var_getbuf(void *wl, const char *iovar, void *param, int param_len, void **bufptr)
+{
+	int len, error;
+
+	memset((char*)g_rwl_aligned_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(g_rwl_aligned_buf, iovar);
+
+	/* include the null */
+	len = (int)strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&g_rwl_aligned_buf[len], param, param_len);
+
+	*bufptr = g_rwl_aligned_buf;
+	/*   When user wants to execute local CMD being in remote wifi mode,
+	*	rwl_wifi_swap_remote_type fucntion is used to change the remote types.
+	*/
+	rwl_wifi_swap_remote_type(remote_type);
+
+	error = wl_get(wl, WLC_GET_VAR, &g_rwl_aligned_buf[0], WLC_IOCTL_MAXLEN);
+	/* revert back to the old remote type */
+	rwl_wifi_swap_remote_type(remote_type);
+	return error;
+}
+
+int
+rwl_var_setbuf(void *wl, const char *iovar, void *param, int param_len)
+{
+	int len, error;
+
+	memset(g_rwl_aligned_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(g_rwl_aligned_buf, iovar);
+
+	/* include the null */
+	len = (int)strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&g_rwl_aligned_buf[len], param, param_len);
+
+	len += param_len;
+	/*   When user wants to execute local CMD being in remote wifi mode,
+	*	rwl_wifi_swap_remote_type fucntion is used to change the remote types.
+	*/
+	rwl_wifi_swap_remote_type(remote_type);
+	error = wl_set(wl, WLC_SET_VAR, &g_rwl_aligned_buf[0], len);
+	/* revert back to the old type */
+	rwl_wifi_swap_remote_type(remote_type);
+	return error;
+}
+
+/* This function will send the buffer to the dongle driver */
+int
+rwl_var_send_vs_actionframe(void* wl, const char* iovar, void* param, int param_len)
+{
+	int len, error;
+
+	memset(g_rwl_aligned_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(g_rwl_aligned_buf, iovar);
+
+	/* include the null */
+	len = (int)strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy((void*)&g_rwl_aligned_buf[len+ OFFSETOF(wl_action_frame_t, data)],
+		param,
+		param_len);
+
+	/* Set the PacketID (not used by remote WL */
+	memset((void*)&g_rwl_aligned_buf[len + OFFSETOF(wl_action_frame_t, packetId)], 0, 4);
+
+	/* Set the dest addr */
+	memcpy((void*)&g_rwl_aligned_buf[len + OFFSETOF(wl_action_frame_t, da)],
+	(void*)g_rwl_buf_mac,
+	ETHER_ADDR_LEN);
+
+	/* set the length */
+	memcpy((void*)&g_rwl_aligned_buf[len + OFFSETOF(wl_action_frame_t, len)],
+	(void*) &param_len,
+	2);
+
+	len  += param_len + ETHER_ADDR_LEN + 2 + 4;
+
+	/*   When user wants to execute local CMD being in remote wifi mode,
+	*	rwl_wifi_swap_remote_type fucntion is used to change the remote types.
+	*/
+	rwl_wifi_swap_remote_type(remote_type);
+
+	error = wl_set(wl, WLC_SET_VAR, &g_rwl_aligned_buf[0], len);
+	/* revert back to the old type */
+	rwl_wifi_swap_remote_type(remote_type);
+	return error;
+}
+#endif /* RWL_WIFI */
+/*
+ * Function for printing the usage if user type invalid command line
+ * options(e.g wl --serial or --dongle or --socket or --wifi)
+ */
+void
+rwl_usage(int remote_type)
+{
+	switch (remote_type) {
+	case REMOTE_SERIAL:
+			fprintf(stderr, " Usage: wl/dhd [--linuxdut/linux] [--debug]");
+			fprintf(stderr, " [--serial port no]");
+			fprintf(stderr, "[--ReadTimeout n] [--interactive] [--clientbatch] \n");
+			fprintf(stderr, "\t--linuxdut/linux removes the WLC_OID_BASE");
+			fprintf(stderr, "when sending the IOCTL command \n");
+			fprintf(stderr, "\t--debug prints out tx packets sending down ");
+			fprintf(stderr, " the serial line, and other debug info \n");
+			fprintf(stderr, "\t--serial enables the remoteWL serial port number\n");
+			fprintf(stderr, "\t--interactive enables using WL in interactive mode\n");
+			fprintf(stderr, "\t--clientbatch enables command batchinng on the client,");
+			fprintf(stderr, " the default is batching on driver\n");
+		break;
+	case REMOTE_DONGLE:
+			fprintf(stderr, " Usage: wl/dhd --dongle <Device Name>  <command>\n");
+			fprintf(stderr, "\t<Device Name> COM1/COM2 (WinXP) or /dev/ttyS0"
+			" or /dev/ttyS1 (Linux)\n");
+			fprintf(stderr, "\t<command> - wl, shell or dhd command\n");
+			fprintf(stderr, "\tDepending on the client you are using(wl or dhd)\n");
+			fprintf(stderr, "\t\t shell command usage: sh <command>\n");
+		break;
+	case REMOTE_SOCKET:
+			fprintf(stderr, " Usage: "
+				"wl/dhd --socket <IP ADDRESS> [<PORT>] <command>\n");
+			fprintf(stderr, "\t<IPADDRESS> IP address of server machine\n");
+			fprintf(stderr, "\t<PORT> Port no of server\n");
+			fprintf(stderr, "\t<command> - wl, shell or dhd command\n");
+			fprintf(stderr, "\tDepending on the client you are using(wl or dhd)\n");
+			fprintf(stderr, "\t\t shell command usage: sh <command>\n");
+			fprintf(stderr, "\t If <PORT> is omitted, use default port number 8000\n");
+		break;
+	case REMOTE_WIFI:
+			fprintf(stderr, " Usage: wl/dhd --wifi <MAC Address> <command>\n");
+			fprintf(stderr, "\t<MAC Address> MAC Address\n");
+			fprintf(stderr, "\t<command> - wl, shell or dhd command\n");
+			fprintf(stderr, "\tDepending on the client you are using(wl or dhd)\n");
+			fprintf(stderr, "\t\t shell command usage: sh <command>\n");
+		break;
+	default:
+		break;
+	}
+}
+#ifdef RWL_SOCKET
+/* Note in case of error ( returned value == FAIL) it is assumed that wl is closed by caller,
+ * no treatment in this function
+ */
+static int
+rwl_socket_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf)
+{
+	uchar* resp_buf = NULL;
+	int pid, msg_len = 0, error = FAIL;
+	g_sig_ctrlc = 1;
+	g_child_pid = pid = rwl_shell_createproc(wl);
+	if (pid == 0) {
+		while (g_sig_ctrlc);
+		remote_CDC_tx(wl, 0, input_buf, 0, 0, CTRLC_FLAG, 0);
+		exit(0);
+	}
+
+	do {
+		if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+		DPRINT_ERR(ERR, "rwl_socket_shellresp: Receiving CDC"
+			"header failed\n");
+		return FAIL;
+		}
+		msg_len = rem_ptr->msg.len;
+		if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
+			DPRINT_ERR(ERR, "rwl_socket_shellresp: Mem alloc fails\n");
+			return FAIL;
+		}
+		if (msg_len > 0) {
+			if (remote_CDC_rx(wl, rem_ptr, resp_buf,
+				rem_ptr->msg.len, 0) == FAIL) {
+				DPRINT_ERR(ERR, "rwl_socket_shellresp: No results!\n");
+				free(resp_buf);
+				return FAIL;
+			}
+		}
+		/* print the shell result */
+		resp_buf[rem_ptr->msg.len] = '\0';
+		/* The return value of the shell command
+		 * will be stored in rem_ptr->msg.cmd
+		 * Return that value to the client process
+		 */
+		if (rem_ptr->msg.flags & REMOTE_REPLY)
+			error = rem_ptr->msg.cmd;
+#ifdef LINUX
+		write(1, resp_buf, msg_len);
+#else
+		fputs((char*)resp_buf, stdout);
+#endif
+	} while (msg_len);
+	rwl_shell_killproc(pid);
+	return error;
+}
+#endif /* RWL_SOCKET */
+/* For wifi shell responses read data until server stops sending */
+#ifdef RWL_WIFI
+static int
+rwl_wifi_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf)
+{
+	int pid, msg_len = 0, error = FAIL;
+	g_sig_ctrlc = 1;
+	g_child_pid = pid = rwl_shell_createproc(wl);
+	if (pid == 0)
+	{
+		while (g_sig_ctrlc);
+		remote_CDC_tx(wl, 0, input_buf, 0, 0, CTRLC_FLAG, 0);
+		exit(0);
+	}
+
+	do {
+		if ((error = remote_CDC_DATA_wifi_rx_frag(wl, rem_ptr, 0,
+		NULL, RWL_WIFI_SHELL_CMD)) < 0) {
+			DPRINT_DBG(OUTPUT, "rwl_shell_information_fe(wifi):"
+			"error in reading shell response\n");
+			continue;
+		}
+		msg_len = rem_ptr->msg.len;
+		error = rem_ptr->msg.cmd;
+	} while (msg_len);
+
+	rwl_shell_killproc(pid);
+	return error;
+}
+#endif /* RWL_WIFI */
+
+/* For dongle or system serial shell responses read data until server stops sending */
+static int
+rwl_dongle_shellresp(void *wl, rem_ioctl_t *rem_ptr, uchar *input_buf, int cmd)
+{
+	int pid, msg_len, error = 0;
+	uchar *resp_buf;
+
+	g_sig_ctrlc = 1;
+	g_child_pid = pid = rwl_shell_createproc(wl);
+	if (pid == 0) {
+		while (g_sig_ctrlc);
+		remote_CDC_tx(wl, cmd, input_buf, 0, 0, CTRLC_FLAG, 0);
+		exit(0);
+	}
+
+	do {
+		if ((rem_ptr = remote_CDC_rx_hdr(wl, 0)) == NULL) {
+			DPRINT_ERR(ERR, "shell_info_fe: Receiving CDC header failed\n");
+			return BCME_SERIAL_PORT_ERR;
+		}
+		/* In case of shell or ASD commands the response size is not known in advance
+		* Hence based on response from the server memory is allocated
+		*/
+		msg_len = rem_ptr->msg.len;
+		if ((resp_buf = malloc(rem_ptr->msg.len + 1)) == NULL) {
+			DPRINT_ERR(ERR, "Mem alloc fails for shell response buffer\n");
+			return FAIL;
+		}
+		/* Response comes in one shot not in fragments */
+		if (remote_CDC_rx(wl, rem_ptr, resp_buf,
+			rem_ptr->msg.len, 0) == FAIL) {
+			DPRINT_ERR(ERR, "shell_info_fe: No results!\n");
+			free(resp_buf);
+			return FAIL;
+		}
+		/* print the shell result */
+		resp_buf[rem_ptr->msg.len] = '\0';
+		/* The return value of the shell command will be stored in rem_ptr->msg.cmd
+		 * Return that value to the client process
+		 */
+		if (rem_ptr->msg.flags & REMOTE_REPLY)
+			error = rem_ptr->msg.cmd;
+#ifdef LINUX
+		write(1, resp_buf, msg_len);
+#else
+		fputs((char*)resp_buf, stdout);
+#endif
+		free(resp_buf);
+	} while (msg_len);
+	rwl_shell_killproc(pid);
+	return error;
+}
+
+int rwl_detect(void *wl, bool debug, int* os_type_ptr)
+{
+	int error, buf = UNKNOWN_OS;
+	unsigned long len = sizeof(buf);
+
+	error = rwl_queryinformation_fe(wl,
+		NEGOTIATE_GET_OS, &buf, &len, debug, REMOTE_NEGOTIATE_CMD);
+	if (!error) {
+		if (buf > UNKNOWN_OS && buf < INVALID_OS) {
+			*os_type_ptr = buf;
+			if (debug)
+				fprintf(stderr, "Autodetect: %d\n", *os_type_ptr);
+			return 0;
+		}
+	}
+
+	fprintf(stderr, "Autodetect failed, rwl server is either "
+			"too old or unreachable. Use --nodetect to disable autodetect.\n");
+	return FAIL;
+}
+
+int rwl_check_port_number(char *s, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		if (!isdigit(s[i]))
+			return FAIL;
+	}
+	return SUCCESS;
+}
diff --git a/wl/src/wl/exe/wlu_client_shared.h b/wl/src/wl/exe/wlu_client_shared.h
new file mode 100644
index 0000000..024432d
--- /dev/null
+++ b/wl/src/wl/exe/wlu_client_shared.h
@@ -0,0 +1,40 @@
+/*
+ * OS independent client specific declarations
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_client_shared.h 514727 2014-11-12 03:02:48Z $
+ */
+#ifndef _wlu_client_shared_h
+#define _wlu_client_shared_h
+
+/* Newly added wrappers from wlu_client_shared.c */
+extern int
+rwl_shell_cmd_proc(void *wl, char **argv, int cmd);
+extern int
+rwl_queryinformation_fe(void *wl, int cmd, void* input_buf, unsigned long *input_len,
+int debug, int rem_ioctl_select);
+extern int
+rwl_setinformation_fe(void *wl, int cmd, void* buf, unsigned long *len, int debug,
+int rem_ioctl_select);
+extern void
+rwl_usage(int remote_type);
+extern int
+rwl_detect(void *wl, bool debug, int* os_type_ptr);
+
+extern int rwl_shell_createproc(void *wl);
+extern void rwl_shell_killproc(int pid);
+/* declaring these as extern to be used in wlu_ndis.c and wlu_linux.c */
+extern volatile sig_atomic_t g_sig_ctrlc;
+extern void ctrlc_handler(int num);
+
+#endif /* _wlu_client_share_h */
diff --git a/wl/src/wl/exe/wlu_cmd.c b/wl/src/wl/exe/wlu_cmd.c
new file mode 100644
index 0000000..b485df2
--- /dev/null
+++ b/wl/src/wl/exe/wlu_cmd.c
@@ -0,0 +1,31 @@
+/*
+ * File:        wlu_cmd.c
+ * Purpose:     Command and IO variable information commands
+ * Requires:
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_cmd.c 601272 2015-11-20 21:12:22Z $
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <wlioctl.h>
+
+#include "wlu.h"
diff --git a/wl/src/wl/exe/wlu_cmd.h b/wl/src/wl/exe/wlu_cmd.h
new file mode 100644
index 0000000..c6a1cfc
--- /dev/null
+++ b/wl/src/wl/exe/wlu_cmd.h
@@ -0,0 +1,177 @@
+/*
+ * Command structure for wl command line utility
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * All Rights Reserved.
+ *
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied or
+ * duplicated in any form, in whole or in part, without the prior written
+ * permission of Broadcom Corporation.
+ *
+ * $Id: wlu_cmd.h 635987 2016-05-06 01:49:37Z $
+ */
+
+#ifndef _wlu_cmd_h_
+#define _wlu_cmd_h_
+
+/*   wl_nan_sub_cmd may also be used in dhd  */
+typedef struct wl_nan_sub_cmd wl_nan_sub_cmd_t;
+typedef int (cmd_handler_t)(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len);
+/*
+ * nan sub-commands list entry
+ */
+struct wl_nan_sub_cmd {
+	char *name;
+	uint8 version;
+	uint16 id;
+	uint16 type;
+	cmd_handler_t *handler;
+};
+
+/*
+ * NAN sub-command help list entry
+ */
+typedef struct wl_nan_cmd_help wl_nan_cmd_help_t;
+typedef void (cmd_help_handler_t)(void);
+struct wl_nan_cmd_help {
+	uint16 type;
+	cmd_help_handler_t *help_handler;
+};
+
+
+typedef struct cmd cmd_t;
+typedef int (cmd_func_t)(void *wl, cmd_t *cmd, char **argv);
+
+/* generic command line argument handler */
+struct cmd {
+	const char *name;
+	cmd_func_t *func;
+	int get;
+	int set;
+	const char *help;
+};
+
+/* list of command line arguments */
+extern cmd_t wl_cmds[];
+extern cmd_t wl_varcmd;
+
+/* per-port ioctl handlers */
+extern int wl_get(void *wl, int cmd, void *buf, int len);
+extern int wl_set(void *wl, int cmd, void *buf, int len);
+
+/*
+ * Flags for command categories.  A command may belong to
+ * multiple categories.  These are used in bitmaps, so be careful
+ * to keep the macro value (2 ^ n) and the array indexes (n)
+ * consistent.
+ */
+
+#define CMD_PHY               0x1
+#define CMD_CHAN              0x2
+#define CMD_RATE              0x4
+#define CMD_POWER             0x8
+#define CMD_MAC               0x10
+#define CMD_MGMT              0x20
+#define CMD_SEC               0x40
+#define CMD_WME               0x80
+#define CMD_MON               0x100
+#define CMD_AP                0x200
+#define CMD_STA               0x400
+#define CMD_BOARD             0x800
+#define CMD_ADMIN             0x1000
+#define CMD_DEV               0x2000
+#define CMD_DEP               0x4000
+#define CMD_UNCAT             0x8000
+
+#define CMD_ALL               0xffff
+
+/* Initializer for category string array */
+
+#define CMD_CATEGORY_STRINGS_INIT { \
+	"phy",   \
+	"chan",  \
+	"rate",  \
+	"power", \
+	"mac",   \
+	"mgmt",  \
+	"sec",   \
+	"wme",   \
+	"mon",   \
+	"ap",    \
+	"sta",   \
+	"board", \
+	"admin", \
+	"dev",   \
+	"dep",   \
+	"uncat", \
+	"" }
+
+extern const char *wl_cmd_category_strings[];
+extern const int wl_cmd_category_count;
+
+/* Initializer for category description strings array */
+#define CMD_CATEGORY_DESC_INIT { \
+	"PHY and radio; speed, band, etc", \
+	"Channel; subclass of phy",  \
+	"Rate; subclass of phy, a/b/g",  \
+	"Power; subclass of phy", \
+	"MAC; Media access",   \
+	"Management, association, IE, etc",  \
+	"Security; subclass of mgmt",   \
+	"WME; media extensions",   \
+	"Monitoring device (counters, etc)",   \
+	"AP subclass of mgmt", \
+	"STA subclass of mgmt", \
+	"Board, hardware", \
+	"Administration; software, UI, diags", \
+	"Device; low level control", \
+	"Deprecated", \
+	"Uncategorized so far", \
+	"" }
+
+extern const char *wl_cmd_category_desc[];
+
+/*
+ *
+ * IO variable information
+ *
+ */
+
+/* Supplemental IO variable info structure */
+typedef const struct wlu_iov_info_s {
+	const char *name;
+	uint32 cat;  /* Category flags; same as command categories */
+	uint32 flags; /* See below */
+	int dflt;  /* Only for integers; see flags */
+	const char *desc;  /* Description */
+} wlu_iov_info_t;
+
+/* Flags for wlu_iov_info_t */
+#define WLU_IOVI_READ_ONLY         0x1   /* Known to be read only */
+#define WLU_IOVI_WRITE_ONLY        0x2   /* Known to be write only */
+#define WLU_IOVI_BCM_INTERNAL      0x4   /* Known to be BCM internal */
+#define WLU_IOVI_DEFAULT_VALID     0x8   /* Default value in structure is valid */
+
+extern wlu_iov_info_t wlu_iov_info[];
+extern int wlu_iov_info_count;
+
+#define WLU_IOV_BLOCK_LEN	10
+
+#define WLU_MOD_NAME_MAX	64 /* Max num modules */
+#define WLU_MOD_NAME_BYTES	16 /* Size of modules name */
+
+extern int wl_get_scan(void *wl, int opc, char *scan_buf, uint buf_len);
+
+#endif /* _wlu_cmd_h_ */
diff --git a/wl/src/wl/exe/wlu_common.c b/wl/src/wl/exe/wlu_common.c
new file mode 100644
index 0000000..a36eac6
--- /dev/null
+++ b/wl/src/wl/exe/wlu_common.c
@@ -0,0 +1,414 @@
+/*
+ * Common code for wl routines
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_common.c 583196 2015-09-01 07:11:55Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include "wlu_common.h"
+#include "wlu.h"
+#include <bcmendian.h>
+
+extern int wl_get(void *wl, int cmd, void *buf, int len);
+extern int wl_set(void *wl, int cmd, void *buf, int len);
+
+wl_cmd_list_t cmd_list;
+int cmd_pkt_list_num;
+bool cmd_batching_mode;
+
+const char *wlu_av0;
+
+/* global wlc index indentifier for RSDB -W/--wlc option */
+int g_wlc_idx = -1;
+
+/* IOCTL swapping mode for Big Endian host with Little Endian dongle.  Default to off */
+bool g_swap = FALSE;
+
+#ifdef SERDOWNLOAD
+extern int debug;
+#endif
+
+/*
+ * format an iovar buffer
+ * iovar name is converted to lower case
+ */
+static uint
+wl_iovar_mkbuf(const char *name, char *data, uint datalen, char *iovar_buf, uint buflen, int *perr)
+{
+	uint iovar_len;
+	char *p;
+
+	iovar_len = strlen(name) + 1;
+
+	/* check for overflow */
+	if ((iovar_len + datalen) > buflen) {
+		*perr = BCME_BUFTOOSHORT;
+		return 0;
+	}
+
+	/* copy data to the buffer past the end of the iovar name string */
+	if (datalen > 0)
+		memmove(&iovar_buf[iovar_len], data, datalen);
+
+	/* copy the name to the beginning of the buffer */
+	strcpy(iovar_buf, name);
+
+	/* wl command line automatically converts iovar names to lower case for
+	 * ease of use
+	 */
+	p = iovar_buf;
+	while (*p != '\0') {
+		*p = tolower((int)*p);
+		p++;
+	}
+
+	*perr = 0;
+	return (iovar_len + datalen);
+}
+
+void
+init_cmd_batchingmode(void)
+{
+	cmd_pkt_list_num = 0;
+	cmd_batching_mode = FALSE;
+}
+
+void
+clean_up_cmd_list(void)
+{
+	wl_seq_cmd_pkt_t *this_cmd, *next_cmd;
+
+	this_cmd = cmd_list.head;
+	while (this_cmd != NULL) {
+		next_cmd = this_cmd->next;
+		if (this_cmd->data != NULL) {
+			free(this_cmd->data);
+		}
+		free(this_cmd);
+		this_cmd = next_cmd;
+	}
+	cmd_list.head = NULL;
+	cmd_list.tail = NULL;
+	cmd_pkt_list_num = 0;
+}
+
+int
+add_one_batched_cmd(int cmd, void *cmdbuf, int len)
+{
+	wl_seq_cmd_pkt_t *new_cmd;
+
+	new_cmd = malloc(sizeof(wl_seq_cmd_pkt_t));
+
+	if (new_cmd == NULL) {
+		printf("malloc(%d) failed, free %d batched commands and exit batching mode\n",
+			(int)sizeof(wl_seq_cmd_pkt_t), cmd_pkt_list_num);
+		goto free_and_exit;
+	} else {
+#ifdef SERDOWNLOAD
+		if (debug)
+#endif /* SERDOWNLOAD */
+			printf("batching %dth command %d\n", cmd_pkt_list_num+1, cmd);
+
+	}
+
+	new_cmd->cmd_header.cmd = cmd;
+	new_cmd->cmd_header.len = len;
+	new_cmd->next  = NULL;
+
+	new_cmd->data = malloc(len);
+
+	if (new_cmd->data == NULL) {
+		printf("malloc(%d) failed, free %d batched commands and exit batching mode\n",
+			len, cmd_pkt_list_num);
+		free(new_cmd);
+		goto free_and_exit;
+	}
+
+	memcpy(new_cmd->data, cmdbuf, len);
+
+	if (cmd_list.tail != NULL)
+		cmd_list.tail->next = new_cmd;
+	else
+		cmd_list.head = new_cmd;
+
+	cmd_list.tail = new_cmd;
+
+	cmd_pkt_list_num ++;
+	return 0;
+
+free_and_exit:
+
+	clean_up_cmd_list();
+
+	if (cmd_batching_mode) {
+		cmd_batching_mode = FALSE;
+	}
+	else {
+		printf("calling add_one_batched_cmd() at non-command-batching mode, weird\n");
+	}
+
+	return -1;
+}
+
+int
+wlu_get_req_buflen(int cmd, void *cmdbuf, int len)
+{
+	int modified_len = len;
+	char *cmdstr = (char *)cmdbuf;
+
+	if (len == WLC_IOCTL_MAXLEN) {
+		if ((strcmp(cmdstr, "dump") == 0) ||
+			(cmd == WLC_SCAN_RESULTS))
+			modified_len = WLC_IOCTL_MAXLEN;
+		else
+			modified_len = WLC_IOCTL_MEDLEN;
+	}
+	return modified_len;
+}
+
+/* Wrapper function that converts -W option in to "wlc:" prefix
+ * (1) It converts an existing iovar to the following format
+ * wlc:<iovar_name>\0<wlc_idx><param>
+ * (2) It converts an existing ioctl to the following format
+ * wlc:ioc\0<wlc_idx><ioct_cmd_id><param>
+ * NOTE: (2) requires new iovar named "ioc" in driver
+*/
+static int
+wlu_wlc_wrapper(void *wl, bool get, int* cmd, void *cmdbuf, int len, void **outbuf, int *outlen)
+{
+	void *param = cmdbuf;
+	int paramlen = len;
+	int wlc_idx = g_wlc_idx;
+	char *name = NULL;
+	BCM_REFERENCE(wl);
+	/* Wrap only if we find a valid WLC index and iovar name */
+	if (wlc_idx >= 0) {
+		int cmdlen = 0;
+		int prefix_len = 0;
+		char *lbuf = NULL;
+		char *buf = NULL;
+		bool ioctl_wrap = FALSE;
+		if ((*cmd == WLC_GET_VAR) || (*cmd == WLC_SET_VAR)) {
+			/* incoming command is an iovar */
+			/* pull out name\0param */
+			name = cmdbuf;
+			cmdlen = strlen(name);
+			param = ((char*)cmdbuf) + cmdlen + 1;
+			paramlen = len - cmdlen - 1;
+		} else {
+			/* we are an ioctl, invoke the common "ioc" iovar and wrap the cmd */
+			name = "ioc";
+			cmdlen = strlen(name);
+			/* additional 4 bytes for storing IOCTL_CMD_ID */
+			prefix_len = sizeof(int);
+			ioctl_wrap = TRUE;
+		}
+		prefix_len += strlen("wlc:") + 1 +  cmdlen + sizeof(int);
+		/* now create wlc:<name>\0<wlc_idx><param> */
+		buf = lbuf = malloc(prefix_len + paramlen);
+		if (buf == NULL) {
+			printf("%s:malloc(%d) failed\n", __FUNCTION__, prefix_len + paramlen);
+			return BCME_NOMEM;
+		}
+		memcpy(buf, "wlc:", 4); buf += 4;
+		strcpy(buf, name); buf += (cmdlen+1);
+		wlc_idx = htod32(wlc_idx);
+		memcpy(buf, &wlc_idx, sizeof(int32)); buf += sizeof(int32);
+		if (ioctl_wrap) {
+			/* For IOCTL wlc:ioc\0<wlc_idx><ioctl_id><param> */
+			int32 ioctl_cmd = htod32(*cmd);
+			memcpy(buf, &ioctl_cmd, sizeof(int32)); buf += sizeof(int32);
+		}
+		memcpy(buf, param, paramlen);
+		*cmd = (get) ? WLC_GET_VAR : WLC_SET_VAR;
+		param = lbuf;
+		paramlen += prefix_len;
+	}
+	*outlen = paramlen;
+	*outbuf = param;
+	return BCME_OK;
+}
+/* now IOCTL GET commands shall call wlu_get() instead of wl_get() so that the commands
+ * can be batched when needed
+ */
+int
+wlu_get(void *wl, int cmd, void *cmdbuf, int len)
+{
+	void *outbuf = NULL;
+	int outlen;
+	int err = 0;
+	if (cmd_batching_mode) {
+		if (!WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd)) {
+			printf("IOCTL GET command %d is not supported in batching mode\n", cmd);
+			return BCME_UNSUPPORTED;
+		}
+	}
+
+	err = wlu_wlc_wrapper(wl, TRUE, &cmd, cmdbuf, len, &outbuf, &outlen);
+	if (err != BCME_OK) return err;
+	err = wl_get(wl, cmd, outbuf, outlen);
+
+	if (outbuf != cmdbuf) {
+		memcpy(cmdbuf, outbuf, len);
+		free(outbuf);
+	}
+	return err;
+}
+
+/* now IOCTL SET commands shall call wlu_set() instead of wl_set() so that the commands
+ * can be batched when needed
+ */
+int
+wlu_set(void *wl, int cmd, void *cmdbuf, int len)
+{
+	int err = 0;
+	void *outbuf = NULL;
+	int outlen;
+
+	err = wlu_wlc_wrapper(wl, FALSE, &cmd, cmdbuf, len, &outbuf, &outlen);
+	if (err != BCME_OK) return err;
+
+	if (cmd_batching_mode) {
+		err = add_one_batched_cmd(cmd, outbuf, outlen);
+	}
+	else {
+		err = wl_set(wl, cmd, outbuf, outlen);
+	}
+	if (outbuf != cmdbuf) {
+		memcpy(cmdbuf, outbuf, len);
+		free(outbuf);
+	}
+	return err;
+
+}
+
+/*
+ * get named iovar providing both parameter and i/o buffers
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_getbuf(void* wl, const char *iovar,
+	void *param, int paramlen, void *bufptr, int buflen)
+{
+	int err;
+
+	wl_iovar_mkbuf(iovar, param, paramlen, bufptr, buflen, &err);
+	if (err)
+		return err;
+
+	return wlu_get(wl, WLC_GET_VAR, bufptr, buflen);
+}
+
+/*
+ * set named iovar providing both parameter and i/o buffers
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_setbuf(void* wl, const char *iovar,
+	void *param, int paramlen, void *bufptr, int buflen)
+{
+	int err;
+	int iolen;
+
+	iolen = wl_iovar_mkbuf(iovar, param, paramlen, bufptr, buflen, &err);
+	if (err)
+		return err;
+
+	return wlu_set(wl, WLC_SET_VAR, bufptr, iolen);
+}
+
+/*
+ * get named iovar without parameters into a given buffer
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_get(void *wl, const char *iovar, void *outbuf, int len)
+{
+	char smbuf[WLC_IOCTL_SMLEN];
+	int err;
+
+	/* use the return buffer if it is bigger than what we have on the stack */
+	if (len > (int)sizeof(smbuf)) {
+		err = wlu_iovar_getbuf(wl, iovar, NULL, 0, outbuf, len);
+	} else {
+		memset(smbuf, 0, sizeof(smbuf));
+		err = wlu_iovar_getbuf(wl, iovar, NULL, 0, smbuf, sizeof(smbuf));
+		if (err == 0)
+			memcpy(outbuf, smbuf, len);
+	}
+
+	return err;
+}
+
+/*
+ * set named iovar given the parameter buffer
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_set(void *wl, const char *iovar, void *param, int paramlen)
+{
+	char smbuf[WLC_IOCTL_SMLEN*2];
+
+	memset(smbuf, 0, sizeof(smbuf));
+
+	return wlu_iovar_setbuf(wl, iovar, param, paramlen, smbuf, sizeof(smbuf));
+}
+
+/*
+ * get named iovar as an integer value
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_getint(void *wl, const char *iovar, int *pval)
+{
+	int ret;
+
+	ret = wlu_iovar_get(wl, iovar, pval, sizeof(int));
+	if (ret >= 0)
+	{
+		*pval = dtoh32(*pval);
+	}
+	return ret;
+}
+
+/*
+ * set named iovar given an integer parameter
+ * iovar name is converted to lower case
+ */
+int
+wlu_iovar_setint(void *wl, const char *iovar, int val)
+{
+	val = htod32(val);
+	return wlu_iovar_set(wl, iovar, &val, sizeof(int));
+}
+/*
+ * Name lookup utility.
+ * Given a name table and an ID, will return the name matching the ID,
+ * or a string with the raw ID, i.e. "ID:<num>"
+ */
+const char* wlu_lookup_name(const wlu_name_entry_t* tbl, uint id)
+{
+	const wlu_name_entry_t *elt = tbl;
+	static char unknown[64];
+
+	for (elt = tbl; elt->name != NULL; elt++) {
+		if (id == elt->id)
+			return elt->name;
+	}
+	snprintf(unknown, sizeof(unknown), "ID:%d", id);
+	return unknown;
+}
diff --git a/wl/src/wl/exe/wlu_common.h b/wl/src/wl/exe/wlu_common.h
new file mode 100644
index 0000000..72e6630
--- /dev/null
+++ b/wl/src/wl/exe/wlu_common.h
@@ -0,0 +1,109 @@
+/*
+ * Common code for wl routines
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_common.h 649191 2016-07-15 06:30:56Z $
+ */
+#include <wlioctl.h>
+#include <bcmutils.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#if defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION >= 0x00020000)
+#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
+#define strtol(nptr, endptr, base)  (long)bcm_strtoul((nptr), (endptr), (base))
+#endif /* defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION >= 0x00020000) */
+
+#if defined(linux)
+
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+
+#elif	defined(_CRT_SECURE_NO_DEPRECATE) /* MSVC common runtime */
+
+#define stricmp _stricmp
+#define strnicmp _strnicmp
+
+#elif	defined(DONGLEBUILD)
+
+#define stricmp strcmp
+#define strnicmp strncmp
+
+#elif	defined(BWL_STRICMP)
+
+#define stricmp bcmstricmp
+#define strnicmp bcmstrnicmp
+
+#endif /* BWL_STRICMP */
+
+/* IOCTL swapping mode for Big Endian host with Little Endian dongle.  Default to off */
+/* The below macros handle endian mis-matches between wl utility and wl driver. */
+extern bool g_swap;
+#define htod64(i) (g_swap?bcmswap64(i):(uint64)(i))
+#define htod32(i) (g_swap?bcmswap32(i):(uint32)(i))
+#define htod16(i) (g_swap?bcmswap16(i):(uint16)(i))
+#define dtoh64(i) (g_swap?bcmswap64(i):(uint64)(i))
+#define dtoh32(i) (g_swap?bcmswap32(i):(uint32)(i))
+#define dtoh16(i) (g_swap?bcmswap16(i):(uint16)(i))
+#define htodchanspec(i) (g_swap?htod16(i):i)
+#define dtohchanspec(i) (g_swap?dtoh16(i):i)
+#define htodenum(i) (g_swap?((sizeof(i) == 4) ? htod32(i) : ((sizeof(i) == 2) ? htod16(i) : i)):i)
+#define dtohenum(i) (g_swap?((sizeof(i) == 4) ? dtoh32(i) : ((sizeof(i) == 2) ? htod16(i) : i)):i)
+
+/* command batching data structure */
+typedef struct wl_seq_cmd_pkt {
+	struct wl_seq_cmd_pkt	*next;
+	wl_seq_cmd_ioctl_t cmd_header;
+	char * data;			/* user buffer */
+} wl_seq_cmd_pkt_t;
+
+typedef struct wl_cmd_list {
+	wl_seq_cmd_pkt_t	*head;
+	wl_seq_cmd_pkt_t	*tail;
+} wl_cmd_list_t;
+
+/*
+ * Name table to associate strings with numeric IDs
+ */
+typedef struct wlu_name_entry {
+	uint id;
+	const char *name;
+} wlu_name_entry_t;
+
+extern wl_cmd_list_t cmd_list;
+extern int cmd_pkt_list_num;
+extern bool cmd_batching_mode;
+
+extern int wlu_iovar_getbuf(void* wl, const char *iovar,
+	void *param, int paramlen, void *bufptr, int buflen);
+extern int wlu_iovar_setbuf(void* wl, const char *iovar,
+	void *param, int paramlen, void *bufptr, int buflen);
+extern int wlu_var_setbuf(void *wl, const char *iovar, void *param, int param_len);
+extern int wlu_iovar_getint(void *wl, const char *iovar, int *pval);
+extern void init_cmd_batchingmode(void);
+extern void clean_up_cmd_list(void);
+extern int wl_check(void *wl);
+
+extern int add_one_batched_cmd(int cmd, void *cmdbuf, int len);
+extern int wlu_get_req_buflen(int cmd, void *cmdbuf, int len);
+extern int wlu_get(void *wl, int cmd, void *cmdbuf, int len);
+extern int wlu_set(void *wl, int cmd, void *cmdbuf, int len);
+extern int wlu_iovar_get(void *wl, const char *iovar, void *outbuf, int len);
+extern int wlu_iovar_set(void *wl, const char *iovar, void *param, int paramlen);
+extern int wlu_iovar_getint(void *wl, const char *iovar, int *pval);
+extern int wlu_iovar_setint(void *wl, const char *iovar, int val);
+extern const char* wlu_lookup_name(const wlu_name_entry_t* tbl, uint id);
diff --git a/wl/src/wl/exe/wlu_iov.c b/wl/src/wl/exe/wlu_iov.c
new file mode 100644
index 0000000..b4822f9
--- /dev/null
+++ b/wl/src/wl/exe/wlu_iov.c
@@ -0,0 +1,32 @@
+/*
+ * Automatically generated IOVariable merge information
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_iov.c 572826 2015-07-21 03:59:03Z $
+ *
+ * Contains user IO variable information
+ * Note that variable type information comes from the driver
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <typedefs.h>
+#include <bcmutils.h>
+#include <wlioctl.h>
+
+#include "wlu.h"
diff --git a/wl/src/wl/exe/wlu_linux.c b/wl/src/wl/exe/wlu_linux.c
new file mode 100644
index 0000000..79c4e16
--- /dev/null
+++ b/wl/src/wl/exe/wlu_linux.c
@@ -0,0 +1,1049 @@
+/*
+ * Linux port of wl command line utility
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_linux.c 659591 2016-09-15 03:19:00Z $
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#ifndef TARGETENV_android
+#include <error.h>
+#endif /* TARGETENV_android */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <proto/ethernet.h>
+#include <proto/bcmip.h>
+
+#ifndef TARGETENV_android
+#include <linux/types.h>
+#endif /* TARGETENV_android */
+
+#include <linux/sockios.h>
+#include <linux/ethtool.h>
+#include <signal.h>
+#include <typedefs.h>
+#include <wlioctl.h>
+#include <bcmutils.h>
+#include <sys/wait.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include "wlu.h"
+#include <bcmcdc.h>
+#include "wlu_remote.h"
+#include "wlu_client_shared.h"
+#include "wlu_pipe.h"
+#ifdef NL80211
+#include "wlu_nl80211.h"
+#endif /* NL80211 */
+#include <miniopt.h>
+
+#define DEV_TYPE_LEN					3 /* length for devtype 'wl'/'et' */
+#define INTERACTIVE_NUM_ARGS			15
+#define INTERACTIVE_MAX_INPUT_LENGTH	512
+#define NO_ERROR						0
+#define RWL_WIFI_JOIN_DELAY				5
+
+/* Function prototypes */
+static cmd_t *wl_find_cmd(char* name);
+static int do_interactive(struct ifreq *ifr);
+static int wl_do_cmd(struct ifreq *ifr, char **argv);
+int process_args(struct ifreq* ifr, char **argv);
+extern int g_child_pid;
+/* RemoteWL declarations */
+int remote_type = NO_REMOTE;
+int rwl_os_type = LINUX_OS;
+static bool rwl_dut_autodetect = TRUE;
+static bool debug = FALSE;
+extern char *g_rwl_buf_mac;
+extern char* g_rwl_device_name_serial;
+extern int g_rwl_device_baud;
+unsigned short g_rwl_servport;
+char *g_rwl_servIP = NULL;
+unsigned short defined_debug = DEBUG_ERR | DEBUG_INFO;
+static uint interactive_flag = 0;
+extern char *remote_vista_cmds[];
+extern char g_rem_ifname[IFNAMSIZ];
+extern int rwl_check_port_number(char *s, int len);
+
+#ifdef NL80211
+static void
+syserr(char *s)
+{
+	UNUSED_PARAMETER(s);
+}
+
+static int wl_driver_nl80211(void *wl, wl_ioctl_t *ioc)
+{
+	struct wl_netlink_info wl_nli;
+	struct ifreq *ifr = (struct ifreq *)wl;
+	int ret = 0;
+
+	wl_nli.ifidx = if_nametoindex(ifr->ifr_name);
+	if (!wl_nli.ifidx) {
+		fprintf(stderr, "invalid device %s\n", ifr->ifr_name);
+		return BCME_IOCTL_ERROR;
+	}
+
+	if (wlnl_sock_connect(&wl_nli) < 0) {
+		fprintf(stderr, "%s: ", wlu_av0);
+		perror("socket");
+		exit(errno);
+	}
+
+	ret = wlnl_do_vndr_cmd(&wl_nli, ioc);
+	wlnl_sock_disconnect(&wl_nli);
+	return ret;
+}
+#else
+static void
+syserr(char *s)
+{
+	fprintf(stderr, "%s: ", wlu_av0);
+	perror(s);
+	exit(errno);
+}
+
+static int wl_driver_nl80211(void *wl, wl_ioctl_t *ioc)
+{
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(ioc);
+	return BCME_IOCTL_ERROR;
+}
+#endif /* NL80211 */
+
+static int wl_driver_ioctl(void *wl, wl_ioctl_t *ioc)
+{
+	struct ifreq *ifr = (struct ifreq *) wl;
+	int ret;
+	int s;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	/* do it */
+	ifr->ifr_data = (caddr_t)ioc;
+	ret = ioctl(s, SIOCDEVPRIVATE, ifr);
+
+	/* cleanup */
+	close(s);
+	return ret;
+}
+
+static int (*g_driver_io)(void *wl, wl_ioctl_t *ioc) = wl_driver_ioctl;
+int
+wl_ioctl(void *wl, int cmd, void *buf, int len, bool set)
+{
+	wl_ioctl_t ioc;
+	int ret;
+
+	/* do it */
+	ioc.cmd = cmd;
+	ioc.buf = buf;
+	ioc.len = len;
+	ioc.set = set;
+
+	ret = g_driver_io(wl, &ioc);
+	if ((cmd == WLC_GET_MAGIC) && (ret < 0)) {
+		if (g_driver_io == wl_driver_ioctl) {
+			/* try using nl80211 testmode interface */
+			ret = wl_driver_nl80211(wl, &ioc);
+			if (ret >= 0) {
+				g_driver_io = wl_driver_nl80211;
+				goto exit;
+			}
+		}
+	} else if (ret < 0) {
+		ret = BCME_IOCTL_ERROR;
+	}
+
+exit:
+	return ret;
+}
+
+static int
+wl_get_dev_type(char *name, void *buf, int len)
+{
+	int s;
+	int ret;
+	struct ifreq ifr;
+	struct ethtool_drvinfo info;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	memset(&ifr, 0, sizeof(ifr));
+
+	/* get device type */
+	memset(&info, 0, sizeof(info));
+	info.cmd = ETHTOOL_GDRVINFO;
+	ifr.ifr_data = (caddr_t)&info;
+	strncpy(ifr.ifr_name, name, IFNAMSIZ - 1);
+	ifr.ifr_name[IFNAMSIZ-1] = 0;
+	if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
+
+		/* print a good diagnostic if not superuser */
+		if (errno == EPERM)
+			syserr("wl_get_dev_type");
+
+		*(char *)buf = '\0';
+	} else {
+		strncpy(buf, info.driver, len);
+	}
+
+	close(s);
+	return ret;
+}
+
+static int
+wl_find(struct ifreq *ifr)
+{
+	char proc_net_dev[] = "/proc/net/dev";
+	FILE *fp;
+	char buf[1000], *c, *name;
+	char dev_type[DEV_TYPE_LEN];
+	int status;
+
+	ifr->ifr_name[0] = '\0';
+
+	if (!(fp = fopen(proc_net_dev, "r")))
+		return BCME_ERROR;
+
+	/* eat first two lines */
+	if (!fgets(buf, sizeof(buf), fp) ||
+	    !fgets(buf, sizeof(buf), fp)) {
+		fclose(fp);
+		return BCME_ERROR;
+	}
+
+	while (fgets(buf, sizeof(buf), fp)) {
+		c = buf;
+		while (isspace(*c))
+			c++;
+		if (!(name = strsep(&c, ":")))
+			continue;
+		strncpy(ifr->ifr_name, name, IFNAMSIZ-1);
+		ifr->ifr_name[IFNAMSIZ-1] = 0;
+
+		/*
+		 * If no -i interface, prioritize ethX, not say wl1.2
+		 * wlanX is Android
+		 */
+		if (!strncmp(name, "wl", 2) && strncmp(name, "wlan", 4)) {
+			continue;
+		}
+
+		if (wl_get_dev_type(name, dev_type, DEV_TYPE_LEN) >= 0 &&
+			(!strncmp(dev_type, "wl", 2) ||
+			!strncmp(dev_type, "brc", 3)))
+			if (wl_check((void *) ifr) == 0)
+				break;
+		ifr->ifr_name[0] = '\0';
+	}
+	if (ifr->ifr_name[0] == '\0')
+		status = BCME_ERROR;
+	else
+		status = BCME_OK;
+
+	fclose(fp);
+	return status;
+}
+
+
+static int
+ioctl_queryinformation_fe(void *wl, int cmd, void* input_buf, unsigned long *input_len)
+{
+	int error = NO_ERROR;
+
+	if (remote_type == NO_REMOTE) {
+		error = wl_ioctl(wl, cmd, input_buf, *input_len, FALSE);
+	} else {
+		error = rwl_queryinformation_fe(wl, cmd, input_buf,
+		              input_len, 0, REMOTE_GET_IOCTL);
+
+	}
+	return error;
+}
+
+static int
+ioctl_setinformation_fe(void *wl, int cmd, void* buf, unsigned long *input_len)
+{
+	int error = 0;
+
+	if (remote_type == NO_REMOTE) {
+		error = wl_ioctl(wl,  cmd, buf, *input_len, TRUE);
+	} else {
+		error = rwl_setinformation_fe(wl, cmd, buf,
+			input_len, 0, REMOTE_SET_IOCTL);
+	}
+
+	return error;
+}
+
+int
+wl_get(void *wl, int cmd, void *buf, int len)
+{
+	int error = 0;
+	unsigned long input_len = len;
+
+	if ((rwl_os_type == WIN32_OS || rwl_os_type == WINVISTA_OS) && remote_type != NO_REMOTE)
+		cmd += WL_OID_BASE;
+	error = (int)ioctl_queryinformation_fe(wl, cmd, buf, &input_len);
+
+	if (error == BCME_SERIAL_PORT_ERR)
+		return BCME_SERIAL_PORT_ERR;
+	else if (error == BCME_NODEVICE)
+		return BCME_NODEVICE;
+	else if (error != 0)
+		return BCME_IOCTL_ERROR;
+
+	return 0;
+}
+
+int
+wl_set(void *wl, int cmd, void *buf, int len)
+{
+	int error = 0;
+	unsigned long input_len = len;
+
+	if ((rwl_os_type == WIN32_OS || rwl_os_type == WINVISTA_OS) && remote_type != NO_REMOTE)
+		cmd += WL_OID_BASE;
+	error = (int)ioctl_setinformation_fe(wl, cmd, buf, &input_len);
+
+	if (error == BCME_SERIAL_PORT_ERR)
+		return BCME_SERIAL_PORT_ERR;
+	else if (error == BCME_NODEVICE)
+		return BCME_NODEVICE;
+	else if (error != 0)
+		return BCME_IOCTL_ERROR;
+
+	return 0;
+}
+
+#if defined(WLMSO)
+int wl_os_type_get_rwl()
+{
+	return rwl_os_type;
+}
+
+void wl_os_type_set_rwl(int os_type)
+{
+	rwl_os_type = os_type;
+}
+
+int wl_ir_init_rwl(void **irh)
+{
+	switch (rwl_get_remote_type()) {
+	case NO_REMOTE:
+	case REMOTE_WIFI: {
+		struct ifreq *ifr;
+		ifr = malloc(sizeof(struct ifreq));
+		if (ifr) {
+			memset(ifr, 0, sizeof(ifr));
+			wl_find(ifr);
+		}
+		*irh = ifr;
+	}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+void wl_close_rwl(int remote_type, void *irh)
+{
+	switch (remote_type) {
+	case NO_REMOTE:
+	case REMOTE_WIFI:
+		free(irh);
+		break;
+	default:
+		break;
+	}
+}
+
+#define LINUX_NUM_ARGS  16
+
+static int
+buf_to_args(char *tmp, char *new_args[])
+{
+	char line[INTERACTIVE_MAX_INPUT_LENGTH];
+	char *token;
+	int argc = 0;
+
+	if (strlen(tmp) >= INTERACTIVE_MAX_INPUT_LENGTH) {
+		printf("wl:error: Input string too long; must be < %d bytes\n",
+		       INTERACTIVE_MAX_INPUT_LENGTH);
+		return 0;
+	}
+
+	strcpy(line, tmp);
+	while  (argc < (LINUX_NUM_ARGS - 1) &&
+		(token = strtok(argc ? NULL : line, " \t")) != NULL) {
+		new_args[argc] = malloc(strlen(token)+1);
+		strncpy(new_args[argc], token, strlen(token)+1);
+		argc++;
+	}
+	new_args[argc] = NULL;
+	if (argc == (LINUX_NUM_ARGS - 1) && (token = strtok(NULL, " \t")) != NULL) {
+		printf("wl:error: too many args; argc must be < %d\n",
+		       (LINUX_NUM_ARGS - 1));
+		argc = LINUX_NUM_ARGS;
+	}
+	return argc;
+}
+
+int
+wl_lib(char *input_str)
+{
+	struct ifreq ifr;
+	char *ifname = NULL;
+	int err = 0;
+	int help = 0;
+	int status = CMD_WL;
+	void* serialHandle = NULL;
+	char *tmp_argv[LINUX_NUM_ARGS];
+	char **argv = tmp_argv;
+	int argc;
+
+	/* buf_to_args return 0 if no args or string too long
+	 * or return NDIS_NUM_ARGS if too many args
+	 */
+	if (((argc = buf_to_args(input_str, argv)) == 0) || (argc == LINUX_NUM_ARGS)) {
+		printf("wl:error: can't convert input string\n");
+		return (-1);
+	}
+#else
+/* Main client function */
+int
+main(int argc, char **argv)
+{
+	struct ifreq ifr;
+	char *ifname = NULL;
+	int err = 0;
+	int help = 0;
+	int status = CMD_WL;
+#if defined(RWL_DONGLE) || RWL_SERIAL
+	void* serialHandle = NULL;
+#endif
+
+#endif /* WLMSO */
+	wlu_av0 = argv[0];
+
+	wlu_init();
+	memset(&ifr, 0, sizeof(ifr));
+	(void)*argv++;
+
+	if ((status = wl_option(&argv, &ifname, &help)) == CMD_OPT) {
+		if (ifname)
+			strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+		/* Bug fix: If -h is used as an option, the above function call
+		 * will notice it and raise the flag but it won't be processed
+		 * in this function so we undo the argv increment so that the -h
+		 * can be spotted by the next call of wl_option. This will ensure
+		 * that wl -h [cmd] will function as desired.
+		 */
+		else if (help)
+			(void)*argv--;
+	}
+
+	/* Linux client looking for a indongle reflector */
+	if (*argv && strncmp (*argv, "--indongle", strlen(*argv)) == 0) {
+		rwl_dut_autodetect = FALSE;
+		(void)*argv++;
+	}
+	/* Linux client looking for a WinVista server */
+	if (*argv && strncmp (*argv, "--vista", strlen(*argv)) == 0) {
+		rwl_os_type = WINVISTA_OS;
+		rwl_dut_autodetect = FALSE;
+		(void)*argv++;
+	}
+
+	/* Provide option for disabling remote DUT autodetect */
+	if (*argv && strncmp(*argv, "--nodetect", strlen(*argv)) == 0) {
+		rwl_dut_autodetect = FALSE;
+		argv++;
+	}
+
+	if (*argv && strncmp (*argv, "--debug", strlen(*argv)) == 0) {
+		debug = TRUE;
+		argv++;
+	}
+
+	/* RWL socket transport Usage: --socket ipaddr/hostname [port num] */
+	if (*argv && strncmp (*argv, "--socket", strlen(*argv)) == 0) {
+		(void)*argv++;
+
+		remote_type = REMOTE_SOCKET;
+
+		if (!(*argv)) {
+			rwl_usage(remote_type);
+			return err;
+		}
+		/* IP address validation is done in client_shared file */
+		g_rwl_servIP = *argv;
+		(void)*argv++;
+
+		/* Port number validation is done in client_shared file */
+		g_rwl_servport = DEFAULT_SERVER_PORT;
+		if ((*argv) && (rwl_check_port_number(*argv, strlen(*argv)) == SUCCESS)) {
+			g_rwl_servport = atoi(*argv);
+			(void)*argv++;
+		}
+	}
+
+	/* RWL from system serial port on client to uart serial port on server */
+	/* Usage: --serial /dev/ttyS0 [--baud 115200] */
+	if (*argv && strncmp (*argv, "--serial", strlen(*argv)) == 0) {
+		(void)*argv++;
+		remote_type = REMOTE_SERIAL;
+	}
+
+	/* RWL from system serial port on client to uart dongle port on server */
+	/* Usage: --dongle /dev/ttyS0 [--baud 115200] */
+	if (*argv && strncmp (*argv, "--dongle", strlen(*argv)) == 0) {
+		(void)*argv++;
+		remote_type = REMOTE_DONGLE;
+	}
+
+#if defined(RWL_SERIAL) || defined(RWL_DONGLE)
+	if (remote_type == REMOTE_SERIAL || remote_type == REMOTE_DONGLE) {
+		if (!(*argv)) {
+			rwl_usage(remote_type);
+			return err;
+		}
+		g_rwl_device_name_serial = *argv;
+		(void)*argv++;
+		if (*argv && strncmp (*argv, "--baud", strlen(*argv)) == 0) {
+			(void)*argv++;
+			if ((*argv) && (rwl_check_port_number(*argv, strlen(*argv)) == SUCCESS)) {
+				g_rwl_device_baud = atoi(*argv);
+				(void)*argv++;
+			}
+		}
+		if ((serialHandle = rwl_open_pipe(remote_type, g_rwl_device_name_serial, 0, 0))
+			 == NULL) {
+			DPRINT_ERR(ERR, "serial device open error\r\n");
+			return -1;
+		}
+		ifr = (*(struct ifreq *)serialHandle);
+	}
+#endif /*  RWL_SERIAL */
+
+	/* RWL over wifi.  Usage: --wifi mac_address */
+	if (*argv && strncmp (*argv, "--wifi", strlen(*argv)) == 0) {
+		(void)*argv++;
+		/* use default interface */
+		if (!*ifr.ifr_name)
+			wl_find(&ifr);
+
+		/* validate the interface */
+		if (!*ifr.ifr_name || (err = wl_check((void *)&ifr)) < 0) {
+			fprintf(stderr, "%s: wl driver adapter not found\n", wlu_av0);
+			exit(1);
+		}
+
+		remote_type = REMOTE_WIFI;
+
+		if (argc < 4) {
+			rwl_usage(remote_type);
+			return err;
+		}
+		/* copy server mac address to local buffer for later use by findserver cmd */
+		if (!wl_ether_atoe(*argv, (struct ether_addr *)g_rwl_buf_mac)) {
+			fprintf(stderr,
+			"could not parse as an ethternet MAC address\n");
+			return FAIL;
+		}
+		(void)*argv++;
+	}
+
+	if ((*argv) && (strlen(*argv) > 2) &&
+		(strncmp(*argv, "--interactive", strlen(*argv)) == 0)) {
+		interactive_flag = 1;
+	}
+
+	/* Process for local wl */
+	if (remote_type == NO_REMOTE) {
+		if (*argv && strncmp (*argv, "-h", strlen(*argv)) == 0) {
+			wl_usage(stdout, NULL); /* outputs multiple screens of help information */
+			return err;
+		}
+
+		if (interactive_flag == 1)
+			(void)*argv--;
+		err = process_args(&ifr, argv);
+		return err;
+	} else {
+#ifndef OLYMPIC_RWL
+		/* Autodetect remote DUT */
+		if (rwl_dut_autodetect == TRUE)
+			rwl_detect((void*)&ifr, debug, &rwl_os_type);
+#endif /* OLYMPIC_RWL */
+	}
+
+	/* RWL client needs to initialize ioctl_version */
+	if (wl_check((void *)&ifr) != 0) {
+		fprintf(stderr, "%s: wl driver adapter not found\n", wlu_av0);
+			exit(1);
+	}
+
+	if (interactive_flag == 1) {
+		err = do_interactive(&ifr);
+		return err;
+	}
+
+	if ((*argv) && (interactive_flag == 0)) {
+		err = process_args(&ifr, argv);
+		if ((err == BCME_SERIAL_PORT_ERR) && (remote_type == REMOTE_DONGLE)) {
+			DPRINT_ERR(ERR, "\n Retry again\n");
+			err = process_args((struct ifreq*)&ifr, argv);
+		}
+		return err;
+	}
+	rwl_usage(remote_type);
+#if defined(RWL_DONGLE) || RWL_SERIAL
+	if (remote_type == REMOTE_DONGLE || remote_type == REMOTE_SERIAL)
+		rwl_close_pipe(remote_type, (void*)&ifr);
+#endif /* RWL_DONGLE || RWL_SERIAL */
+	return err;
+}
+
+/*
+ * Function called for  'local' execution and for 'remote' non-interactive session
+ * (shell cmd, wl cmd)
+ */
+int
+process_args(struct ifreq* ifr, char **argv)
+{
+	char *ifname = NULL;
+	int help = 0;
+	int status = 0;
+	int vista_cmd_index;
+	int err = 0;
+	cmd_t *cmd = NULL;
+#ifdef RWL_WIFI
+	int retry;
+#endif
+
+	while (*argv) {
+		if ((strcmp (*argv, "sh") == 0) && (remote_type != NO_REMOTE)) {
+			(void)*argv++; /* Get the shell command */
+			if (*argv) {
+				/* Register handler in case of shell command only */
+				err = rwl_shell_cmd_proc((void*)ifr, argv, SHELL_CMD);
+			} else {
+				DPRINT_ERR(ERR, "Enter the shell "
+				           "command, e.g. ls(Linux) or dir(Win CE)\n");
+				err = -1;
+			}
+			return err;
+		}
+
+#ifdef RWLASD
+		if ((strcmp (*argv, "asd") == 0) && (remote_type != NO_REMOTE)) {
+			(void)*argv++; /* Get the asd command */
+			if (*argv) {
+				err = rwl_shell_cmd_proc((void*)ifr, argv, ASD_CMD);
+			} else {
+				DPRINT_ERR(ERR, "Enter the ASD command, e.g. ca_get_version\n");
+				err = -1;
+			}
+			return err;
+		}
+#endif
+		if (rwl_os_type == WINVISTA_OS) {
+			for (vista_cmd_index = 0; remote_vista_cmds[vista_cmd_index] &&
+				strcmp(remote_vista_cmds[vista_cmd_index], *argv);
+				vista_cmd_index++);
+			if (remote_vista_cmds[vista_cmd_index] != NULL) {
+				err = rwl_shell_cmd_proc((void *)ifr, argv, VISTA_CMD);
+				if ((remote_type == REMOTE_WIFI) && ((!strcmp(*argv, "join")))) {
+#ifdef RWL_WIFI
+					DPRINT_INFO(OUTPUT,
+						"\nChannel will be synchronized by Findserver\n\n");
+					sleep(RWL_WIFI_JOIN_DELAY);
+					for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+						if ((rwl_find_remote_wifi_server(ifr,
+							&g_rwl_buf_mac[0]) == 0)) {
+						break;
+					}
+				}
+#endif /* RWL_WIFI */
+			}
+			return err;
+			}
+		}
+
+		if ((status = wl_option(&argv, &ifname, &help)) == CMD_OPT) {
+			if (help)
+				break;
+			if (ifname) {
+				if (remote_type == NO_REMOTE) {
+					strncpy((*ifr).ifr_name, ifname, IFNAMSIZ);
+				}
+				else {
+					strncpy(g_rem_ifname, ifname, IFNAMSIZ);
+				}
+			}
+			continue;
+		}
+		/* parse error */
+		else if (status == CMD_ERR)
+			break;
+
+		if (remote_type == NO_REMOTE) {
+			/* use default interface */
+			if (!*(*ifr).ifr_name)
+				wl_find(ifr);
+
+			/* validate the interface */
+			if (!*(*ifr).ifr_name || (err = wl_check((void *)ifr)) < 0) {
+				fprintf(stderr, "%s: wl driver adapter not found\n", wlu_av0);
+				exit(1);
+			}
+
+			if ((strcmp (*argv, "--interactive") == 0) || (interactive_flag == 1)) {
+				err = do_interactive(ifr);
+				return err;
+			}
+		 }
+		/* search for command */
+		cmd = wl_find_cmd(*argv);
+		/* if not found, use default set_var and get_var commands */
+		if (!cmd) {
+			cmd = &wl_varcmd;
+		}
+#ifdef RWL_WIFI
+		if (!strcmp(cmd->name, "findserver")) {
+			remote_wifi_ser_init_cmds((void *) ifr);
+		}
+#endif /* RWL_WIFI */
+
+		/* RWL over Wifi supports 'lchannel' command which lets client
+		 * (ie *this* machine) change channels since normal 'channel' command
+		 * applies to the server (ie target machine)
+		 */
+		if (remote_type == REMOTE_WIFI)	{
+#ifdef RWL_WIFI
+			if (!strcmp(argv[0], "lchannel")) {
+				strcpy(argv[0], "channel");
+				rwl_wifi_swap_remote_type(remote_type);
+				err = (*cmd->func)((void *) ifr, cmd, argv);
+				rwl_wifi_swap_remote_type(remote_type);
+			} else {
+				err = (*cmd->func)((void *) ifr, cmd, argv);
+			}
+			/* After join cmd's gets exeuted on the server side , client needs to know
+			* the channel on which the server is associated with AP , after delay of
+			* few seconds client will intiate the scan on diffrent channels by calling
+			* rwl_find_remote_wifi_server fucntion
+			*/
+			if ((!strcmp(cmd->name, "join") || ((!strcmp(cmd->name, "ssid") &&
+				(*(++argv) != NULL))))) {
+				DPRINT_INFO(OUTPUT, "\n Findserver is called to synchronize the"
+				"channel\n\n");
+				sleep(RWL_WIFI_JOIN_DELAY);
+				for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+					if ((rwl_find_remote_wifi_server(ifr,
+					&g_rwl_buf_mac[0]) == 0)) {
+						break;
+					}
+				}
+			}
+#endif /* RWL_WIFI */
+		} else {
+			/* do command */
+			err = (*cmd->func)((void *) ifr, cmd, argv);
+		}
+		break;
+	} /* while loop end */
+
+	/* provide for help on a particular command */
+	if (help && *argv) {
+		cmd = wl_find_cmd(*argv);
+		if (cmd) {
+			wl_cmd_usage(stdout, cmd);
+		} else {
+			DPRINT_ERR(ERR, "%s: Unrecognized command \"%s\", type -h for help\n",
+			                                                          wlu_av0, *argv);
+		}
+	} else if (!cmd) {
+		fprintf(stderr, "type -h for help\n");
+	} else if (err == BCME_USAGE_ERROR) {
+		wl_cmd_usage(stderr, cmd);
+	} else if (err == BCME_IOCTL_ERROR) {
+		wl_printlasterror((void *) ifr);
+	} else if (err == BCME_BADARG) {
+		DPRINT_ERR(ERR, "One or more parameters have invalid values\n");
+	} else if (err == BCME_NODEVICE) {
+		DPRINT_ERR(ERR, "%s : wl driver adapter not found\n", g_rem_ifname);
+	} else if (err) {
+		DPRINT_ERR(ERR, "error\n");
+	}
+
+	return err;
+}
+
+/* Function called for 'local' interactive session and for 'remote' interactive session */
+static int
+do_interactive(struct ifreq *ifr)
+{
+	int err = 0;
+
+#ifdef RWL_WIFI
+	int retry;
+#endif
+
+	while (1) {
+		char *fgsret;
+		char line[INTERACTIVE_MAX_INPUT_LENGTH];
+		fprintf(stdout, "> ");
+		fgsret = fgets(line, sizeof(line), stdin);
+
+		/* end of file */
+		if (fgsret == NULL)
+			break;
+		if (line[0] == '\n')
+			continue;
+
+		if (strlen (line) > 0) {
+			/* skip past first arg if it's "wl" and parse up arguments */
+			char *argv[INTERACTIVE_NUM_ARGS];
+			int argc;
+			char *token;
+			argc = 0;
+
+			while (argc < (INTERACTIVE_NUM_ARGS - 1) &&
+			       (token = strtok(argc ? NULL : line, " \t\n")) != NULL) {
+
+				/* Specifically make sure empty arguments (like SSID) are empty */
+				if (token[0] == '"' && token[1] == '"') {
+				    token[0] = '\0';
+				}
+
+				argv[argc++] = token;
+			}
+			argv[argc] = NULL;
+			if (argc == (INTERACTIVE_NUM_ARGS - 1) &&
+			    (token = strtok(NULL, " \t")) != NULL) {
+				printf("wl:error: too many args; argc must be < %d\n",
+				       (INTERACTIVE_NUM_ARGS - 1));
+				continue;
+			}
+#ifdef RWL_WIFI
+		if (!strcmp(argv[0], "findserver")) {
+			remote_wifi_ser_init_cmds((void *) ifr);
+		}
+#endif /* RWL_WIFI */
+
+			if (strcmp(argv[0], "q") == 0 || strcmp(argv[0], "exit") == 0) {
+				break;
+			}
+
+			if ((strcmp(argv[0], "sh") == 0) && (remote_type != NO_REMOTE))  {
+				if (argv[1]) {
+					process_args(ifr, argv);
+				} else {
+					DPRINT_ERR(ERR, "Give shell command");
+					continue;
+				}
+			} else { /* end shell */
+				/* check for lchannel support,applicable only for wifi transport.
+				* when lchannel is called remote type is swapped by calling swap_
+				* remote_type.This is done to change, the remote type to local,
+				* so that local machine's channel can be executed and
+				* returned to the user.
+				* To get back the original remote type, swap is recalled.
+				*/
+				if (remote_type == REMOTE_WIFI) {
+#ifdef RWL_WIFI
+					if (!strcmp(argv[0], "lchannel")) {
+						strcpy(argv[0], "channel");
+						rwl_wifi_swap_remote_type(remote_type);
+						err = wl_do_cmd(ifr, argv);
+						rwl_wifi_swap_remote_type(remote_type);
+					} else {
+						err = wl_do_cmd(ifr, argv);
+					}
+				/* After join cmd's gets exeuted on the server side, client
+				 * needs to know the channel on which the server is associated
+				 * with AP , after delay of few seconds client will intiate the
+				 * scan on diffrent channels by calling
+				 * rwl_find_remote_wifi_server function
+				 */
+					if ((!strcmp(argv[0], "join")) ||
+						(!strcmp(argv[0], "ssid"))) {
+						DPRINT_INFO(OUTPUT, "\n Findserver is called"
+						"after the join issued to remote \n \n");
+						sleep(RWL_WIFI_JOIN_DELAY);
+						for (retry = 0; retry < RWL_WIFI_RETRY; retry++) {
+							if ((rwl_find_remote_wifi_server(ifr,
+							&g_rwl_buf_mac[0]) == 0)) {
+								break;
+							}
+						}
+					}
+#endif /* RWL_WIFI */
+				} else {
+					err = wl_do_cmd(ifr, argv);
+				}
+			} /* end of wl */
+		} /* end of strlen (line) > 0 */
+	} /* while (1) */
+
+	return err;
+}
+
+/*
+ * find command in argv and execute it
+ * Won't handle changing ifname yet, expects that to happen with the --interactive
+ * Return an error if unable to find/execute command
+ */
+static int
+wl_do_cmd(struct ifreq *ifr, char **argv)
+{
+	cmd_t *cmd = NULL;
+	int err = 0;
+	int help = 0;
+	char *ifname = NULL;
+	int status = CMD_WL;
+
+	/* skip over 'wl' if it's there */
+	if (*argv && strcmp (*argv, "wl") == 0) {
+		argv++;
+	}
+
+	/* handle help or interface name changes */
+	if (*argv && (status = wl_option (&argv, &ifname, &help)) == CMD_OPT) {
+		if (ifname) {
+			fprintf(stderr,
+			        "Interface name change not allowed within --interactive\n");
+		}
+	}
+
+	/* in case wl_option eats all the args */
+	if (!*argv) {
+		return err;
+	}
+
+	if (status != CMD_ERR) {
+		/* search for command */
+		cmd = wl_find_cmd(*argv);
+
+		/* defaults to using the set_var and get_var commands */
+		if (!cmd) {
+			cmd = &wl_varcmd;
+		}
+		/* do command */
+		err = (*cmd->func)((void *)ifr, cmd, argv);
+	}
+
+	if (help) {
+		if (*argv) {
+			/* provide for help on a particular command */
+			cmd = wl_find_cmd(*argv);
+			if (cmd) {
+				wl_cmd_usage(stdout, cmd);
+			} else {
+				DPRINT_ERR(ERR, "%s: Unrecognized command \"%s\", "
+						"type -h for help\n", wlu_av0, *argv);
+			}
+		} else {
+			wl_usage(stdout, NULL); /* outputs multiple screens of help information */
+		}
+	} else if (err == BCME_USAGE_ERROR)
+		wl_cmd_usage(stderr, cmd);
+	else if (err == BCME_IOCTL_ERROR)
+		wl_printlasterror((void *)ifr);
+	else if (err == BCME_NODEVICE)
+		DPRINT_ERR(ERR, "%s : wl driver adapter not found\n", g_rem_ifname);
+
+	return err;
+}
+
+/* Search the wl_cmds table for a matching command name.
+ * Return the matching command or NULL if no match found.
+ */
+static cmd_t *
+wl_find_cmd(char* name)
+{
+	return wlu_find_cmd(name);
+}
+
+void def_handler(int signum)
+{
+	UNUSED_PARAMETER(signum);
+	kill(g_child_pid, SIGINT);
+	kill(getpid(), SIGINT);
+	exit(0);
+}
+/* Create a child that waits for Ctrl-C at the client side
+ */
+int rwl_shell_createproc(void *wl)
+{
+	UNUSED_PARAMETER(wl);
+	signal(SIGINT, ctrlc_handler);
+	signal(SIGTERM, def_handler);
+	signal(SIGABRT, def_handler);
+	return fork();
+}
+
+/* In case if the server shell command exits normally
+ * then kill the thread that was waiting for Ctr-C to happen
+ * at the client side
+ */
+void rwl_shell_killproc(int pid)
+{
+	kill(pid, SIGKILL);
+	signal(SIGINT, SIG_DFL);
+	wait(NULL);
+}
+#ifdef RWL_SOCKET
+/* to validate hostname/ip given by the client */
+int validate_server_address()
+{
+	struct hostent *he;
+	struct ipv4_addr temp;
+	if (!wl_atoip(g_rwl_servIP, &temp)) {
+	/* Wrong IP address format check for hostname */
+		if ((he = gethostbyname(g_rwl_servIP)) != NULL) {
+			if (!wl_atoip(*he->h_addr_list, &temp)) {
+				g_rwl_servIP =
+				inet_ntoa(*(struct in_addr *)*he->h_addr_list);
+				if (g_rwl_servIP == NULL) {
+					DPRINT_ERR(ERR, "Error at inet_ntoa \n");
+					return FAIL;
+				}
+			} else {
+				DPRINT_ERR(ERR, "Error in IP address \n");
+				return FAIL;
+			}
+		} else {
+			DPRINT_ERR(ERR, "Enter correct IP address/hostname format\n");
+			return FAIL;
+		}
+	}
+	return SUCCESS;
+}
+#endif /* RWL_SOCKET */
diff --git a/wl/src/wl/exe/wlu_nl80211.c b/wl/src/wl/exe/wlu_nl80211.c
new file mode 100644
index 0000000..0587aad
--- /dev/null
+++ b/wl/src/wl/exe/wlu_nl80211.c
@@ -0,0 +1,210 @@
+/*
+ * nl80211 linux driver interface.
+ *
+ * Copyright (C) 2017, Broadcom. 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: $
+ */
+#include <errno.h>
+#include <linux/nl80211.h>
+#include <wlioctl.h>
+#include <brcm_nl80211.h>
+#include "wlu_nl80211.h"
+
+static struct nla_policy wl_nl_policy[BCM_NLATTR_MAX + 1] = {
+	[BCM_NLATTR_LEN] = { .type = NLA_U16 },
+	[BCM_NLATTR_DATA] = { .type = NLA_UNSPEC },
+};
+
+/* libnl 1.x compatibility code */
+#if !defined(CONFIG_LIBNL20) && !defined(CONFIG_LIBNL30)
+static inline struct nl_handle *nl_socket_alloc(void)
+{
+	return nl_handle_alloc();
+}
+
+static inline void nl_socket_free(struct nl_sock *h)
+{
+	nl_handle_destroy(h);
+}
+#endif /* CONFIG_LIBNL20 && CONFIG_LIBNL30 */
+
+static int wlnl_error_handler(struct sockaddr_nl * nla,	struct nlmsgerr *err, void *arg)
+{
+	struct nl_prv_data *prv = arg;
+	UNUSED_PARAMETER(nla);
+
+	if (err->error) {
+		prv->err = err->error;
+		return NL_STOP;
+	}
+	return NL_SKIP;
+}
+
+static int wlnl_finish_handler(struct nl_msg *msg, void *arg)
+{
+	UNUSED_PARAMETER(msg);
+	UNUSED_PARAMETER(arg);
+	return NL_SKIP;
+}
+
+static int wlnl_ack_handler(struct nl_msg *msg, void *arg)
+{
+	struct nl_prv_data *prv = arg;
+	UNUSED_PARAMETER(msg);
+
+	prv->err = 0;
+	return NL_STOP;
+}
+
+static int wlnl_valid_handler(struct nl_msg *msg, void *arg)
+{
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct nlattr *attrs[NL80211_ATTR_MAX + 1];
+	struct nlattr *bcmnl[BCM_NLATTR_MAX + 1];
+	struct nl_prv_data *prv = arg;
+	int ret;
+	uint payload;
+
+	nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		genlmsg_attrlen(gnlh, 0), NULL);
+	if (!attrs[NL80211_ATTR_VENDOR_DATA]) {
+		fprintf(stderr, "Could not find attrs NL80211_ATTR_VENDOR_DATA\n");
+		return NL_SKIP;
+	}
+
+	ret = nla_parse_nested(bcmnl, BCM_NLATTR_MAX,
+		attrs[NL80211_ATTR_VENDOR_DATA], wl_nl_policy);
+	if (ret != 0 || !bcmnl[BCM_NLATTR_LEN] || !bcmnl[BCM_NLATTR_DATA]) {
+		fprintf(stderr, "nla_parse_nested error\n");
+		return NL_SKIP;
+	}
+
+	payload = nla_get_u16(bcmnl[BCM_NLATTR_LEN]);
+	if (payload > prv->len)
+		payload = prv->len;
+	memcpy(prv->data, nla_data(bcmnl[BCM_NLATTR_DATA]), payload);
+	prv->data += payload;
+	prv->len -= payload;
+
+	return NL_SKIP;
+}
+
+int wlnl_sock_connect(struct wl_netlink_info *wl_nli)
+{
+	wl_nli->nl = nl_socket_alloc();
+	if (wl_nli->nl == NULL)
+		return -1;
+
+	if (genl_connect(wl_nli->nl) < 0) {
+		fprintf(stderr, "netlink connection failed\n");
+		goto err;
+	}
+
+	wl_nli->nl_id = genl_ctrl_resolve(wl_nli->nl, "nl80211");
+	if (wl_nli->nl_id < 0) {
+		fprintf(stderr, "'nl80211' netlink not found\n");
+		goto err;
+	}
+
+	wl_nli->cb = nl_cb_alloc(NL_CB_DEFAULT);
+	if (wl_nli->cb == NULL)
+		goto err;
+
+	nl_socket_set_cb(wl_nli->nl, wl_nli->cb);
+	return 0;
+
+err:
+	nl_cb_put(wl_nli->cb);
+	nl_socket_free(wl_nli->nl);
+	fprintf(stderr, "nl80211 connection failed\n");
+	return -1;
+}
+
+void wlnl_sock_disconnect(struct wl_netlink_info *wl_nli)
+{
+	nl_cb_put(wl_nli->cb);
+	nl_socket_free(wl_nli->nl);
+}
+
+int wlnl_do_vndr_cmd(struct wl_netlink_info *wl_nli, wl_ioctl_t *ioc)
+{
+	struct nl_msg *msg;
+	struct nl_prv_data prv_dat;
+	struct bcm_nlmsg_hdr *nlioc;
+	uint msglen = ioc->len;
+
+	msg = nlmsg_alloc();
+	if (msg == NULL)
+		return -ENOMEM;
+
+	/* nlmsg_alloc() can only allocate default_pagesize packet, cap
+	 * any buffer send down to 1536 bytes
+	 * DO NOT switch to nlmsg_alloc_size because Android doesn't support it
+	 */
+	if (msglen > 0x600)
+		msglen = 0x600;
+	msglen += sizeof(struct bcm_nlmsg_hdr);
+	nlioc = malloc(msglen);
+	if (nlioc == NULL) {
+		nlmsg_free(msg);
+		return -ENOMEM;
+	}
+	nlioc->cmd = ioc->cmd;
+	nlioc->len = ioc->len;
+	nlioc->offset = sizeof(struct bcm_nlmsg_hdr);
+	nlioc->set = ioc->set;
+	nlioc->magic = 0;
+	memcpy(((void *)nlioc) + nlioc->offset, ioc->buf, msglen - nlioc->offset);
+
+	/* fill testmode message */
+	genlmsg_put(msg, 0, 0, wl_nli->nl_id, 0, 0, NL80211_CMD_VENDOR, 0);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wl_nli->ifidx);
+	NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, OUI_BRCM);
+	NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, BRCM_VENDOR_SCMD_PRIV_STR);
+	NLA_PUT(msg, NL80211_ATTR_VENDOR_DATA, msglen, nlioc);
+
+	prv_dat.err = nl_send_auto_complete(wl_nli->nl, msg);
+	if (prv_dat.err < 0) {
+		goto out;
+	}
+
+	prv_dat.err = 1;
+	prv_dat.nlioc = nlioc;
+	prv_dat.data = ioc->buf;
+	prv_dat.len = ioc->len;
+	nl_cb_err(wl_nli->cb, NL_CB_CUSTOM, wlnl_error_handler, &prv_dat);
+	nl_cb_set(wl_nli->cb, NL_CB_ACK, NL_CB_CUSTOM,
+		wlnl_ack_handler, &prv_dat);
+	nl_cb_set(wl_nli->cb, NL_CB_FINISH, NL_CB_CUSTOM,
+		wlnl_finish_handler, &prv_dat);
+	nl_cb_set(wl_nli->cb, NL_CB_VALID, NL_CB_CUSTOM,
+		wlnl_valid_handler, &prv_dat);
+	while (prv_dat.err > 0)
+		nl_recvmsgs(wl_nli->nl, wl_nli->cb);
+
+out:
+	free(nlioc);
+	nlmsg_free(msg);
+	return prv_dat.err;
+
+nla_put_failure:
+	fprintf(stderr, "setting netlink attribute failed\n");
+	prv_dat.err = -EFAULT;
+	goto out;
+}
diff --git a/wl/src/wl/exe/wlu_nl80211.h b/wl/src/wl/exe/wlu_nl80211.h
new file mode 100644
index 0000000..3fa0977
--- /dev/null
+++ b/wl/src/wl/exe/wlu_nl80211.h
@@ -0,0 +1,52 @@
+/*
+ * Definitions for DHD nl80211 driver interface.
+ *
+ * Copyright (C) 2017, Broadcom. 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: $
+ */
+
+#ifndef DHDU_NL80211_H_
+#define DHDU_NL80211_H_
+
+#ifdef NL80211
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+
+/* libnl 1.x compatibility code */
+#if !defined(CONFIG_LIBNL20) && !defined(CONFIG_LIBNL30)
+#define nl_sock		nl_handle
+#endif
+
+struct wl_netlink_info
+{
+	struct nl_sock *nl;
+	struct nl_cb *cb;
+	int nl_id;
+	int ifidx;
+};
+
+int wlnl_sock_connect(struct wl_netlink_info *wl_nli);
+void wlnl_sock_disconnect(struct wl_netlink_info *wl_nli);
+int wlnl_do_vndr_cmd(struct wl_netlink_info *wl_nli, wl_ioctl_t *ioc);
+
+#endif /* NL80211 */
+
+#endif /* DHDU_NL80211_H_ */
diff --git a/wl/src/wl/exe/wlu_pipe.c b/wl/src/wl/exe/wlu_pipe.c
new file mode 100644
index 0000000..157fa24
--- /dev/null
+++ b/wl/src/wl/exe/wlu_pipe.c
@@ -0,0 +1,1109 @@
+/*
+ * Common Functionality for pipe
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_pipe.c 625881 2016-03-18 02:58:34Z $
+ */
+#ifdef WIN32
+#define NEED_IR_TYPES
+
+#include <windows.h>
+#include <epictrl.h>
+#include <irelay.h>
+#endif /* WIN32 */
+
+#ifdef LINUX
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <wlioctl.h>
+#include <net/if.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#if defined(TARGETOS_symbian)
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#else
+#if !defined(TARGETOS_nucleus) && !defined(__FreeBSD__)
+#include <malloc.h>
+#endif
+#endif /* TARGETOS_symbian */
+#include <typedefs.h>
+#include <wlioctl.h>
+
+#include <proto/ethernet.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#include <bcmcdc.h>
+#include <proto/802.11.h>
+#if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)
+#include <rwl_wifi.h>
+#endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */
+#include "wlu.h"
+#include "wlu_remote.h"
+#ifdef DHD_VISTA
+#include "wlu_remote_vista.h"
+#endif /* DHD_VISTA */
+
+static rem_ioctl_t rem_cdc;
+char  *g_rwl_device_name_serial = "";
+int g_rwl_device_baud = 115200;
+bool g_rwl_swap = FALSE;
+char g_rem_ifname[IFNAMSIZ] = "\0";
+int need_speedy_response; /* Indicate findserver is checking channels */
+
+#ifdef LINUX
+	/* Linux 100 usec */
+#define SYNC_TIME 100
+#else
+	/* WinXP 1 sec  */
+#define SYNC_TIME 1
+#endif
+
+#define UART_FIFO_LEN 			64
+#define END_OF_PACK_SEP_LEN 	2
+#define INIT_CMD_SLEEP 			500
+#define dtoh32(i) i
+
+/* dword align allocation */
+union {
+	uchar bufdata[ETHER_ADDR_LEN];
+	uint32 alignme;
+} bufmac_wlu;
+char *g_rwl_buf_mac = (char*) &bufmac_wlu.bufdata;
+
+#ifdef RWL_WIFI
+/* dword align allocation */
+union {
+	uchar shelldata[WL_MAX_BUF_LEN];
+	uint32 alignme;
+} shell_wlu;
+char *g_rwl_buf_shell = (char*) &shell_wlu.shelldata;
+int rwl_find_remote_wifi_server(void *wl, char *id);
+int wl_ioctl(void *wl, int cmd, void *buf, int len, bool set);
+
+#ifdef DHD_VISTA
+extern GUID dev;
+#endif
+
+/*
+ * This function runs a set of commands before running the wi-fi server
+ * This is avoids packet drops and improves performance.
+ * We run the following wl commands
+ * up, mpc 0, wsec 0, slow_timer 999999, fast_timer 999999, glacial_timer 999999
+ * legacylink 1, monitor 1.
+ */
+void remote_wifi_ser_init_cmds(void *wl)
+{
+	int err;
+	char bigbuf[RWL_WIFI_BUF_LEN];
+	uint len = 0, count;
+	/* The array stores command, length and then data format */
+	remote_wifi_cmds_t wifi_cmds[] = {
+						{WLC_UP,  NULL, 0x0},
+						{WLC_SET_VAR,  "mpc", 0},
+						{WLC_SET_WSEC,  NULL, 0x0},
+						{WLC_SET_VAR, "slow_timer", 999999},
+						{WLC_SET_VAR, "fast_timer", 999999},
+						{WLC_SET_VAR, "glacial_timer", 999999},
+						{WLC_SET_MONITOR, NULL, 0x1},
+						{WLC_SET_PM, NULL, 0x0}
+	};
+
+	for (count = 0; count < ARRAYSIZE(wifi_cmds); count++) {
+
+		if (wifi_cmds[count].data == NULL)
+			len = sizeof(int);
+		else
+			len = (uint)strlen(wifi_cmds[count].data) + 1 + sizeof(int);
+
+		/* If the command length exceeds the buffer length continue
+		 * executing the next command
+		 */
+		if (len > sizeof(bigbuf)) {
+			DPRINT_ERR(ERR, "Err: command len exceeds buf len. Check"
+				"initialization cmds\n");
+			continue;
+		}
+
+		if (wifi_cmds[count].data != NULL) {
+			strcpy(bigbuf, wifi_cmds[count].data);
+			memcpy(&bigbuf[strlen(wifi_cmds[count].data)+1],
+			(char*)&wifi_cmds[count].value, sizeof(int));
+		} else {
+			memcpy(&bigbuf[0], (char*)&wifi_cmds[count].value, sizeof(int));
+		}
+#ifdef WIN32
+		/* Add OID base for NDIS commands */
+
+#ifdef DHD_VISTA
+		err = (int)ir_vista_setinformation(wl, &dev, wifi_cmds[count].cmd + WL_OID_BASE,
+			bigbuf, &len);
+#else
+		err = (int)ir_setinformation(wl, wifi_cmds[count].cmd + WL_OID_BASE, bigbuf, &len);
+#endif
+#endif /* DHD_VISTA */
+
+#if defined(LINUX) || defined(TARGETOS_symbian)
+		if (wifi_cmds[count].cmd == WLC_UP)
+			/* NULL needs to be passed to the driver if WL UP command needs to
+			 * be executed Otherwise driver hangs
+			 */
+			err = wl_ioctl(wl, wifi_cmds[count].cmd,
+				NULL, 0, TRUE);
+		else
+			err = wl_ioctl(wl, wifi_cmds[count].cmd,
+			(void*)&bigbuf, len, TRUE);
+
+#endif 
+		rwl_sleep(INIT_CMD_SLEEP);
+	}
+	BCM_REFERENCE(err);
+}
+
+/* When user wants to execute local CMD being in remote wifi mode, this fucntion is used
+ * to change the remote types.
+ * This fucntion is called to swap the remote type to execute the cmd using the local
+ *  driver interface.
+ * This is required for to call proper front end fucntions to achive the local set/get ioctl.
+ */
+void
+rwl_wifi_swap_remote_type(int flag)
+{
+	static int remote_flag;
+	if (flag == REMOTE_WIFI) {
+		remote_type = NO_REMOTE;
+		remote_flag = flag;
+	} else if (remote_flag == REMOTE_WIFI) {
+		remote_type = remote_flag;
+		remote_flag = flag;
+	}
+	return;
+}
+
+void
+rwl_wifi_free_list(dot11_action_wifi_vendor_specific_t *list[])
+{
+	int i;
+	for (i = 0; i < RWL_DEFAULT_WIFI_FRAG_COUNT; i++) {
+		if (list[i])
+			free(list[i]);
+	}
+}
+
+/*
+ *  Configures local channel  for finding server.
+ *  Server call this fucntion for getting its current channel,
+ *  client uses this fucntion for setting its channel to new channel.
+ */
+static int
+rwl_wifi_config_channel(void *wl, int cmd, int *channel)
+{
+	int error;
+	channel_info_t ci;
+	error = -1;
+	/* Get functionality is used only by server */
+	if (cmd == WLC_GET_CHANNEL) {
+		memset((char*)&ci, 0, sizeof(ci));
+		if ((error = wl_get(wl, cmd, &ci, sizeof(channel_info_t))) < 0)
+			return error;
+		ci.hw_channel = dtoh32(ci.hw_channel);
+		ci.scan_channel = dtoh32(ci.scan_channel);
+		ci.target_channel = dtoh32(ci.target_channel);
+		if (ci.scan_channel) {
+			printf("Scan in progress.\n");
+		}
+		*channel = ci.hw_channel;
+	}
+
+	if (cmd == WLC_SET_CHANNEL) {
+		/* Set functionality is used by the client */
+		ci.target_channel = *channel;
+		/*   When user wants to execute local CMD being in remote wifi mode,
+		*	rwl_wifi_swap_remote_type fucntion is used to change the remote types.
+		*/
+		rwl_wifi_swap_remote_type(remote_type);
+		error = wl_set(wl, cmd, &ci.target_channel, sizeof(int));
+		/* rever it back to same old remote type */
+		rwl_wifi_swap_remote_type(remote_type);
+	}
+	return error;
+}
+/*
+allocate the memory for action frame and update with wifi tranport header.
+*/
+dot11_action_wifi_vendor_specific_t *
+rwl_wifi_allocate_actionframe()
+{
+	dot11_action_wifi_vendor_specific_t *action_frame;
+
+	if ((action_frame = (dot11_action_wifi_vendor_specific_t *)
+	malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
+		DPRINT_ERR(ERR, "rwl_wifi_allocate_actionframe: unable to allocate frame \n");
+		return action_frame;
+	}
+	action_frame->category 	= RWL_ACTION_WIFI_CATEGORY;
+	action_frame->OUI[0] 	= RWL_WIFI_OUI_BYTE0;
+	action_frame->OUI[1] 	= RWL_WIFI_OUI_BYTE1;
+	action_frame->OUI[2] 	= RWL_WIFI_OUI_BYTE2;
+	action_frame->type   	= RWL_WIFI_DEFAULT_TYPE;
+	action_frame->subtype   = RWL_WIFI_DEFAULT_SUBTYPE;
+
+	return action_frame;
+}
+/*
+ * Send the valid action frame (CDC+DATA) through the REF driver interface.
+ * if the CMD is "findserver" then "findmypeer" frames are sent on the diffrent
+ * channels to reconnect
+ * to with server. Other wl cmd takes the normal path.
+ * parameter 3 , i.e. buf contains the cmd line arguments  and buf_len is the actual
+ * length of the buf. data_len is the length of the actual data to be sent to remote server.
+ */
+int
+remote_CDC_wifi_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags)
+{
+	rem_ioctl_t *rem_ptr = &rem_cdc;
+	int error, read_try;
+	dot11_action_wifi_vendor_specific_t *rem_wifi_send;
+
+	/* prepare CDC header */
+	rem_ptr->msg.cmd = cmd;
+	rem_ptr->msg.len = buf_len;
+	rem_ptr->msg.flags = flags;
+	rem_ptr->data_len = data_len;
+
+	if (strlen(g_rem_ifname) != 0)
+		strncpy(rem_ptr->intf_name, g_rem_ifname, (int)IFNAMSIZ);
+	rwl_swap_header(rem_ptr, HOST_TO_NETWORK);
+
+	if ((data_len > buf_len)) {
+		DPRINT_ERR(ERR, "remote_CDC_wifi_tx: data_len (%d) > buf_len (%d)\n",
+		data_len, buf_len);
+		return (FAIL);
+	}
+	/* client will not send data greater than RWL_WIFI_FRAG_DATA_SIZE to server,
+	 * this condition should not be hit on client side, when sending the cmd
+	 * to remote server
+	 */
+	if (data_len > RWL_WIFI_FRAG_DATA_SIZE)
+		DPRINT_DBG(OUTPUT, "data size exceeds data_len %d\n", rem_ptr->msg.len);
+
+	if ((buf != NULL) && (strlen((char*)buf) >= (sizeof(RWL_WIFI_FIND_SER_CMD)-1)) &&
+		(!strcmp((char*)buf, RWL_WIFI_FIND_SER_CMD))) {
+		/* This is special case for wifi, when user wants to findserver,
+		* client has to execute it locally.Find the channel on the on
+		* which DUT is operating and sync up with specified MAC address,
+		* retry if fails to find the server
+		*/
+		for (read_try = 0; read_try < RWL_WIFI_RETRY; read_try++) {
+			if (((error = rwl_find_remote_wifi_server(wl,
+			&g_rwl_buf_mac[0])) == 0)) {
+				break;
+			}
+		}
+		return error;
+	}
+
+	if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
+		DPRINT_ERR(ERR, "remote_CDC_wifi_tx: Failed to allocate memory\n");
+		return (FAIL);
+	}
+	/* only data length needs to be sent to remote server using this function
+	* This function is only meant for client to send data to server
+	* Copy the CDC header and data to action frame data feild
+	* Now we have encapsulated the CDC header and data completely to in the
+	* action frame.
+	*/
+	memcpy((void*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
+		(char*)rem_ptr, REMOTE_SIZE);
+	if (buf != NULL) {
+	  memcpy((void*)&rem_wifi_send->data[REMOTE_SIZE], buf, data_len);
+	}
+
+	/* Send the action frame to remote server using the  rwl_var_setbuf fucntion,
+	 * which will use the local driver interface to send this frame on the air
+	 */
+	if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
+	RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+		DPRINT_ERR(ERR, "Unable to read the action frame %d error\n", error);
+	}
+	free(rem_wifi_send);
+	return error;
+}
+
+/*
+ * Read the valid action frame through the REF/DUT driver interface.
+ * Retry for no of times, wait for action frame for the specified time.
+ */
+int
+remote_CDC_DATA_wifi_rx(void *wl, dot11_action_wifi_vendor_specific_t * rec_frame)
+{
+	int error, read_try;
+	void *ptr = NULL;
+
+
+	/* retry is to ensure to read late arrival action frame */
+	for (read_try = 0; read_try < RWL_WIFI_RX_RETRY; read_try++) {
+		/* read the action frame queued in the local driver wifi queue */
+		if ((error = rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, rec_frame,
+		 RWL_WIFI_ACTION_FRAME_SIZE, &ptr)) < 0) {
+			DPRINT_ERR(ERR, "remote_CDC_DATA_wifi_rx: Error in reading the frame %d\n",
+			error);
+			return error;
+		}
+		/* copy the read action frame to the user frame and cjheck for the action category.
+		 *  If the action category matches with RWL_ACTION_WIFI_CATEGORY ,
+		 *  then its the valid frame, otherwise ignore it.
+		 */
+		memcpy((char*)rec_frame, ptr, RWL_WIFI_ACTION_FRAME_SIZE);
+
+		if (rec_frame->category == RWL_ACTION_WIFI_CATEGORY) {
+			break;
+		} else {
+			/* If we are executing findserver then sleep less */
+			if (!need_speedy_response)
+				rwl_sleep(RWL_WIFI_RX_DELAY);
+			else
+				rwl_sleep(RWL_CHANNEL_RX_SCAN_DELAY);
+		}
+	}
+	/* If failed to get the valid frame , indicate the error  */
+	if (!(rec_frame->category == RWL_ACTION_WIFI_CATEGORY)) {
+		return (FAIL);
+	}
+	return error;
+}
+/*
+ * read data that has reached client in fragments. If the functtion is
+ * called from rwl_shell_information_fe then the flag will be set to 1.
+ * For shell response this function will output the response on the standard interface.
+ * Response will be coming in out of order , this fucntion will make it inorder.
+ * Duplicate action frames are ignored.
+ */
+int
+remote_CDC_DATA_wifi_rx_frag(void *wl, rem_ioctl_t *rem_ptr, uint input_len,
+void *input, bool shell)
+{
+	int error, totalfrag, seq_num, num_frags, remainingbytes;
+	dot11_action_wifi_vendor_specific_t *rec_frame;
+	uchar *input_buf = (uchar*)input;
+	/* An array of pointers to each recieved frag */
+	dot11_action_wifi_vendor_specific_t *master_list[RWL_DEFAULT_WIFI_FRAG_COUNT];
+
+	UNUSED_PARAMETER(input_len);
+	remainingbytes = 0;
+
+	memset(master_list, 0, sizeof(master_list));
+	/* in case of shell cmd's receive size is unknown */
+	if (shell) {
+		input_buf = (uchar*)g_rwl_buf_shell;
+		memset(input_buf, 0, WL_MAX_BUF_LEN);
+	}
+
+	/* We don't yet know how many fragments we will need to read since the
+	   length is contained in the first frgment of the message itself. Set
+	   totalfrag to an arbitry large number and we will readjust it after we
+	   successfully recieve the first frag.
+	*/
+	totalfrag = RWL_DEFAULT_WIFI_FRAG_COUNT;
+
+	for (num_frags = 0; num_frags <= totalfrag; num_frags++) {
+		if ((rec_frame = rwl_wifi_allocate_actionframe()) == NULL) {
+			DPRINT_DBG(OUTPUT, "malloc failure\n");
+			rwl_wifi_free_list(master_list);
+			return (FAIL);
+		}
+		if ((error = remote_CDC_DATA_wifi_rx((void*)wl, rec_frame)) < 0) {
+			free(rec_frame);
+			rwl_wifi_free_list(master_list);
+			return FAIL;
+		}
+
+		if (rec_frame->subtype >= RWL_DEFAULT_WIFI_FRAG_COUNT) {
+			DPRINT_DBG(OUTPUT, " Read bogus subtype %d\n", rec_frame->subtype);
+			free(rec_frame);
+			continue;
+		}
+		/* Keep only originals and discard any dup frags */
+		if (!master_list[rec_frame->subtype]) {
+			master_list[rec_frame->subtype] = rec_frame;
+		} else {
+			num_frags--;
+			free(rec_frame);
+		}
+
+		/* Look for first frag so we can accurately calculate totalfrag */
+		if (rec_frame->subtype == RWL_WIFI_DEFAULT_SUBTYPE) {
+			memcpy((char*)rem_ptr,
+			(char*)&master_list[rec_frame->subtype]->
+			data[RWL_WIFI_CDC_HEADER_OFFSET], REMOTE_SIZE);
+			rwl_swap_header(rem_ptr, NETWORK_TO_HOST);
+			totalfrag = rem_ptr->msg.len / RWL_WIFI_FRAG_DATA_SIZE;
+			remainingbytes = rem_ptr->msg.len % RWL_WIFI_FRAG_DATA_SIZE;
+		}
+	}
+
+	/* All frags are now read and there are no dups. Check for missing frags */
+	for (seq_num = 0; seq_num < totalfrag; seq_num++) {
+		if (!master_list[seq_num]) {
+			DPRINT_DBG(OUTPUT, "Missing frag number %d\n", seq_num);
+			rwl_wifi_free_list(master_list);
+			return (FAIL);
+		}
+	}
+	/*
+	case 1: response in one frame i.e if (totalfrag==0)
+	case 2: response in multiple frame ( multiple of RWL_WIFI_FRAG_DATA_SIZE)
+	case 3: response in multiple frame and not in multiple of RWL_WIFI_FRAG_DATA_SIZE
+	*/
+
+	/* case 1: Check for the response in single frame */
+	if (totalfrag == 0)
+		memcpy((char*)&input_buf[0],
+		(char*)&master_list[0]->data[REMOTE_SIZE], rem_ptr->msg.len);
+	else /* case 2: Copy fragments into contiguous frame */
+		memcpy((char*)&input_buf[0],
+		(char*)&master_list[0]->data[REMOTE_SIZE], RWL_WIFI_FRAG_DATA_SIZE);
+
+	/*
+	* If all the frames are recieved , copy them to a contigues buffer
+	*/
+	for (seq_num = 1; seq_num < totalfrag; seq_num++) {
+		memcpy((char*)&input_buf[seq_num*RWL_WIFI_FRAG_DATA_SIZE],
+		(char*)&master_list[seq_num]->data, RWL_WIFI_FRAG_DATA_SIZE);
+	}
+
+	/* case 3 : if response is in fragments and valid data in the last frame is less
+	 * than RWL_WIFI_FRAG_DATA_SIZE
+	 */
+	if (remainingbytes && (totalfrag > 0))
+		memcpy((char*)&input_buf[seq_num*RWL_WIFI_FRAG_DATA_SIZE],
+		(char*)&master_list[seq_num]->data, remainingbytes);
+
+	if (shell) {
+#ifdef LINUX
+		write(1, (char*)input_buf, strlen((char*)input_buf));
+#else
+		fputs((char*)input_buf, stdout);
+#endif /* LINUX */
+	}
+
+	rwl_wifi_free_list(master_list);
+	return error;
+}
+/*
+ * read out all the action frame which are queued in the driver even
+ * before issuing any wl cmd. This is essential because due to late arrival of frame it can
+ * get queued after the read expires.
+ */
+int
+rwl_wifi_purge_actionframes(void *wl)
+{
+	dot11_action_wifi_vendor_specific_t *rec_frame;
+	void *ptr = NULL;
+	int error = BCME_OK;
+
+	if ((rec_frame = (dot11_action_wifi_vendor_specific_t *)
+	malloc(RWL_WIFI_ACTION_FRAME_SIZE)) == NULL) {
+		DPRINT_DBG(OUTPUT, "Purge Error in reading the frame \n");
+		return BCME_NOMEM;
+	}
+
+	for (;;) {
+		if ((error = rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, rec_frame,
+		RWL_WIFI_ACTION_FRAME_SIZE, &ptr)) < 0) {
+			DPRINT_DBG(OUTPUT, "rwl_wifi_purge_actionframes:"
+			"Purge Error in reading the frame \n");
+			break;
+		}
+		memcpy((char*)rec_frame, ptr, RWL_WIFI_ACTION_FRAME_SIZE);
+
+		if ((rec_frame->category != RWL_ACTION_WIFI_CATEGORY))
+			break;
+	}
+
+	free(rec_frame);
+
+	return error;
+}
+/*
+ * check for the channel of remote and respond if it matches with its current
+ * channel. Once the server gets the handshake cmd, it will check the channel
+ * number of the remote with its channel and if it matches , then it send out the
+ * ack to the remote client. This fucntion is used only by the server.
+ */
+void
+rwl_wifi_find_server_response(void *wl, dot11_action_wifi_vendor_specific_t *rec_frame)
+{
+	int error, send, server_channel;
+
+	if (rec_frame->type == RWL_WIFI_FIND_MY_PEER) {
+
+		rec_frame->type = RWL_WIFI_FOUND_PEER;
+		/* read channel on of the SERVER */
+		rwl_wifi_config_channel(wl, WLC_GET_CHANNEL, &server_channel);
+		/* overlapping channel not supported,
+		so server will only respond to client on the channel of the client
+		*/
+		if (rec_frame->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] == server_channel) {
+			/* send the response by updating server channel in the frame */
+			rec_frame->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] = server_channel;
+			/* change the TYPE feild for giving the ACK */
+			for (send = 0; send < RWL_WIFI_SEND; send++) {
+				if ((error = rwl_var_send_vs_actionframe(wl,
+					RWL_WIFI_ACTION_CMD,
+					rec_frame,
+					RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+					DPRINT_ERR(ERR, "rwl_wifi_find_server_response: Failed"
+					"to Send the Frame %d\n", error);
+					break;
+				}
+				rwl_sleep(RWL_WIFI_SEND_DELAY);
+			}
+		}
+	}
+	return;
+}
+/*
+ * This function is used by client only. Sends the finmypeer sync frame to remote
+ * server on diffrent channels and  waits for the response.
+ */
+int
+rwl_find_remote_wifi_server(void *wl, char *id)
+{
+	dot11_action_wifi_vendor_specific_t *rem_wifi_send, *rem_wifi_recv;
+	rem_ioctl_t *rem_ptr = &rem_cdc;
+	/* This list is generated considering valid channel and if this
+	 * may requires updation or deletion. This needs to be identified.
+	 * we have assumed that server band is not known and considered all band channels.
+	 */
+	int wifichannel[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+	11, 36, 40, 44, 48, 149, 153, 157, 161, 165};
+	int i, error, schannel, channel_count;
+	struct ether_addr * curr_macaddr;
+	int ret;
+	need_speedy_response = TRUE;
+
+	if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
+		DPRINT_ERR(ERR, " rwl_find_remote_wifi_server : Failed to allocate \n");
+		return FAIL;
+	}
+	if ((rem_wifi_recv = rwl_wifi_allocate_actionframe()) == NULL) {
+		DPRINT_ERR(ERR, " rwl_find_remote_wifi_server : Failed to allocate\n");
+		free(rem_wifi_send);
+		return FAIL;
+	}
+
+	channel_count = sizeof(wifichannel) / sizeof(int);
+
+	/* make dummy read to make sure we don't read the already queued
+	 * actionframes against the cmd we issue
+	 */
+	if ((error = rwl_wifi_purge_actionframes(wl)) < 0) {
+		free(rem_wifi_send);
+		free(rem_wifi_recv);
+		return error;
+	}
+
+	/* update the client sync specifier */
+	rem_wifi_send->type = RWL_WIFI_FIND_MY_PEER;
+	/* update the CDC flag to indicate it is handshake frame */
+	rem_ptr->msg.cmd = 0;
+	/* cmd =0 ,this will be ignored when server receive frame
+	 * with REMOTE_FINDSERVER_IOCTL flag
+	 */
+	rem_ptr->msg.len = RWL_WIFI_FRAG_DATA_SIZE;
+	rem_ptr->msg.flags = REMOTE_FINDSERVER_IOCTL;
+	rem_ptr->data_len = RWL_WIFI_FRAG_DATA_SIZE;
+	rwl_swap_header(rem_ptr, HOST_TO_NETWORK);
+
+	memcpy((char*)&rem_wifi_send->data, (char*)rem_ptr, REMOTE_SIZE);
+	/* copy server mac to which ref driver needs to send unicast action frame */
+	memcpy((char*)&rem_wifi_send->data[RWL_REF_MAC_ADDRESS_OFFSET], &id[0], ETHER_ADDR_LEN);
+
+	if ((ret = rwl_var_getbuf(wl, "cur_etheraddr", NULL, 0, (void**) &curr_macaddr)) < 0) {
+		DPRINT_ERR(ERR, "Error getting current Mac addr \n");
+		return FAIL;
+	}
+
+	memcpy((char*)&rem_wifi_send->data[RWL_DUT_MAC_ADDRESS_OFFSET], (char*)curr_macaddr->octet,
+		ETHER_ADDR_LEN);
+	/* Start with the channel in the list and keep changing till the server
+	 * responds or channels list ends
+	 */
+	for (i = 0; i < channel_count; i++) {
+		DPRINT_INFO(OUTPUT, "Scanning Channel: %d ...\n", wifichannel[i]);
+		if ((error = rwl_wifi_config_channel(wl, WLC_SET_CHANNEL,
+		&wifichannel[i])) < 0) {
+			DPRINT_ERR(ERR, " Failed to set the specified channel %d\n",
+			wifichannel[i]);
+			break;
+		}
+		/* send channel detail of client to server */
+		rem_wifi_send->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] = wifichannel[i];
+
+		if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
+		RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+			DPRINT_DBG(OUTPUT, "Failed to Send the Frame %d\n", error);
+			break;
+		}
+		/* read the server response on the same channel */
+		if ((error = remote_CDC_DATA_wifi_rx(wl, rem_wifi_recv)) < 0) {
+			rwl_sleep(RWL_CHANNEL_SCAN_WAIT);
+			continue;
+		}
+		/* Verify for the Type RWL_WIFI_FOUND_PEER */
+		if (rem_wifi_recv->type == RWL_WIFI_FOUND_PEER) {
+			if (rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] ==
+				rem_wifi_recv->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET]) {
+
+				DPRINT_INFO(OUTPUT, "Server is on channel # %d\n",
+				rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET]);
+
+				schannel = rem_wifi_recv->data[RWL_WIFI_SERVER_CHANNEL_OFFSET];
+				/* Set the back to the channel on which REF was originally */
+				if ((error = rwl_wifi_config_channel(wl,
+				WLC_SET_CHANNEL, &schannel) < 0)) {
+					DPRINT_ERR(ERR, "Failed to set the specified"
+					"channel %d\n", schannel);
+				} else {
+					DPRINT_ERR(ERR, "REF now moved to the"
+					"channel of server # %d\n", schannel);
+				}
+				need_speedy_response = FALSE;
+				/* we are done here, end the loop */
+				break;
+			} else {
+				DPRINT_INFO(OUTPUT, "Server is operating on diffrent channel."
+				"continue scanning\n");
+			}
+		}
+		/* before chaning the channel of client and sending sync frame
+		 * wait for while and send
+		 */
+		rwl_sleep(RWL_CHANNEL_SCAN_WAIT);
+	}
+	need_speedy_response = FALSE;
+
+	free(rem_wifi_send);
+	free(rem_wifi_recv);
+	return error;
+}
+#endif /* RWL_WIFI */
+#ifdef RWL_DONGLE
+static int
+remote_CDC_tx_dongle(void *wl, rem_ioctl_t *rem_ptr, uchar *buf)
+{
+	unsigned long numwritten;
+	char end_of_packet[END_OF_PACK_SEP_LEN] = "\n\n";
+	uchar loc_buf[UART_FIFO_LEN];
+	uint len = END_OF_PACK_SEP_LEN;
+	uint noframes, frame_count, rem_bytes;
+	uint n_bytes;
+	uint data_len;
+
+	/* Converting the CDC header with keyword 'rwl ' in ascii format
+	 * as dongle UART understands only ascii format.
+	 * In dongle UART driver CDC structure is made from the ascii data
+	 * it received.
+	 */
+	sprintf((char*)loc_buf, "rwl %d %d %d %d ", rem_ptr->msg.cmd, rem_ptr->msg.len,
+		rem_ptr->msg.flags, rem_ptr->data_len);
+	n_bytes = (uint)strlen((char*)loc_buf);
+
+	data_len = ltoh32(rem_ptr->data_len);
+	DPRINT_DBG(OUTPUT, "rwl %x %d %d %d ", ltoh32(rem_ptr->msg.cmd), ltoh32(rem_ptr->msg.len),
+		ltoh32(rem_ptr->msg.flags), data_len);
+	DPRINT_DBG(OUTPUT, "CDC Header:No of bytes to be sent=%d\n", n_bytes);
+	DPRINT_DBG(OUTPUT, "Data:No of bytes to be sent=%d\n", data_len);
+
+	/* Send the CDC Header */
+	if (rwl_write_serial_port(wl, (char*)loc_buf, n_bytes, &numwritten) < 0) {
+		DPRINT_ERR(ERR, "CDC_Tx: Header: Write failed\n");
+		DPRINT_ERR(ERR, "CDC_Tx: Header: numwritten %ld != n_bytes %d\n",
+			numwritten, n_bytes);
+		return (FAIL);
+	}
+
+	/* Dongle UART FIFO len is 64 bytes and flow control is absent.
+	 * While transmitting large chunk of data the data was getting lost
+	 * at UART driver so for large chunk of data 64 bytes are sent at a time
+	 * folowed by delay and then next set of 64 bytes and so on.
+	 * For data which is less than 64 bytes it is sent in one shot
+	 */
+
+	noframes = rem_ptr->data_len/UART_FIFO_LEN;
+	if (noframes == 0) {
+		/* Send the data now */
+		if (rwl_write_serial_port(wl, (char*)buf, rem_ptr->data_len, &numwritten) < 0) {
+			DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
+			DPRINT_ERR(ERR, "Data_Tx: Header: numwritten %ld != len %d\n",
+			numwritten, rem_ptr->data_len);
+			return (FAIL);
+		}
+
+	} else {
+		if (rem_ptr->data_len % UART_FIFO_LEN == 0) {
+			rem_bytes = UART_FIFO_LEN;
+		} else {
+			rem_bytes = rem_ptr->data_len % UART_FIFO_LEN;
+			noframes += 1;
+		}
+
+		for (frame_count = 0; frame_count < noframes; frame_count++) {
+			if (frame_count != noframes-1) {
+				memcpy(loc_buf, (char*)(&buf[frame_count*UART_FIFO_LEN]),
+				UART_FIFO_LEN);
+				/* Send the data now */
+				if (rwl_write_serial_port(wl, (char*)loc_buf, UART_FIFO_LEN,
+				&numwritten) == -1) {
+					DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
+					return (-1);
+				}
+
+			} else {
+				memcpy(loc_buf, (char*)(&buf[frame_count*UART_FIFO_LEN]),
+				rem_bytes);
+
+				if (rwl_write_serial_port(wl, (char*)loc_buf, rem_bytes,
+				&numwritten) == -1) {
+					DPRINT_ERR(ERR, "Data_Tx: Header: Write failed\n");
+					return (-1);
+				}
+
+			}
+			rwl_sleep(SYNC_TIME);
+		}
+	}
+
+	/* Send end of packet now */
+	if (rwl_write_serial_port(wl, end_of_packet, len, &numwritten) == -1) {
+		DPRINT_ERR(ERR, "CDC_Tx: Header: Write failed\n");
+		DPRINT_ERR(ERR, "CDC_Tx: Header: numwritten %ld != len %d\n",
+			numwritten, len);
+		return (FAIL);
+	}
+
+	DPRINT_DBG(OUTPUT, "Packet sent!\n");
+
+	/* Return size of actual buffer to satisfy accounting going on above this level */
+	return (ltoh32(rem_ptr->msg.len));
+}
+#endif /* RWL_DONGLE */
+
+#if defined(RWL_SERIAL) || defined(RWL_DONGLE)|| defined(RWL_SOCKET)
+void *
+rwl_open_pipe(int remote_type, char *port, int ReadTotalTimeout, int debug)
+{
+	return rwl_open_transport(remote_type, port, ReadTotalTimeout, debug);
+}
+
+int
+rwl_close_pipe(int remote_type, void* handle)
+{
+	return rwl_close_transport(remote_type, handle);
+}
+#endif
+
+int
+remote_CDC_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags, int debug)
+{
+#ifdef RWL_SERIAL
+	unsigned long numwritten = 0;
+#endif
+	rem_ioctl_t *rem_ptr = &rem_cdc;
+#ifdef RWL_WIFI
+	int error;
+	uint totalframes, tx_count;
+	dot11_action_wifi_vendor_specific_t *rem_wifi_send;
+#endif
+	UNUSED_PARAMETER(debug);
+	UNUSED_PARAMETER(buf);
+	UNUSED_PARAMETER(wl);
+
+	memset(rem_ptr, 0, sizeof(rem_ioctl_t));
+	rem_ptr->msg.cmd = cmd;
+	rem_ptr->msg.len = buf_len;
+	rem_ptr->msg.flags = flags;
+	rem_ptr->data_len = data_len;
+
+	if (strlen(g_rem_ifname) != 0) {
+		strncpy(rem_ptr->intf_name, g_rem_ifname, (int)IFNAMSIZ - 1);
+		rem_ptr->intf_name[IFNAMSIZ - 1] = '\0';
+	}
+	rwl_swap_header(rem_ptr, HOST_TO_NETWORK);
+
+	if (data_len > buf_len) {
+		DPRINT_ERR(ERR, "remote_CDC_tx: data_len (%d) > buf_len (%d)\n", data_len, buf_len);
+		return (FAIL);
+	}
+#ifdef RWL_SERIAL
+	if (remote_type == REMOTE_SERIAL) {
+		int ret;
+		/* Send CDC header first */
+		if ((ret = rwl_write_serial_port(wl, (char *)rem_ptr,
+			REMOTE_SIZE, &numwritten)) == -1) {
+			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
+			return (FAIL);
+		}
+		numwritten = ret;
+
+		/* Send data second */
+		if ((ret = rwl_write_serial_port(wl, (char*)buf,
+			data_len, &numwritten)) == -1) {
+			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
+			return (FAIL);
+		}
+		numwritten = ret;
+
+		return (buf_len);
+	}
+#endif /* RWL_SERIAL */
+#ifdef RWL_DONGLE
+	if (remote_type == REMOTE_DONGLE) {
+		return (remote_CDC_tx_dongle(wl, rem_ptr, buf));
+	}
+#endif /* RWL_DONGLE */
+#ifdef RWL_SOCKET
+	if (remote_type == REMOTE_SOCKET) {
+		int ret;
+
+		/* Send CDC header first */
+		if ((ret = rwl_send_to_streamsocket(*(int*)wl, (char *)rem_ptr,
+			REMOTE_SIZE, 0)) == -1) {
+			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
+			return (FAIL);
+		}
+
+		/* Send data second */
+		if ((ret = rwl_send_to_streamsocket(*(int*)wl, (const char*)buf,
+			data_len, 0)) == -1) {
+			DPRINT_ERR(ERR, "CDC_Tx: Data: Write failed \n");
+			return (FAIL);
+		}
+
+		return (buf_len);
+	}
+#endif /* RWL_SOCKET */
+
+#ifdef RWL_WIFI
+	/*
+	 * wifi action frame is formed based on the CDC header and data.
+	 * If the data is bigger than RWL_WIFI_FRAG_DATA_SIZE size, number of fragments are
+	 * calculated and sent
+	 * similar number of action frames with subtype incremented with sequence.
+	 * Frames are sent with delay to avoid the outof order at receving end
+	 */
+	if (remote_type == REMOTE_WIFI) {
+		if ((rem_wifi_send = rwl_wifi_allocate_actionframe()) == NULL) {
+			DPRINT_ERR(ERR, "remote_CDC_tx: Failed to get allocated buffer\n");
+			return (FAIL);
+		}
+
+		if (buf_len > RWL_WIFI_FRAG_DATA_SIZE) {
+			/* response needs to be sent in fragments */
+			totalframes = buf_len / RWL_WIFI_FRAG_DATA_SIZE;
+			memcpy((char*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
+			(char*)rem_ptr,	REMOTE_SIZE);
+			memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE], &buf[0],
+			RWL_WIFI_FRAG_DATA_SIZE);
+			/* update type feild to inform receiver it's frammeted response frame
+			*/
+			rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
+			rem_wifi_send->subtype = RWL_WIFI_DEFAULT_SUBTYPE;
+
+			if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,
+				rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+				DPRINT_DBG(OUTPUT, "Failed to Send the Frame %d\n", error);
+				free(rem_wifi_send);
+				return error;
+			}
+			/* Send remaining bytes in fragments */
+			for (tx_count = 1; tx_count < totalframes; tx_count++) {
+				rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
+				rem_wifi_send->subtype = tx_count;
+				/* First frame onwards , buf contains only data */
+				memcpy((char*)&rem_wifi_send->data,
+				&buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE], RWL_WIFI_FRAG_DATA_SIZE);
+				if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,
+					rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+					free(rem_wifi_send);
+					return error;
+				}
+				rwl_sleep(RWL_WIFI_SEND_DELAY);
+			}
+
+			/* Check for remaing bytes to send */
+			if ((totalframes*RWL_WIFI_FRAG_DATA_SIZE) != buf_len) {
+				rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
+				rem_wifi_send->subtype = tx_count;
+				memcpy((char*)&rem_wifi_send->data,
+				&buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE],
+				(buf_len - (tx_count*RWL_WIFI_FRAG_DATA_SIZE)));
+				if ((error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD,
+					rem_wifi_send, RWL_WIFI_ACTION_FRAME_SIZE)) < 0) {
+					free(rem_wifi_send);
+					return error;
+				}
+			}
+		} else {
+			/* response fits to single frame */
+			memcpy((char*)&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET],
+			(char*)rem_ptr,	REMOTE_SIZE);
+			/* when data_len is 0 , buf will be NULL */
+			if (buf != NULL) {
+				memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE],
+				&buf[0], data_len);
+			}
+			error = rwl_var_send_vs_actionframe(wl, RWL_WIFI_ACTION_CMD, rem_wifi_send,
+			RWL_WIFI_ACTION_FRAME_SIZE);
+			free(rem_wifi_send);
+			return error;
+		}
+	}
+#endif /* RWL_WIFI */
+	return (0);
+}
+
+
+rem_ioctl_t *
+remote_CDC_rx_hdr(void *remote, int debug)
+{
+#ifdef RWL_SOCKET
+	int ret;
+#endif /* RWL_SOCKET */
+
+#if defined(RWL_SERIAL) || defined(RWL_DONGLE) || defined(RWL_SOCKET)
+	uint numread = 0;
+#endif
+	rem_ioctl_t *rem_ptr = &rem_cdc;
+	memset(rem_ptr, 0, sizeof(rem_ioctl_t));
+
+	UNUSED_PARAMETER(remote);
+	UNUSED_PARAMETER(debug);
+
+	switch (remote_type)	{
+#if defined(RWL_SERIAL) || defined(RWL_DONGLE)
+		case REMOTE_SERIAL:
+		case REMOTE_DONGLE:
+			if (rwl_read_serial_port(remote, (char *)rem_ptr, sizeof(rem_ioctl_t),
+				&numread) < 0) {
+				DPRINT_ERR(ERR, "remote_CDC_rx_hdr: Header Read failed \n");
+				return (NULL);
+			}
+			break;
+#endif /* RWL_SERIAL |  RWL_DONGLE */
+
+
+#ifdef RWL_SOCKET
+		case REMOTE_SOCKET:
+			ret = rwl_receive_from_streamsocket(*(int*)remote, (char *)rem_ptr,
+				sizeof(rem_ioctl_t), 0);
+			numread = ret;
+			if (ret == -1) {
+				DPRINT_ERR(ERR, "remote_CDC_rx_hdr: numread:%d\n", numread);
+				return (NULL);
+			}
+		if (numread == 0) {
+		      DPRINT_DBG(OUTPUT, "\n remote_CDC_rx_hdr:No data to receive\n");
+			return NULL;
+			}
+			break;
+#endif
+		default:
+			DPRINT_ERR(ERR, "\n Unknown Transport Type\n");
+			break;
+	}
+
+	return (rem_ptr);
+}
+
+/* Return a CDC type buffer */
+int
+remote_CDC_rx(void *wl, rem_ioctl_t *rem_ptr, uchar *readbuf, uint buflen, int debug)
+{
+	uint numread = 0;
+
+#ifdef RWL_SOCKET
+	int ret;
+#endif
+
+#ifdef RWL_WIFI
+	UNUSED_PARAMETER(numread);
+#endif /* RWL_WIFI */
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(readbuf);
+	UNUSED_PARAMETER(buflen);
+	UNUSED_PARAMETER(debug);
+	UNUSED_PARAMETER(numread);
+
+	if (rem_ptr->data_len > rem_ptr->msg.len) {
+		DPRINT_ERR(ERR, "remote_CDC_rx: remote data len (%d) > msg len (%d)\n",
+			rem_ptr->data_len, rem_ptr->msg.len);
+		return (FAIL);
+	}
+
+
+#if defined(RWL_DONGLE) || defined(RWL_SERIAL)
+	if ((remote_type == REMOTE_DONGLE) || (remote_type == REMOTE_SERIAL)) {
+		if (rwl_read_serial_port(wl, (char*)readbuf, rem_ptr->data_len,
+			&numread) < 0) {
+			DPRINT_ERR(ERR, "remote_CDC_rx_hdr: Data Receivefailed \n");
+			return (FAIL);
+		}
+	}
+#endif /* RWL_DONGLE || RWL_SERIAL */
+
+#ifdef RWL_SOCKET
+	if (remote_type == REMOTE_SOCKET) {
+		if (((ret = rwl_receive_from_streamsocket(*(int*)wl, (char*)readbuf,
+		rem_ptr->data_len, 0)) == -1)) {
+				DPRINT_ERR(ERR, "remote_CDC_rx:Data Receive failed\n");
+				return (FAIL);
+		}
+	}
+#endif /* RWL_SOCKET */
+	return (SUCCESS);
+}
+#ifdef RWL_SOCKET
+int
+rwl_sockconnect(int SockDes, struct sockaddr *servAddr, int size)
+{
+	DPRINT_DBG(OUTPUT, "sockconnet SockDes=%d\n", SockDes);
+	if (rwl_connectsocket(SockDes, servAddr, size) < 0) {
+			DPRINT_ERR(ERR, "\n Server is not running\n");
+			return FAIL;
+	}
+	return SUCCESS;
+}
+#endif /* RWL_SOCKET */
+void
+rwl_swap_header(rem_ioctl_t *rem_ptr, bool host_to_network)
+{
+	rem_ptr->msg.cmd = host_to_network?(htol32(rem_ptr->msg.cmd)):(ltoh32(rem_ptr->msg.cmd));
+	rem_ptr->msg.len = host_to_network?(htol32(rem_ptr->msg.len)):(ltoh32(rem_ptr->msg.len));
+	rem_ptr->msg.flags = host_to_network?(htol32(rem_ptr->msg.flags)):
+		(ltoh32(rem_ptr->msg.flags));
+	rem_ptr->msg.status = host_to_network?(htol32(rem_ptr->msg.status)):
+		(ltoh32(rem_ptr->msg.status));
+	rem_ptr->data_len = host_to_network?(htol32(rem_ptr->data_len)):(ltoh32(rem_ptr->data_len));
+}
diff --git a/wl/src/wl/exe/wlu_pipe.h b/wl/src/wl/exe/wlu_pipe.h
new file mode 100644
index 0000000..a99df56
--- /dev/null
+++ b/wl/src/wl/exe/wlu_pipe.h
@@ -0,0 +1,51 @@
+/*
+ * OS independent declarations
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_pipe.h 532220 2015-02-05 10:00:56Z $
+ */
+#ifndef _wlu_pipe_h
+#define _wlu_pipe_h
+
+/* Function prototypes defined in wlu_pipe.c */
+
+/* Macros to access globals */
+extern char *g_rwl_device_name_serial;
+#define rwl_get_serial_port_name()		(g_rwl_device_name_serial)
+#define rwl_set_serial_port_name(name) 	(g_rwl_device_name_serial = name)
+extern char *g_rwl_buf_mac;
+#define rwl_get_wifi_mac()				(g_rwl_buf_mac)
+
+extern int remote_CDC_tx(void *wl, uint cmd, uchar *buf, uint buf_len,
+uint data_len, uint flags, int debug);
+extern rem_ioctl_t *remote_CDC_rx_hdr(void *remote, int debug);
+extern int remote_CDC_rx(void *wl, rem_ioctl_t *rem_ptr, uchar *readbuf, uint buflen, int debug);
+
+extern void* rwl_open_pipe(int remote_type, char *port, int ReadTotalTimeout, int debug);
+extern int rwl_close_pipe(int remote_type, void* hndle);
+
+#ifdef RWL_SOCKET
+extern int rwl_sockconnect(int SockDes, struct sockaddr *servAddr, int size);
+#endif /* RWL_SOCKET */
+
+extern int remote_CDC_DATA_wifi_rx_frag(void *wl, rem_ioctl_t *rem_ptr, uint input_len,
+void *input, bool shell);
+extern int remote_CDC_DATA_wifi_rx(void *wl, struct dot11_action_wifi_vendor_specific *rec_frame);
+extern int
+remote_CDC_wifi_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags);
+extern void rwl_wifi_server_response(void *wl, struct dot11_action_wifi_vendor_specific *rec_frame);
+extern int rwl_find_remote_wifi_server(void *wl, char *id);
+extern int rwl_wifi_purge_actionframes(void *wl);
+extern void rwl_wifi_swap_remote_type(int flag);
+extern void remote_wifi_ser_init_cmds(void *wl);
+#endif /* _wlu_pipe_h */
diff --git a/wl/src/wl/exe/wlu_pipe_linux.c b/wl/src/wl/exe/wlu_pipe_linux.c
new file mode 100644
index 0000000..bd7dec1
--- /dev/null
+++ b/wl/src/wl/exe/wlu_pipe_linux.c
@@ -0,0 +1,645 @@
+/*
+ * linux version of remote Wl transport mechanisms (pipes).
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_pipe_linux.c 625881 2016-03-18 02:58:34Z $
+ */
+
+/*  Revision History: Linux version of remote Wl transport mechanisms (pipes).
+ *
+ * Date        Author         Description
+ *
+ * 27-Dec-2007 Suganthi        Version 0.0
+ *
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <proto/802.11.h>
+#include <bcmendian.h>
+#include <bcmcdc.h>
+#include <proto/802.11.h>
+#include <wlioctl.h>
+#include <typedefs.h>
+#include "wlu_remote.h"
+#include <miniopt.h>
+#if defined(RWL_DONGLE) || defined(RWL_SERIAL)
+#define READ_DELAY 			500000
+#define BAUD_RATE_115200	115200
+#define VMIN_VAL			16
+#define VTIME_VAL			50
+#define LINUX_SYNC_DELAY	200
+extern char  *g_rwl_device_name_serial;
+extern int g_rwl_device_baud;
+#endif
+
+#define MICRO_SEC_CONVERTER_VAL		1000
+int g_irh;
+int g_shellsync_pid;
+
+#ifdef RWL_SOCKET
+#define MAX_INTERFACE_NAME	32
+static int
+rwl_opensocket(int AddrFamily, int Type, int Protocol)
+{
+	int SockDes;
+
+	if ((SockDes = socket(AddrFamily, Type, Protocol)) == -1) {
+		perror("rwl_opensocket Fails:");
+		DPRINT_ERR(ERR, "\nerrno:%d\n", errno);
+		return FAIL;
+	}
+	return SockDes;
+}
+
+static int
+rwl_set_socket_option(int SocketDes, int Level, int OptName, int Val)
+{
+	if (setsockopt(SocketDes, Level, OptName, &Val, sizeof(int)) == -1) {
+		perror("Error at SetTCPSocketOpt()");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+/* Function to connect with the server waiting in the same port */
+int
+rwl_connectsocket(int SocketDes, struct sockaddr* SerAddr, int SizeOfAddr)
+{
+	if (connect(SocketDes, SerAddr, SizeOfAddr) == -1) {
+		perror("Failed to connect() to server");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+/*
+ * Function for associating a local address with a socket.
+ */
+int
+rwl_bindsocket(int SocketDes, struct sockaddr * MyAddr, int SizeOfAddr)
+{
+	if (bind(SocketDes, MyAddr, SizeOfAddr) == -1) {
+		perror("Error at rwl_bindSocket()");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+/*
+ * Function for making the socket to listen for incoming connection.
+ */
+int
+rwl_listensocket(int SocketDes, int BackLog)
+{
+	if (listen(SocketDes, BackLog) == -1) {
+		perror("Error at rwl_listensocket()");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+/*
+ * Function for permitting an incoming connection attempt on a socket
+ * Function  called by server
+ */
+int
+rwl_acceptconnection(int SocketDes, struct sockaddr* ClientAddr, int *SizeOfAddr)
+{
+	int NewSockDes;
+
+	if ((NewSockDes = accept(SocketDes, ClientAddr, (socklen_t*)SizeOfAddr)) == -1) {
+		perror("Error at rwl_acceptConnection()");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return NewSockDes;
+}
+
+static int
+rwl_closesocket(int SocketDes)
+{
+	if (close(SocketDes) == -1) {
+		perror("Error at rwl_closeSocket()");
+		DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+/* Transmit the response in the opened TCP stream socket */
+int
+rwl_send_to_streamsocket(int SocketDes, const char* SendBuff, int data_size, int Flag)
+{
+	int total_numwritten = 0,  numwritten = 0;
+	while (total_numwritten < data_size) {
+		if ((numwritten = send(SocketDes, SendBuff,
+			data_size - total_numwritten, Flag)) == -1) {
+			perror("Failed to send()");
+			DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+			return (FAIL);
+		}
+
+		/* Sent successfully at first attempt no more retries */
+		if (numwritten == data_size) {
+			total_numwritten = numwritten;
+			break;
+		}
+
+		/* If socket is busy we may hit this condition */
+		if (numwritten != data_size - total_numwritten) {
+			DPRINT_DBG(OUTPUT, "wanted to send %d bytes sent only %d bytes\n",
+				data_size - total_numwritten, numwritten);
+		}
+
+		/* Now send the remaining buffer */
+		total_numwritten += numwritten;
+		SendBuff += numwritten;
+	}
+
+	return total_numwritten;
+}
+
+/* Receive the response from the opened TCP stream socket */
+int
+rwl_receive_from_streamsocket(int SocketDes, char* RecvBuff, int data_size, int Flag)
+{
+	int numread = 0;
+	int total_numread = 0;
+
+	while (total_numread < data_size) {
+		if ((numread = recv(SocketDes, RecvBuff, data_size - total_numread, Flag)) == -1) {
+			perror("Failed to Receive()");
+			DPRINT_ERR(ERR, "\n errno:%d\n", errno);
+			return FAIL;
+		}
+
+		if (numread != data_size - total_numread) {
+			DPRINT_DBG(OUTPUT, "asked %d bytes got %d bytes\n",
+				data_size - total_numread, numread);
+		}
+
+		if (numread == 0)
+			break;
+
+		total_numread += numread;
+		RecvBuff += numread;
+	}
+
+	return numread;
+}
+
+
+int
+rwl_init_server_socket_setup(int argc, char** argv, uint remote_type)
+{
+	char netif[MAX_INTERFACE_NAME];
+	unsigned short servPort;
+	struct sockaddr_in ServerAddress;
+	int err, SockDes, val;
+
+	/* Default option */
+	servPort = DEFAULT_SERVER_PORT;
+
+	strcpy(netif, "eth0");
+
+	/* User option can override default arguments */
+	if (argc == 3) {
+		argv++;
+
+		if (isalpha(**argv) == FALSE) {
+			DPRINT_ERR(ERR, "USAGE ERROR:Incorrect network interface\n");
+			return FAIL;
+		}
+		strcpy(netif, *argv);
+		argv++;
+
+		if (isdigit(**argv) == FALSE) {
+			DPRINT_ERR(ERR, "USAGE ERROR:Incorrect port\n");
+			return FAIL;
+		}
+		servPort = atoi(*argv);
+	}
+
+	if (argc == 2) {
+		argv++;
+
+		if (isalpha(**argv) == FALSE) {
+			if (isdigit(**argv) == FALSE) {
+				DPRINT_ERR(ERR, "USAGE ERROR\n");
+				return FAIL;
+			}
+			else
+				servPort = atoi(*argv);
+		}
+		else
+			strcpy(netif, *argv);
+	}
+
+	DPRINT_INFO(OUTPUT, "INFO: Network Interface:%s, Port:%d\n",
+		netif, servPort);
+
+	if ((SockDes = (*(int *)rwl_open_transport(remote_type, NULL, 0, 0))) == FAIL)
+	   return FAIL;
+
+	val = 1;
+	if ((rwl_set_socket_option(SockDes, SOL_SOCKET, SO_REUSEADDR, val)) == FAIL)
+		return FAIL;
+
+	memset(&ServerAddress, 0, sizeof(ServerAddress));
+
+	rwl_GetifAddr(netif, &ServerAddress);
+	ServerAddress.sin_family = AF_INET; /* host byte order */
+	ServerAddress.sin_port = hton16(servPort); /* short, network byte order */
+
+	if (((err = rwl_bindsocket(SockDes, (struct sockaddr *)&ServerAddress,
+	sizeof(ServerAddress))) == FAIL))
+		return err;
+	if ((err = rwl_listensocket(SockDes, BACKLOG)) == FAIL)
+		return err;
+
+	DPRINT_DBG(OUTPUT, "Waiting for client to connect...\n");
+
+	return SockDes;
+}
+
+int rwl_GetifAddr(char *ifname, struct sockaddr_in *sa)
+{
+	struct ifreq ifr;
+	int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+
+	if (fd < 0)
+	{
+	   DPRINT_ERR(ERR, "socket open error\n");
+	   return FAIL;
+	}
+
+	strcpy(ifr.ifr_name, ifname);
+	ifr.ifr_addr.sa_family = AF_INET;
+	if (ioctl(fd, SIOCGIFADDR, &ifr) == 0)
+	{
+		 memcpy(sa, (struct sockaddr_in *)&ifr.ifr_addr, sizeof(struct sockaddr_in));
+	         close(fd);
+		 return SUCCESS;
+	}
+	close(fd);
+	return FAIL;
+}
+#endif /* RWL_SOCKET */
+
+#if defined(RWL_SERIAL) || defined(RWL_DONGLE)
+static speed_t
+rwl_termios_b(int baud)
+{
+	speed_t result;
+	switch (baud) {
+		case 50:     result = B50;     break;
+		case 75:     result = B75;     break;
+		case 110:    result = B110;    break;
+		case 134:    result = B134;    break;
+		case 150:    result = B150;    break;
+		case 200:    result = B200;    break;
+		case 300:    result = B300;    break;
+		case 600:    result = B600;    break;
+		case 1200:   result = B1200;   break;
+		case 1800:   result = B1800;   break;
+		case 2400:   result = B2400;   break;
+		case 4800:   result = B4800;   break;
+		case 9600:   result = B9600;   break;
+		case 19200:  result = B19200;  break;
+		case 38400:  result = B38400;  break;
+		case 57600:  result = B57600;  break;
+		case 115200: result = B115200; break;
+		case 230400: result = B230400; break;
+		default:     result = B115200; break;
+	}
+	return result;
+}
+static int
+rwl_open_serial(int remote_type, char *port, int baud)
+{
+	struct termios tio;
+	int fCom;
+	long BAUD, DATABITS, STOPBITS, PARITYON;
+	speed_t baud_rate;
+
+	DPRINT_DBG(OUTPUT, "\n rwl_open_serial:%s\n", port);
+	if (remote_type == REMOTE_DONGLE)
+		fCom = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
+	else
+		fCom = open(port, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC);
+	if (fCom < 0) {
+		DPRINT_ERR(ERR, "open COM failed with error %d.\n", errno);
+		return fCom;
+	} else {
+		/* To make the read as a blocking operation */
+		fcntl(fCom, F_SETFL, 0);
+	}
+
+	bzero(&tio, sizeof(tio));
+	/* Get the current option for the port... */
+	tcgetattr(fCom, &tio);
+	/* Set the baud rate */
+	cfsetispeed(&tio, rwl_termios_b(baud));
+	cfsetospeed(&tio, rwl_termios_b(baud));
+	if (remote_type == REMOTE_DONGLE) {
+		if (tcsetattr(fCom, TCSANOW, &tio) < 0) {
+			perror("tcsetattr:setspeed");
+			return FAIL;
+		}
+
+		baud_rate = cfgetospeed(&tio);
+		DPRINT_DBG(OUTPUT, "Baud_rate set is:%d\n", baud_rate);
+
+		BAUD = baud_rate;
+		DATABITS = CS8;
+		STOPBITS = 1;
+		PARITYON = 0;
+
+		tio.c_cflag = BAUD |  DATABITS | STOPBITS | PARITYON | CLOCAL | CREAD;
+		tio.c_iflag = IGNPAR;
+		tio.c_oflag = 0;
+		tio.c_lflag = 0;
+		tio.c_cc[VMIN] = VMIN_VAL;
+		tio.c_cc[VTIME] = VTIME_VAL;
+
+		tcflush(fCom, TCIOFLUSH);
+		if (tcsetattr(fCom, TCSANOW, &tio) < 0) {
+			perror("tcsetattr:");
+			return FAIL;
+		}
+
+		if (tcgetattr(fCom, &tio) < 0) {
+			perror("tcgetattr:");
+			return FAIL;
+		}
+
+		DPRINT_DBG(OUTPUT, "tcgetattr:VMIN is:%d\n", tio.c_cc[VMIN]);
+		DPRINT_DBG(OUTPUT, "tcgetattr:VTIME is:%d\n", tio.c_cc[VTIME]);
+		tcflush(fCom, TCIOFLUSH);
+	}
+	else {
+		UNUSED_PARAMETER(PARITYON);
+		UNUSED_PARAMETER(STOPBITS);
+		UNUSED_PARAMETER(DATABITS);
+		UNUSED_PARAMETER(BAUD);
+		UNUSED_PARAMETER(baud_rate);
+
+		/* Enable the receiver and set local mode  */
+		tio.c_cflag |= (CLOCAL | CREAD);
+
+		tio.c_cflag &= ~PARENB;
+		tio.c_cflag &= ~CSTOPB;
+		tio.c_cflag &= ~CSIZE;
+		tio.c_cflag |= CS8;
+		tio.c_cc[VTIME] = 255;
+		tio.c_cc[VMIN] = 1;
+
+		tio.c_iflag = 0;
+		tio.c_iflag  |= IGNBRK;
+
+		tio.c_oflag  &= ~OPOST;
+#ifndef __FreeBSD__
+		tio.c_oflag  &= ~OLCUC;
+#endif
+		tio.c_oflag  &= ~ONLCR;
+		tio.c_oflag  &= ~OCRNL;
+		tio.c_oflag  &= ~ONOCR;
+		tio.c_oflag  &= ~ONLRET;
+#ifndef __FreeBSD__
+		tio.c_oflag  &= ~OFILL;
+#endif
+
+		tio.c_lflag &= ~ICANON;
+		tio.c_lflag &= ~ISIG;
+#ifndef __FreeBSD__
+		tio.c_lflag &= ~XCASE;
+#endif
+		tio.c_lflag &= ~ECHO;
+		tio.c_lflag &= ~FLUSHO;
+		tio.c_lflag &= ~IEXTEN;
+		tio.c_lflag |= NOFLSH;
+		/* Set the new tio for the port... */
+		tcsetattr(fCom, TCSANOW, &tio);
+		tcflush(fCom, TCIOFLUSH);
+	}
+	return (fCom);
+}
+
+int
+rwl_write_serial_port(void* hndle, char* write_buf, unsigned long size, unsigned long *numwritten)
+{
+	int ret;
+
+	ret = write((*(int *)hndle), (const void*)write_buf, size);
+	*numwritten = ret;
+	if (ret == -1) {
+		perror("WriteToPort Failed");
+		DPRINT_ERR(ERR, "Errno:%d\n", errno);
+		return FAIL;
+	}
+	if (*numwritten != size) {
+		DPRINT_ERR(ERR, "rwl_write_serial_port failed numwritten %ld != len %ld\n",
+		*numwritten, size);
+		return FAIL;
+	}
+	return SUCCESS;
+}
+
+static int
+rwl_check_inqueue(void *hndle, int timeout_ms, int *bufferlen)
+{
+	int inbuflen = 0;
+	int stat;
+	int delay_ms = 10;
+	int n;
+	int div = timeout_ms / delay_ms;
+	if (bufferlen)
+		*bufferlen = 0;
+	for (n = 0; n < div; n++)
+	{
+		stat = ioctl(*(int *)hndle, FIONREAD, &inbuflen);
+		if (stat == 0 && 0 < inbuflen)
+		{
+			if (bufferlen)
+				*bufferlen = inbuflen;
+			return 0;
+		}
+		usleep(delay_ms * 1000);
+	}
+
+	return -1;
+}
+
+int
+rwl_read_serial_port(void* hndle, char* read_buf, uint data_size, uint *numread)
+{
+	int ret;
+	uint total_numread = 0;
+	int count = 0;
+	int inqueuelen;
+	int readlen;
+	while (total_numread < data_size) {
+		if (rwl_check_inqueue (hndle, 10000, &inqueuelen) != 0)
+		{
+				DPRINT_ERR(ERR, "input buffer is empty\n");
+			return FAIL;
+		}
+		readlen = data_size - total_numread;
+		if (inqueuelen < readlen)
+			readlen = inqueuelen;
+
+		ret = read(*(int *)hndle, read_buf, readlen);
+
+		*numread = ret;
+		if (ret == -1) {
+			perror("ReadFromPort Failed");
+			DPRINT_ERR(ERR, "Errno:%d\n", errno);
+			return FAIL;
+		}
+		if (*numread != data_size - total_numread) {
+			DPRINT_DBG(OUTPUT, "asked for %d bytes got %d bytes\n",
+				data_size - total_numread, *numread);
+		}
+		if ((*numread == 0) && (count > 10000)) {
+			DPRINT_ERR(ERR, "rwl_read_serial_port failed after %d retries\n",
+				count);
+			return FAIL;
+		}
+
+		total_numread += *numread;
+		read_buf += *numread;
+		count++;
+	}
+	return SUCCESS;
+}
+
+void
+rwl_sync_delay(uint noframes)
+{
+	if (noframes > 1) {
+		rwl_sleep(LINUX_SYNC_DELAY);
+	}
+}
+
+#endif /* RWL_DONGLE ||RWL_SERIAL */
+
+#if defined(RWL_DONGLE) || defined(RWL_SOCKET) || defined(RWL_SERIAL)
+void*
+rwl_open_transport(int remote_type, char *port, int ReadTotalTimeout, int debug)
+{
+	void* hndle;
+
+	UNUSED_PARAMETER(port);
+	UNUSED_PARAMETER(ReadTotalTimeout);
+	UNUSED_PARAMETER(debug);
+
+	switch (remote_type) {
+#if defined(RWL_DONGLE) || defined(RWL_SERIAL)
+	case REMOTE_SERIAL:
+#ifdef RWL_SERIAL
+			g_rwl_device_name_serial = port;
+#endif
+	case REMOTE_DONGLE:
+			if ((g_irh = rwl_open_serial(remote_type, g_rwl_device_name_serial,
+					g_rwl_device_baud)) == FAIL) {
+			/* Initial port opening settings failed in reboot.
+			 * So retry opening the serial port
+			 */
+				if ((g_irh = rwl_open_serial(remote_type, g_rwl_device_name_serial,
+						g_rwl_device_baud)) == FAIL) {
+					DPRINT_ERR(ERR, "Can't open serial port\n");
+					return NULL;
+				}
+			}
+			break;
+#endif /* RWL_DONGLE || RWL_SERIAL */
+
+#ifdef RWL_SOCKET
+		case REMOTE_SOCKET:
+			if ((g_irh = rwl_opensocket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == FAIL) {
+				DPRINT_ERR(ERR, "\nCan't open socket \n");
+				return NULL;
+			}
+
+			break;
+#endif /* RWL_SOCKET */
+
+		default:
+		DPRINT_ERR(ERR, "rwl_open_transport: Unknown remote_type %d\n", remote_type);
+		return NULL;
+		break;
+	} /* end - switch case */
+
+	hndle = (void*) &g_irh;
+	return hndle;
+}
+
+int
+rwl_close_transport(int remote_type, void* Des)
+{
+	switch (remote_type) {
+#ifdef RWL_SOCKET
+		case REMOTE_SOCKET:
+			if (Des != NULL) {
+				if (rwl_closesocket(*(int *)Des) == FAIL)
+					return FAIL;
+			}
+		break;
+#endif /* RWL_SOCKET */
+
+#if defined(RWL_DONGLE) || defined(RWL_SERIAL)
+	case REMOTE_DONGLE:
+	case REMOTE_SERIAL:
+			if (close(*(int *)Des) == -1)
+				return FAIL;
+		break;
+#endif /* RWL_DONGLE || RWL_SERIAL */
+
+		default:
+			DPRINT_ERR(ERR, "close_pipe: Unknown remote_type %d\n", remote_type);
+		break;
+	}
+	return SUCCESS;
+}
+#endif /* #if defined (RWL_DONGLE) || defined (RWL_SOCKET) */
+
+void
+rwl_sleep(int delay)
+{
+	usleep(delay * MICRO_SEC_CONVERTER_VAL);
+}
+
+#if defined(WLMSO) || defined(WLDYNLIB)
+int
+rwl_init_socket(void)
+{
+	return 0;
+}
+#endif
diff --git a/wl/src/wl/exe/wlu_rates_matrix.c b/wl/src/wl/exe/wlu_rates_matrix.c
new file mode 100644
index 0000000..3924ff2
--- /dev/null
+++ b/wl/src/wl/exe/wlu_rates_matrix.c
@@ -0,0 +1,1119 @@
+/*
+ * This module does provides various mappings to or from the CLM rate indexes.
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ */
+/*FILE-CSTYLED*/
+
+#include <stdio.h>
+#include <typedefs.h>
+#include <assert.h>
+#include "wlu_rates_matrix.h"
+
+#define CLM_NO_RATE_STRING "NO_RATE"
+#define EXP_MODE_UNKNOWN   "Unknown expansion mode"
+#define AUTO_RATESPEC 0x0
+#define MHZ_TO_HALF_MHZ 2
+
+typedef enum exp_mode {
+	EXP_MODE_ID_DEF = 0,
+	EXP_MODE_ID_STBC,
+	EXP_MODE_ID_TXBF,
+	EXP_MODE_ID_MAX
+} exp_mode_t;
+
+static reg_rate_index_t get_legacy_reg_rate_index(int rate_hmhz, int tx_expansion, exp_mode_t mode);
+static reg_rate_index_t get_ht_reg_rate_index(int mcs, int tx_expansion, exp_mode_t mode);
+static reg_rate_index_t get_vht_reg_rate_index(int mcs, int nss, int tx_expansion, exp_mode_t mode);
+static int get_legacy_rate_identifier(int rate_hmhz);
+static int get_legacy_mode_identifier(int tx_expansion, exp_mode_t mode);
+static int get_vht_rate_identifier(int vht_mcs_index);
+static int get_vht_ss1_mode_identifier(int tx_expansion, exp_mode_t mode);
+static int get_vht_ss2_mode_identifier(int tx_expansion, exp_mode_t mode);
+static int get_vht_ss3_mode_identifier(int tx_expansion, exp_mode_t mode);
+static int get_vht_ss4_mode_identifier(int tx_expansion, exp_mode_t mode);
+static const char *get_mode_name(exp_mode_t mode);
+
+enum {
+	LEGACY_RATE_ID_NO_RATE = -1,
+	LEGACY_RATE_ID_1MHZ = 0,
+	LEGACY_RATE_ID_2MHZ,
+	LEGACY_RATE_ID_5_5MHZ,
+	LEGACY_RATE_ID_11MHZ,
+	LEGACY_RATE_ID_6MHZ,
+	LEGACY_RATE_ID_9MHZ,
+	LEGACY_RATE_ID_12MHZ,
+	LEGACY_RATE_ID_18MHZ,
+	LEGACY_RATE_ID_24MHZ,
+	LEGACY_RATE_ID_36MHZ,
+	LEGACY_RATE_ID_48MHZ,
+	LEGACY_RATE_ID_54MHZ,
+	LEGACY_RATE_ID_MAX
+};
+
+enum {
+	LEGACY_MODE_ID_NONE = 0,
+	LEGACY_MODE_ID_TXEXP1,
+	LEGACY_MODE_ID_TXEXP2,
+	LEGACY_MODE_ID_TXEXP3,
+	LEGACY_MODE_ID_TXBF1,
+	LEGACY_MODE_ID_TXBF2,
+	LEGACY_MODE_ID_TXBF3,
+	LEGACY_MODE_ID_MAX
+};
+
+enum {
+	VHT_RATE_INDEX_0 = 0,
+	VHT_RATE_INDEX_1,
+	VHT_RATE_INDEX_2,
+	VHT_RATE_INDEX_3,
+	VHT_RATE_INDEX_4,
+	VHT_RATE_INDEX_5,
+	VHT_RATE_INDEX_6,
+	VHT_RATE_INDEX_7,
+	VHT_RATE_INDEX_8,
+	VHT_RATE_INDEX_9,
+	VHT_RATE_INDEX_10,
+	VHT_RATE_INDEX_11,
+	VHT_RATE_INDEX_MAX
+};
+
+enum {
+	VHT_SS1_MODE_ID_NONE = 0,
+	VHT_SS1_MODE_ID_CDD1,
+	VHT_SS1_MODE_ID_STBC,
+	VHT_SS1_MODE_ID_CDD2,
+	VHT_SS1_MODE_ID_STBC_SPEXP1,
+	VHT_SS1_MODE_ID_CDD3,
+	VHT_SS1_MODE_ID_STBC_SPEXP2,
+	VHT_SS1_MODE_ID_TXBF1,
+	VHT_SS1_MODE_ID_TXBF2,
+	VHT_SS1_MODE_ID_TXBF3,
+	VHT_SS1_MODE_ID_MAX
+};
+
+enum {
+	VHT_SS2_MODE_ID_NONE = 0,
+	VHT_SS2_MODE_ID_SPEXP1,
+	VHT_SS2_MODE_ID_SPEXP2,
+	VHT_SS2_MODE_ID_TXBF0,
+	VHT_SS2_MODE_ID_TXBF1,
+	VHT_SS2_MODE_ID_TXBF2,
+	VHT_SS2_MODE_ID_MAX
+};
+
+enum {
+	VHT_SS3_MODE_ID_NONE = 0,
+	VHT_SS3_MODE_ID_SPEXP1,
+	VHT_SS3_MODE_ID_TXBF0,
+	VHT_SS3_MODE_ID_TXBF1,
+	VHT_SS3_MODE_ID_MAX
+};
+
+enum {
+	VHT_SS4_MODE_ID_NONE = 0,
+	VHT_SS4_MODE_ID_TXBF0,
+	VHT_SS4_MODE_ID_MAX
+};
+
+const char *clm_rate_group_labels[] = {
+	"DSSS",
+	"OFDM",
+	"MCS0_7",
+	"VHT8_9SS1",
+	"VHT10_11SS1",
+	"DSSS_MULTI1",
+	"OFDM_CDD1",
+	"MCS0_7_CDD1",
+	"VHT8_9SS1_CDD1",
+	"VHT10_11SS1_CDD1",
+	"MCS0_7_STBC",
+	"VHT8_9SS1_STBC",
+	"VHT10_11SS1_STBC",
+	"MCS8_15",
+	"VHT8_9SS2",
+	"VHT10_11SS2",
+	"DSSS_MULTI2",
+	"OFDM_CDD2",
+	"MCS0_7_CDD2",
+	"VHT8_9SS1_CDD2",
+	"VHT10_11SS1_CDD2",
+	"MCS0_7_STBC_SPEXP1",
+	"VHT8_9SS1_STBC_SPEXP1",
+	"VHT10_11SS1_STBC_SPEXP1",
+	"MCS8_15_SPEXP1",
+	"VHT8_9SS2_SPEXP1",
+	"VHT10_11SS2_SPEXP1",
+	"MCS16_23",
+	"VHT8_9SS3",
+	"VHT10_11SS3",
+	"DSSS_MULTI3",
+	"OFDM_CDD3",
+	"MCS0_7_CDD3",
+	"VHT8_9SS1_CDD3",
+	"VHT10_11SS1_CDD3",
+	"MCS0_7_STBC_SPEXP2",
+	"VHT8_9SS1_STBC_SPEXP2",
+	"VHT10_11SS1_STBC_SPEXP2",
+	"MCS8_15_SPEXP2",
+	"VHT8_9SS2_SPEXP2",
+	"VHT10_11SS2_SPEXP2",
+	"MCS16_23_SPEXP1",
+	"VHT8_9SS3_SPEXP1",
+	"VHT10_11SS3_SPEXP1",
+	"MCS24_31",
+	"VHT8_9SS4",
+	"VHT10_11SS4",
+	"OFDM_TXBF1",
+	"MCS0_7_TXBF1",
+	"VHT8_9SS1_TXBF1",
+	"VHT10_11SS1_TXBF1",
+	"MCS8_15_TXBF0",
+	"VHT8_9SS2_TXBF0",
+	"VHT10_11SS2_TXBF0",
+	"OFDM_TXBF2",
+	"MCS0_7_TXBF2",
+	"VHT8_9SS1_TXBF2",
+	"VHT10_11SS1_TXBF2",
+	"MCS8_15_TXBF1",
+	"VHT8_9SS2_TXBF1",
+	"VHT10_11SS2_TXBF1",
+	"MCS16_23_TXBF0",
+	"VHT8_9SS3_TXBF0",
+	"VHT10_11SS3_TXBF0",
+	"OFDM_TXBF3",
+	"MCS0_7_TXBF3",
+	"VHT8_9SS1_TXBF3",
+	"VHT10_11SS1_TXBF3",
+	"MCS8_15_TXBF2",
+	"VHT8_9SS2_TXBF2",
+	"VHT10_11SS2_TXBF2",
+	"MCS16_23_TXBF1",
+	"VHT8_9SS3_TXBF1",
+	"VHT10_11SS3_TXBF1",
+	"MCS24_31_TXBF0",
+	"VHT8_9SS4_TXBF0",
+	"VHT10_11SS4_TXBF0",
+};
+
+
+const char *clm_rate_labels[] = {
+	"DSSS1",
+	"DSSS2",
+	"DSSS5",
+	"DSSS11",
+	"OFDM6",
+	"OFDM9",
+	"OFDM12",
+	"OFDM18",
+	"OFDM24",
+	"OFDM36",
+	"OFDM48",
+	"OFDM54",
+	"MCS0",
+	"MCS1",
+	"MCS2",
+	"MCS3",
+	"MCS4",
+	"MCS5",
+	"MCS6",
+	"MCS7",
+	"VHT8SS1",
+	"VHT9SS1",
+	"VHT10SS1",
+	"VHT11SS1",
+	"DSSS1_MULTI1",
+	"DSSS2_MULTI1",
+	"DSSS5_MULTI1",
+	"DSSS11_MULTI1",
+	"OFDM6_CDD1",
+	"OFDM9_CDD1",
+	"OFDM12_CDD1",
+	"OFDM18_CDD1",
+	"OFDM24_CDD1",
+	"OFDM36_CDD1",
+	"OFDM48_CDD1",
+	"OFDM54_CDD1",
+	"MCS0_CDD1",
+	"MCS1_CDD1",
+	"MCS2_CDD1",
+	"MCS3_CDD1",
+	"MCS4_CDD1",
+	"MCS5_CDD1",
+	"MCS6_CDD1",
+	"MCS7_CDD1",
+	"VHT8SS1_CDD1",
+	"VHT9SS1_CDD1",
+	"VHT10SS1_CDD1",
+	"VHT11SS1_CDD1",
+	"MCS0_STBC",
+	"MCS1_STBC",
+	"MCS2_STBC",
+	"MCS3_STBC",
+	"MCS4_STBC",
+	"MCS5_STBC",
+	"MCS6_STBC",
+	"MCS7_STBC",
+	"VHT8SS1_STBC",
+	"VHT9SS1_STBC",
+	"VHT10SS1_STBC",
+	"VHT11SS1_STBC",
+	"MCS8",
+	"MCS9",
+	"MCS10",
+	"MCS11",
+	"MCS12",
+	"MCS13",
+	"MCS14",
+	"MCS15",
+	"VHT8SS2",
+	"VHT9SS2",
+	"VHT10SS2",
+	"VHT11SS2",
+	"DSSS1_MULTI2",
+	"DSSS2_MULTI2",
+	"DSSS5_MULTI2",
+	"DSSS11_MULTI2",
+	"OFDM6_CDD2",
+	"OFDM9_CDD2",
+	"OFDM12_CDD2",
+	"OFDM18_CDD2",
+	"OFDM24_CDD2",
+	"OFDM36_CDD2",
+	"OFDM48_CDD2",
+	"OFDM54_CDD2",
+	"MCS0_CDD2",
+	"MCS1_CDD2",
+	"MCS2_CDD2",
+	"MCS3_CDD2",
+	"MCS4_CDD2",
+	"MCS5_CDD2",
+	"MCS6_CDD2",
+	"MCS7_CDD2",
+	"VHT8SS1_CDD2",
+	"VHT9SS1_CDD2",
+	"VHT10SS1_CDD2",
+	"VHT11SS1_CDD2",
+	"MCS0_STBC_SPEXP1",
+	"MCS1_STBC_SPEXP1",
+	"MCS2_STBC_SPEXP1",
+	"MCS3_STBC_SPEXP1",
+	"MCS4_STBC_SPEXP1",
+	"MCS5_STBC_SPEXP1",
+	"MCS6_STBC_SPEXP1",
+	"MCS7_STBC_SPEXP1",
+	"VHT8SS1_STBC_SPEXP1",
+	"VHT9SS1_STBC_SPEXP1",
+	"VHT10SS1_STBC_SPEXP1",
+	"VHT11SS1_STBC_SPEXP1",
+	"MCS8_SPEXP1",
+	"MCS9_SPEXP1",
+	"MCS10_SPEXP1",
+	"MCS11_SPEXP1",
+	"MCS12_SPEXP1",
+	"MCS13_SPEXP1",
+	"MCS14_SPEXP1",
+	"MCS15_SPEXP1",
+	"VHT8SS2_SPEXP1",
+	"VHT9SS2_SPEXP1",
+	"VHT10SS2_SPEXP1",
+	"VHT11SS2_SPEXP1",
+	"MCS16",
+	"MCS17",
+	"MCS18",
+	"MCS19",
+	"MCS20",
+	"MCS21",
+	"MCS22",
+	"MCS23",
+	"VHT8SS3",
+	"VHT9SS3",
+	"VHT10SS3",
+	"VHT11SS3",
+	"DSSS1_MULTI3",
+	"DSSS2_MULTI3",
+	"DSSS5_MULTI3",
+	"DSSS11_MULTI3",
+	"OFDM6_CDD3",
+	"OFDM9_CDD3",
+	"OFDM12_CDD3",
+	"OFDM18_CDD3",
+	"OFDM24_CDD3",
+	"OFDM36_CDD3",
+	"OFDM48_CDD3",
+	"OFDM54_CDD3",
+	"MCS0_CDD3",
+	"MCS1_CDD3",
+	"MCS2_CDD3",
+	"MCS3_CDD3",
+	"MCS4_CDD3",
+	"MCS5_CDD3",
+	"MCS6_CDD3",
+	"MCS7_CDD3",
+	"VHT8SS1_CDD3",
+	"VHT9SS1_CDD3",
+	"VHT10SS1_CDD3",
+	"VHT11SS1_CDD3",
+	"MCS0_STBC_SPEXP2",
+	"MCS1_STBC_SPEXP2",
+	"MCS2_STBC_SPEXP2",
+	"MCS3_STBC_SPEXP2",
+	"MCS4_STBC_SPEXP2",
+	"MCS5_STBC_SPEXP2",
+	"MCS6_STBC_SPEXP2",
+	"MCS7_STBC_SPEXP2",
+	"VHT8SS1_STBC_SPEXP2",
+	"VHT9SS1_STBC_SPEXP2",
+	"VHT10SS1_STBC_SPEXP2",
+	"VHT11SS1_STBC_SPEXP2",
+	"MCS8_SPEXP2",
+	"MCS9_SPEXP2",
+	"MCS10_SPEXP2",
+	"MCS11_SPEXP2",
+	"MCS12_SPEXP2",
+	"MCS13_SPEXP2",
+	"MCS14_SPEXP2",
+	"MCS15_SPEXP2",
+	"VHT8SS2_SPEXP2",
+	"VHT9SS2_SPEXP2",
+	"VHT10SS2_SPEXP2",
+	"VHT11SS2_SPEXP2",
+	"MCS16_SPEXP1",
+	"MCS17_SPEXP1",
+	"MCS18_SPEXP1",
+	"MCS19_SPEXP1",
+	"MCS20_SPEXP1",
+	"MCS21_SPEXP1",
+	"MCS22_SPEXP1",
+	"MCS23_SPEXP1",
+	"VHT8SS3_SPEXP1",
+	"VHT9SS3_SPEXP1",
+	"VHT10SS3_SPEXP1",
+	"VHT11SS3_SPEXP1",
+	"MCS24",
+	"MCS25",
+	"MCS26",
+	"MCS27",
+	"MCS28",
+	"MCS29",
+	"MCS30",
+	"MCS31",
+	"VHT8SS4",
+	"VHT9SS4",
+	"VHT10SS4",
+	"VHT11SS4",
+	"OFDM6_TXBF1",
+	"OFDM9_TXBF1",
+	"OFDM12_TXBF1",
+	"OFDM18_TXBF1",
+	"OFDM24_TXBF1",
+	"OFDM36_TXBF1",
+	"OFDM48_TXBF1",
+	"OFDM54_TXBF1",
+	"MCS0_TXBF1",
+	"MCS1_TXBF1",
+	"MCS2_TXBF1",
+	"MCS3_TXBF1",
+	"MCS4_TXBF1",
+	"MCS5_TXBF1",
+	"MCS6_TXBF1",
+	"MCS7_TXBF1",
+	"VHT8SS1_TXBF1",
+	"VHT9SS1_TXBF1",
+	"VHT10SS1_TXBF1",
+	"VHT11SS1_TXBF1",
+	"MCS8_TXBF0",
+	"MCS9_TXBF0",
+	"MCS10_TXBF0",
+	"MCS11_TXBF0",
+	"MCS12_TXBF0",
+	"MCS13_TXBF0",
+	"MCS14_TXBF0",
+	"MCS15_TXBF0",
+	"VHT8SS2_TXBF0",
+	"VHT9SS2_TXBF0",
+	"VHT10SS2_TXBF0",
+	"VHT11SS2_TXBF0",
+	"OFDM6_TXBF2",
+	"OFDM9_TXBF2",
+	"OFDM12_TXBF2",
+	"OFDM18_TXBF2",
+	"OFDM24_TXBF2",
+	"OFDM36_TXBF2",
+	"OFDM48_TXBF2",
+	"OFDM54_TXBF2",
+	"MCS0_TXBF2",
+	"MCS1_TXBF2",
+	"MCS2_TXBF2",
+	"MCS3_TXBF2",
+	"MCS4_TXBF2",
+	"MCS5_TXBF2",
+	"MCS6_TXBF2",
+	"MCS7_TXBF2",
+	"VHT8SS1_TXBF2",
+	"VHT9SS1_TXBF2",
+	"VHT10SS1_TXBF2",
+	"VHT11SS1_TXBF2",
+	"MCS8_TXBF1",
+	"MCS9_TXBF1",
+	"MCS10_TXBF1",
+	"MCS11_TXBF1",
+	"MCS12_TXBF1",
+	"MCS13_TXBF1",
+	"MCS14_TXBF1",
+	"MCS15_TXBF1",
+	"VHT8SS2_TXBF1",
+	"VHT9SS2_TXBF1",
+	"VHT10SS2_TXBF1",
+	"VHT11SS2_TXBF1",
+	"MCS16_TXBF0",
+	"MCS17_TXBF0",
+	"MCS18_TXBF0",
+	"MCS19_TXBF0",
+	"MCS20_TXBF0",
+	"MCS21_TXBF0",
+	"MCS22_TXBF0",
+	"MCS23_TXBF0",
+	"VHT8SS3_TXBF0",
+	"VHT9SS3_TXBF0",
+	"VHT10SS3_TXBF0",
+	"VHT11SS3_TXBF0",
+	"OFDM6_TXBF3",
+	"OFDM9_TXBF3",
+	"OFDM12_TXBF3",
+	"OFDM18_TXBF3",
+	"OFDM24_TXBF3",
+	"OFDM36_TXBF3",
+	"OFDM48_TXBF3",
+	"OFDM54_TXBF3",
+	"MCS0_TXBF3",
+	"MCS1_TXBF3",
+	"MCS2_TXBF3",
+	"MCS3_TXBF3",
+	"MCS4_TXBF3",
+	"MCS5_TXBF3",
+	"MCS6_TXBF3",
+	"MCS7_TXBF3",
+	"VHT8SS1_TXBF3",
+	"VHT9SS1_TXBF3",
+	"VHT10SS1_TXBF3",
+	"VHT11SS1_TXBF3",
+	"MCS8_TXBF2",
+	"MCS9_TXBF2",
+	"MCS10_TXBF2",
+	"MCS11_TXBF2",
+	"MCS12_TXBF2",
+	"MCS13_TXBF2",
+	"MCS14_TXBF2",
+	"MCS15_TXBF2",
+	"VHT8SS2_TXBF2",
+	"VHT9SS2_TXBF2",
+	"VHT10SS2_TXBF2",
+	"VHT11SS2_TXBF2",
+	"MCS16_TXBF1",
+	"MCS17_TXBF1",
+	"MCS18_TXBF1",
+	"MCS19_TXBF1",
+	"MCS20_TXBF1",
+	"MCS21_TXBF1",
+	"MCS22_TXBF1",
+	"MCS23_TXBF1",
+	"VHT8SS3_TXBF1",
+	"VHT9SS3_TXBF1",
+	"VHT10SS3_TXBF1",
+	"VHT11SS3_TXBF1",
+	"MCS24_TXBF0",
+	"MCS25_TXBF0",
+	"MCS26_TXBF0",
+	"MCS27_TXBF0",
+	"MCS28_TXBF0",
+	"MCS29_TXBF0",
+	"MCS30_TXBF0",
+	"MCS31_TXBF0",
+	"VHT8SS4_TXBF0",
+	"VHT9SS4_TXBF0",
+	"VHT10SS4_TXBF0",
+	"VHT11SS4_TXBF0",
+};
+
+int legacy_reg_rate_map[LEGACY_RATE_ID_MAX][LEGACY_MODE_ID_MAX] = {
+	{DSSS1,  DSSS1_MULTI1,  DSSS1_MULTI2, DSSS1_MULTI3,  NO_RATE,       NO_RATE,      NO_RATE},
+	{DSSS2,  DSSS2_MULTI1,  DSSS2_MULTI2, DSSS2_MULTI3,  NO_RATE,       NO_RATE,      NO_RATE},
+	{DSSS5,  DSSS5_MULTI1,  DSSS5_MULTI2, DSSS5_MULTI3,  NO_RATE,       NO_RATE,      NO_RATE},
+	{DSSS11, DSSS11_MULTI1, DSSS11_MULTI2,DSSS11_MULTI3, NO_RATE,       NO_RATE,      NO_RATE},
+	{OFDM6,  OFDM6_CDD1,    OFDM6_CDD2,   OFDM6_CDD3,    OFDM6_TXBF1,   OFDM6_TXBF2,  OFDM6_TXBF3},
+	{OFDM9,  OFDM9_CDD1,    OFDM9_CDD2,   OFDM9_CDD3,    OFDM9_TXBF1,   OFDM9_TXBF2,  OFDM9_TXBF3},
+	{OFDM12, OFDM12_CDD1,   OFDM12_CDD2,  OFDM12_CDD3,   OFDM12_TXBF1,  OFDM12_TXBF2, OFDM12_TXBF3},
+	{OFDM18, OFDM18_CDD1,   OFDM18_CDD2,  OFDM18_CDD3,   OFDM18_TXBF1,  OFDM18_TXBF2, OFDM18_TXBF3},
+	{OFDM24, OFDM24_CDD1,   OFDM24_CDD2,  OFDM24_CDD3,   OFDM24_TXBF1,  OFDM24_TXBF2, OFDM24_TXBF3},
+	{OFDM36, OFDM36_CDD1,   OFDM36_CDD2,  OFDM36_CDD3,   OFDM36_TXBF1,  OFDM36_TXBF2, OFDM36_TXBF3},
+	{OFDM48, OFDM48_CDD1,   OFDM48_CDD2,  OFDM48_CDD3,   OFDM48_TXBF1,  OFDM48_TXBF2, OFDM48_TXBF3},
+	{OFDM54, OFDM54_CDD1,   OFDM54_CDD2,  OFDM54_CDD3,   OFDM54_TXBF1,  OFDM54_TXBF2, OFDM54_TXBF3},
+};
+
+int vht_ss1_reg_rate_map[VHT_RATE_INDEX_MAX][VHT_SS1_MODE_ID_MAX] = {
+	{MCS0,    MCS0_CDD1,    MCS0_STBC,    MCS0_CDD2,    MCS0_STBC_SPEXP1,  MCS0_CDD3,  MCS0_STBC_SPEXP2,  MCS0_TXBF1,  MCS0_TXBF2, MCS0_TXBF3},
+	{MCS1,    MCS1_CDD1,    MCS1_STBC,    MCS1_CDD2,    MCS1_STBC_SPEXP1,  MCS1_CDD3,  MCS1_STBC_SPEXP2,  MCS1_TXBF1,  MCS1_TXBF2, MCS1_TXBF3},
+	{MCS2,    MCS2_CDD1,    MCS2_STBC,    MCS2_CDD2,    MCS2_STBC_SPEXP1,  MCS2_CDD3,  MCS2_STBC_SPEXP2,  MCS2_TXBF1,  MCS2_TXBF2, MCS2_TXBF3},
+	{MCS3,    MCS3_CDD1,    MCS3_STBC,    MCS3_CDD2,    MCS3_STBC_SPEXP1,  MCS3_CDD3,  MCS3_STBC_SPEXP2,  MCS3_TXBF1,  MCS3_TXBF2, MCS3_TXBF3},
+	{MCS4,    MCS4_CDD1,    MCS4_STBC,    MCS4_CDD2,    MCS4_STBC_SPEXP1,  MCS4_CDD3,  MCS4_STBC_SPEXP2,  MCS4_TXBF1,  MCS4_TXBF2, MCS4_TXBF3},
+	{MCS5,    MCS5_CDD1,    MCS5_STBC,    MCS5_CDD2,    MCS5_STBC_SPEXP1,  MCS5_CDD3,  MCS5_STBC_SPEXP2,  MCS5_TXBF1,  MCS5_TXBF2, MCS5_TXBF3},
+	{MCS6,    MCS6_CDD1,    MCS6_STBC,    MCS6_CDD2,    MCS6_STBC_SPEXP1,  MCS6_CDD3,  MCS6_STBC_SPEXP2,  MCS6_TXBF1,  MCS6_TXBF2, MCS6_TXBF3},
+	{MCS7,    MCS7_CDD1,    MCS7_STBC,    MCS7_CDD2,    MCS7_STBC_SPEXP1,  MCS7_CDD3,  MCS7_STBC_SPEXP2,  MCS7_TXBF1,  MCS7_TXBF2, MCS7_TXBF3},
+	{VHT8SS1, VHT8SS1_CDD1, VHT8SS1_STBC, VHT8SS1_CDD2, VHT8SS1_STBC_SPEXP1, VHT8SS1_CDD3, VHT8SS1_STBC_SPEXP2, VHT8SS1_TXBF1, VHT8SS1_TXBF2, VHT8SS1_TXBF3},
+	{VHT9SS1, VHT9SS1_CDD1, VHT9SS1_STBC, VHT9SS1_CDD2, VHT9SS1_STBC_SPEXP1, VHT9SS1_CDD3, VHT9SS1_STBC_SPEXP2, VHT9SS1_TXBF1, VHT9SS1_TXBF2, VHT9SS1_TXBF3},
+	{VHT10SS1, VHT10SS1_CDD1, VHT10SS1_STBC, VHT10SS1_CDD2, VHT10SS1_STBC_SPEXP1, VHT10SS1_CDD3, VHT10SS1_STBC_SPEXP2, VHT10SS1_TXBF1, VHT10SS1_TXBF2, VHT10SS1_TXBF3},
+	{VHT11SS1, VHT11SS1_CDD1, VHT11SS1_STBC, VHT11SS1_CDD2, VHT11SS1_STBC_SPEXP1, VHT11SS1_CDD3, VHT11SS1_STBC_SPEXP2, VHT11SS1_TXBF1, VHT11SS1_TXBF2, VHT11SS1_TXBF3},
+};
+
+int vht_ss2_reg_rate_map[VHT_RATE_INDEX_MAX][VHT_SS2_MODE_ID_MAX] = {
+	{MCS8,    MCS8_SPEXP1,   MCS8_SPEXP2,  MCS8_TXBF0,   MCS8_TXBF1, MCS8_TXBF2},
+	{MCS9,    MCS9_SPEXP1,   MCS9_SPEXP2,  MCS9_TXBF0,   MCS9_TXBF1, MCS9_TXBF2},
+	{MCS10,   MCS10_SPEXP1,  MCS10_SPEXP2, MCS10_TXBF0, MCS10_TXBF1, MCS10_TXBF2},
+	{MCS11,   MCS11_SPEXP1,  MCS11_SPEXP2, MCS11_TXBF0, MCS11_TXBF1, MCS11_TXBF2},
+	{MCS12,   MCS12_SPEXP1,  MCS12_SPEXP2, MCS12_TXBF0, MCS12_TXBF1, MCS12_TXBF2},
+	{MCS13,   MCS13_SPEXP1,  MCS13_SPEXP2, MCS13_TXBF0, MCS13_TXBF1, MCS13_TXBF2},
+	{MCS14,   MCS14_SPEXP1,  MCS14_SPEXP2, MCS14_TXBF0, MCS14_TXBF1, MCS14_TXBF2},
+	{MCS15,   MCS15_SPEXP1,  MCS15_SPEXP2, MCS15_TXBF0, MCS15_TXBF1, MCS15_TXBF2},
+	{VHT8SS2, VHT8SS2_SPEXP1,VHT8SS2_SPEXP2,VHT8SS2_TXBF0, VHT8SS2_TXBF1, VHT8SS2_TXBF2},
+	{VHT9SS2, VHT9SS2_SPEXP1,VHT9SS2_SPEXP2,VHT9SS2_TXBF0, VHT9SS2_TXBF1, VHT9SS2_TXBF2},
+	{VHT10SS2, VHT10SS2_SPEXP1,VHT10SS2_SPEXP2,VHT10SS2_TXBF0, VHT10SS2_TXBF1, VHT10SS2_TXBF2},
+	{VHT11SS2, VHT11SS2_SPEXP1,VHT11SS2_SPEXP2,VHT11SS2_TXBF0, VHT11SS2_TXBF1, VHT11SS2_TXBF2},
+};
+
+int vht_ss3_reg_rate_map[VHT_RATE_INDEX_MAX][VHT_SS3_MODE_ID_MAX] = {
+	{MCS16,      MCS16_SPEXP1, MCS16_TXBF0, MCS16_TXBF1},
+	{MCS17,      MCS17_SPEXP1, MCS17_TXBF0, MCS17_TXBF1},
+	{MCS18,      MCS18_SPEXP1, MCS18_TXBF0, MCS18_TXBF1},
+	{MCS19,      MCS19_SPEXP1, MCS19_TXBF0, MCS19_TXBF1},
+	{MCS20,      MCS20_SPEXP1, MCS20_TXBF0, MCS20_TXBF1},
+	{MCS21,      MCS21_SPEXP1, MCS21_TXBF0, MCS21_TXBF1},
+	{MCS22,      MCS22_SPEXP1, MCS22_TXBF0, MCS22_TXBF1},
+	{MCS23,      MCS23_SPEXP1, MCS23_TXBF0, MCS23_TXBF1},
+	{VHT8SS3,    VHT8SS3_SPEXP1, VHT8SS3_TXBF0, VHT8SS3_TXBF1},
+	{VHT9SS3,    VHT9SS3_SPEXP1, VHT9SS3_TXBF0, VHT9SS3_TXBF1},
+	{VHT10SS3,   VHT10SS3_SPEXP1, VHT10SS3_TXBF0, VHT10SS3_TXBF1},
+	{VHT11SS3,   VHT11SS3_SPEXP1, VHT11SS3_TXBF0, VHT11SS3_TXBF1},
+};
+
+
+int vht_ss4_reg_rate_map[VHT_RATE_INDEX_MAX][VHT_SS4_MODE_ID_MAX] = {
+	{MCS24,      MCS24_TXBF0},
+	{MCS25,      MCS25_TXBF0},
+	{MCS26,      MCS26_TXBF0},
+	{MCS27,      MCS27_TXBF0},
+	{MCS28,      MCS28_TXBF0},
+	{MCS29,      MCS29_TXBF0},
+	{MCS30,      MCS30_TXBF0},
+	{MCS31,      MCS31_TXBF0},
+	{VHT8SS4,    VHT8SS4_TXBF0},
+	{VHT9SS4,    VHT9SS4_TXBF0},
+	{VHT10SS4,   VHT10SS4_TXBF0},
+	{VHT11SS4,   VHT11SS4_TXBF0},
+};
+
+const char *exp_mode_name[EXP_MODE_ID_MAX] = {
+	"CDD",
+	"STBC",
+	"TXBF"
+};
+
+const char *
+get_clm_rate_group_label(int rategroup)
+{
+	return clm_rate_group_labels[rategroup];
+}
+
+const char *
+get_reg_rate_string_from_ratespec(int ratespec)
+{
+	reg_rate_index_t index = get_reg_rate_index_from_ratespec(ratespec);
+
+	if (index >= 0)
+	{
+		return clm_rate_labels[index];
+	}
+	return CLM_NO_RATE_STRING;
+}
+
+reg_rate_index_t
+get_reg_rate_index_from_ratespec(int ratespec)
+{
+	uint encode, rate, txexp;
+	bool stbc,txbf;
+	int rate_index = NO_RATE;
+	exp_mode_t expmode = EXP_MODE_ID_DEF;
+
+	/* If auto is set, we don't get a ratespec that can be decoded */
+	if (ratespec == AUTO_RATESPEC)
+		return rate_index;
+
+	encode = (ratespec & WL_RSPEC_ENCODING_MASK);
+	rate   = (ratespec & WL_RSPEC_RATE_MASK);
+	txexp  = (ratespec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT;
+	stbc   = (ratespec & WL_RSPEC_STBC) != 0;
+	txbf   = (ratespec & WL_RSPEC_TXBF) != 0;
+
+	if (stbc && txbf) {
+		return rate_index;
+	} else if (txbf) {
+		expmode = EXP_MODE_ID_TXBF;
+	} else if (stbc) {
+		expmode = EXP_MODE_ID_STBC;
+	}
+
+	if (encode == WL_RSPEC_ENCODE_RATE) {
+		rate_index = get_legacy_reg_rate_index(rate, txexp, expmode);
+	} else if (encode == WL_RSPEC_ENCODE_HT) {
+		rate_index = get_ht_reg_rate_index(rate, txexp, expmode);
+	} else if (encode == WL_RSPEC_ENCODE_VHT) {
+		uint mcs = (ratespec & WL_RSPEC_VHT_MCS_MASK);
+		uint nss = (ratespec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
+		rate_index = get_vht_reg_rate_index(mcs, nss, txexp, expmode);
+	}
+
+	return rate_index;
+}
+
+reg_rate_index_t
+get_legacy_reg_rate_index(int rate_hmhz, int tx_expansion, exp_mode_t expmode)
+{
+	reg_rate_index_t index = NO_RATE;
+	int rate_id;
+	rate_id = get_legacy_rate_identifier(rate_hmhz);
+	if (rate_id == LEGACY_RATE_ID_NO_RATE || (expmode == EXP_MODE_ID_TXBF && rate_id < LEGACY_RATE_ID_6MHZ))
+	{
+		fprintf(stderr, "ERROR: Bad legacy rate spec: %d\n", rate_hmhz);
+	}
+	else
+	{
+		index = legacy_reg_rate_map[rate_id][get_legacy_mode_identifier(tx_expansion, expmode)];
+	}
+	return index;
+}
+
+static int get_legacy_rate_identifier(int rate_hmhz)
+{
+	int rate_lut[LEGACY_RATE_ID_MAX];
+	int rate_index = LEGACY_RATE_ID_NO_RATE;
+	int i;
+
+	rate_lut[LEGACY_RATE_ID_1MHZ]   = 1 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_2MHZ]   = 2 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_5_5MHZ] = 11; /* 5.5 * MHZ_TO_HALF_MHZ */
+	rate_lut[LEGACY_RATE_ID_11MHZ]  = 11 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_6MHZ]   = 6 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_9MHZ]   = 9 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_12MHZ]  = 12 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_18MHZ]  = 18 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_24MHZ]  = 24 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_36MHZ]  = 36 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_48MHZ]  = 48 * MHZ_TO_HALF_MHZ;
+	rate_lut[LEGACY_RATE_ID_54MHZ]  = 54 * MHZ_TO_HALF_MHZ;
+
+	for (i = 0; i < LEGACY_RATE_ID_MAX; i++)
+	{
+		if (rate_lut[i] == rate_hmhz)
+		{
+			rate_index = i;
+			break;
+		}
+	}
+
+	return rate_index;
+}
+
+static int get_legacy_mode_identifier(int tx_expansion, exp_mode_t expmode)
+{
+	int mode_identifier = 0;
+
+	if (tx_expansion == 0)
+	{
+		mode_identifier = LEGACY_MODE_ID_NONE;
+	}
+	else if (tx_expansion == 1)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = LEGACY_MODE_ID_TXEXP1;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = LEGACY_MODE_ID_TXBF1;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad legacy tx_expansion spec: %d expansion mode %s\n",
+				 tx_expansion, get_mode_name(expmode));
+			break;
+		}
+	}
+	else if (tx_expansion == 2)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = LEGACY_MODE_ID_TXEXP2;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = LEGACY_MODE_ID_TXBF2;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad legacy tx_expansion spec: %d expansion mode %s\n",
+				 tx_expansion, get_mode_name(expmode));
+			break;
+		}
+	}
+	else if (tx_expansion == 3)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = LEGACY_MODE_ID_TXEXP3;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = LEGACY_MODE_ID_TXBF3;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad legacy tx_expansion spec: %d expansion mode %s\n",
+				 tx_expansion, get_mode_name(expmode));
+			break;
+		}
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad legacy tx_expansion spec: %d expansion mode %s\n", tx_expansion,
+				get_mode_name(expmode));
+	}
+
+	return mode_identifier;
+}
+
+reg_rate_index_t
+get_ht_reg_rate_index(int mcs, int tx_expansion, exp_mode_t expmode)
+{
+	reg_rate_index_t rate_index = NO_RATE;
+	int vht_mcs, nss;
+
+	if (mcs > WLC_MAXMCS)
+	{
+		fprintf(stderr, "ERROR: Bad ht mcs spec: %d\n", mcs);
+	}
+	else
+	{
+		if (IS_PROPRIETARY_11N_MCS(mcs)) {
+			switch (mcs) {
+			case 87:
+				nss = 1;
+				vht_mcs = VHT_RATE_INDEX_8;
+				break;
+			case 99:
+				nss = 2;
+				vht_mcs = VHT_RATE_INDEX_8;
+				break;
+			case 101:
+				nss = 3;
+				vht_mcs = VHT_RATE_INDEX_8;
+				break;
+			case 88:
+				nss = 1;
+				vht_mcs = VHT_RATE_INDEX_9;
+				break;
+			case 100:
+				nss = 2;
+				vht_mcs = VHT_RATE_INDEX_9;
+				break;
+			case 102:
+				nss = 3;
+				vht_mcs = VHT_RATE_INDEX_9;
+				break;
+			default:
+				assert(0);
+				return rate_index;
+			}
+		} else {
+			vht_mcs = mcs % 8;
+			nss = (mcs / 8) + 1;
+		}
+		rate_index = get_vht_reg_rate_index(vht_mcs, nss, tx_expansion, expmode);
+	}
+
+	return rate_index;
+}
+
+reg_rate_index_t
+get_vht_reg_rate_index(int mcs, int nss, int tx_expansion, exp_mode_t expmode)
+{
+	reg_rate_index_t rate_index = NO_RATE;
+	int rate_id = get_vht_rate_identifier(mcs);
+
+	if (nss == 1)
+	{
+		rate_index = vht_ss1_reg_rate_map[rate_id][get_vht_ss1_mode_identifier(tx_expansion, expmode)];
+	}
+	else if (nss == 2)
+	{
+		rate_index = vht_ss2_reg_rate_map[rate_id][get_vht_ss2_mode_identifier(tx_expansion, expmode)];
+	}
+	else if (nss == 3)
+	{
+		rate_index = vht_ss3_reg_rate_map[rate_id][get_vht_ss3_mode_identifier(tx_expansion, expmode)];
+	}
+	else if (nss == 4)
+	{
+		rate_index = vht_ss4_reg_rate_map[rate_id][get_vht_ss4_mode_identifier(tx_expansion, expmode)];
+	}
+
+	return rate_index;
+}
+
+static int get_vht_rate_identifier(int vht_mcs_index)
+{
+	int rate_index = 0;
+
+	if (vht_mcs_index >= VHT_RATE_INDEX_0 && vht_mcs_index < VHT_RATE_INDEX_MAX)
+	{
+		rate_index = vht_mcs_index;
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad vht mcs spec: %d\n", vht_mcs_index);
+	}
+	return rate_index;
+}
+
+static int get_vht_ss1_mode_identifier(int tx_expansion, exp_mode_t expmode)
+{
+	int mode_identifier = 0;
+
+	if (tx_expansion == 0)
+	{
+		switch (expmode)
+		{
+			case EXP_MODE_ID_DEF:
+				mode_identifier = VHT_SS1_MODE_ID_NONE;
+				break;
+			case EXP_MODE_ID_STBC:
+				mode_identifier = VHT_SS1_MODE_ID_STBC;
+				break;
+			default:
+				fprintf(stderr, "ERROR: Bad vht ss1 mode: %d, expansion mode %s\n", tx_expansion,
+						get_mode_name(expmode));
+				break;
+		}
+	}
+	else if (tx_expansion == 1)
+	{
+		switch (expmode)
+		{
+			case EXP_MODE_ID_DEF:
+				mode_identifier = VHT_SS1_MODE_ID_CDD1;
+				break;
+			case EXP_MODE_ID_STBC:
+				mode_identifier = VHT_SS1_MODE_ID_STBC_SPEXP1;
+				break;
+			case EXP_MODE_ID_TXBF:
+				mode_identifier = VHT_SS1_MODE_ID_TXBF1;
+				break;
+			default:
+				fprintf(stderr, "ERROR: Bad vht ss1 mode: %d, expansion mode %s\n", tx_expansion,
+						get_mode_name(expmode));
+				break;
+		}
+	}
+	else if (tx_expansion == 2)
+	{
+		switch (expmode)
+		{
+			case EXP_MODE_ID_DEF:
+				mode_identifier = VHT_SS1_MODE_ID_CDD2;
+				break;
+			case EXP_MODE_ID_STBC:
+				mode_identifier = VHT_SS1_MODE_ID_STBC_SPEXP2;
+				break;
+			case EXP_MODE_ID_TXBF:
+				mode_identifier = VHT_SS1_MODE_ID_TXBF2;
+				break;
+			default:
+				fprintf(stderr, "ERROR: Bad vht ss1 mode: %d, expansion mode %s\n", tx_expansion,
+						get_mode_name(expmode));
+				break;
+		}
+	}
+	else if (tx_expansion == 3)
+	{
+		switch (expmode)
+		{
+			case EXP_MODE_ID_DEF:
+				mode_identifier = VHT_SS1_MODE_ID_CDD3;
+				break;
+			case EXP_MODE_ID_TXBF:
+				mode_identifier = VHT_SS1_MODE_ID_TXBF3;
+				break;
+			default:
+				fprintf(stderr, "ERROR: Bad vht ss1 mode: %d, expansion mode %s\n", tx_expansion,
+						get_mode_name(expmode));
+				break;
+		}
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad vht ss1 mode: %d, expansion mode: %s\n", tx_expansion,
+				 get_mode_name(expmode));
+	}
+
+	return mode_identifier;
+}
+
+static int get_vht_ss2_mode_identifier(int tx_expansion, exp_mode_t expmode)
+{
+	int mode_identifier = 0;
+
+	if (tx_expansion == 0)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = VHT_SS2_MODE_ID_NONE;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = VHT_SS2_MODE_ID_TXBF0;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad vht ss2 mode: %d, expansion mode %s\n", tx_expansion,
+				get_mode_name(expmode));
+			break;
+		}
+	}
+	else if (tx_expansion == 1)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = VHT_SS2_MODE_ID_SPEXP1;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = VHT_SS2_MODE_ID_TXBF1;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad vht ss2 mode: %d, expansion mode %s\n", tx_expansion,
+				  get_mode_name(expmode));
+			break;
+		}
+	}
+	else if (tx_expansion == 2)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = VHT_SS2_MODE_ID_SPEXP2;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = VHT_SS2_MODE_ID_TXBF2;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad vht ss2 mode: %d, expansion mode %s\n", tx_expansion,
+				  get_mode_name(expmode));
+			break;
+		}
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad vht ss2 mode: %d expansion mode: %s\n", tx_expansion,
+			   get_mode_name(expmode));
+	}
+
+	return mode_identifier;
+}
+
+static int get_vht_ss3_mode_identifier(int tx_expansion, exp_mode_t expmode)
+{
+	int mode_identifier = 0;
+
+	if (tx_expansion == 0)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = VHT_SS3_MODE_ID_NONE;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = VHT_SS3_MODE_ID_TXBF0;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad vht ss3 mode: %d, expansion mode: %s\n", tx_expansion
+					, get_mode_name(expmode));
+			break;
+		}
+	}
+	else if (tx_expansion == 1)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = VHT_SS3_MODE_ID_SPEXP1;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = VHT_SS3_MODE_ID_TXBF1;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad vht ss3 mode: %d, expansion mode: %s\n", tx_expansion
+					, get_mode_name(expmode));
+			break;
+		}
+
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad vht ss3 mode: %d, expansion: %s\n", tx_expansion,
+			   get_mode_name(expmode));
+	}
+
+	return mode_identifier;
+}
+
+static int get_vht_ss4_mode_identifier(int tx_expansion, exp_mode_t expmode)
+{
+	int mode_identifier = 0;
+
+	if (tx_expansion == 0)
+	{
+		switch (expmode)
+		{
+		case EXP_MODE_ID_DEF:
+			mode_identifier = VHT_SS4_MODE_ID_NONE;
+			break;
+		case EXP_MODE_ID_TXBF:
+			mode_identifier = VHT_SS4_MODE_ID_TXBF0;
+			break;
+		default:
+			fprintf(stderr, "ERROR: Bad vht ss4 mode: %d, expansion mode: %s\n", tx_expansion
+					, get_mode_name(expmode));
+			break;
+		}
+	}
+	else
+	{
+		fprintf(stderr, "ERROR: Bad vht ss4 mode: %d, expansion: %s\n", tx_expansion,
+			   get_mode_name(expmode));
+	}
+
+	return mode_identifier;
+}
+
+
+static const char *get_mode_name(exp_mode_t mode)
+{
+	if (mode >= EXP_MODE_ID_MAX)
+		return EXP_MODE_UNKNOWN;
+
+	return exp_mode_name[mode];
+}
diff --git a/wl/src/wl/exe/wlu_rates_matrix.h b/wl/src/wl/exe/wlu_rates_matrix.h
new file mode 100644
index 0000000..18eb46b
--- /dev/null
+++ b/wl/src/wl/exe/wlu_rates_matrix.h
@@ -0,0 +1,667 @@
+/*
+ * This module does provides various mappings to or from the CLM rate indexes.
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ */
+/*FILE-CSTYLED*/
+
+#ifndef _WLU_RATES_MATRIX_H_
+#define _WLU_RATES_MATRIX_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <bcmwifi_rates.h>
+#include <wlioctl.h>
+#include <typedefs.h>
+#include <epivers.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <bcmwifi_channels.h>
+#include <wlc_ppr.h>
+
+#ifdef LINUX
+#include <inttypes.h>
+#endif
+#include <miniopt.h>
+
+#define WL_UNSUPPORTED_IDX 0xFFF
+
+#define WLC_MAXMCS	102	/* Maximum valid mcs index */
+
+#define IS_PROPRIETARY_11N_MCS(mcs) \
+	((mcs) == 87 || (mcs) == 88 || (mcs) == 99 || (mcs) == 100 || (mcs) == 101 || (mcs) == 102)
+
+typedef enum clm_rate_group_id {
+	RATE_GROUP_ID_DSSS = 0,
+	RATE_GROUP_ID_OFDM,
+	RATE_GROUP_ID_MCS0_7,
+	RATE_GROUP_ID_VHT8_9SS1,
+	RATE_GROUP_ID_VHT10_11SS1,
+	RATE_GROUP_ID_DSSS_MULTI1,
+	RATE_GROUP_ID_OFDM_CDD1,
+	RATE_GROUP_ID_MCS0_7_CDD1,
+	RATE_GROUP_ID_VHT8_9SS1_CDD1,
+	RATE_GROUP_ID_VHT10_11SS1_CDD1,
+	RATE_GROUP_ID_MCS0_7_STBC,
+	RATE_GROUP_ID_VHT8_9SS1_STBC,
+	RATE_GROUP_ID_VHT10_11SS1_STBC,
+	RATE_GROUP_ID_MCS8_15,
+	RATE_GROUP_ID_VHT8_9SS2,
+	RATE_GROUP_ID_VHT10_11SS2,
+	RATE_GROUP_ID_DSSS_MULTI2,
+	RATE_GROUP_ID_OFDM_CDD2,
+	RATE_GROUP_ID_MCS0_7_CDD2,
+	RATE_GROUP_ID_VHT8_9SS1_CDD2,
+	RATE_GROUP_ID_VHT10_11SS1_CDD2,
+	RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,
+	RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP1,
+	RATE_GROUP_ID_VHT10_11SS1_STBC_SPEXP1,
+	RATE_GROUP_ID_MCS8_15_SPEXP1,
+	RATE_GROUP_ID_VHT8_9SS2_SPEXP1,
+	RATE_GROUP_ID_VHT10_11SS2_SPEXP1,
+	RATE_GROUP_ID_MCS16_23,
+	RATE_GROUP_ID_VHT8_9SS3,
+	RATE_GROUP_ID_VHT10_11SS3,
+	RATE_GROUP_ID_DSSS_MULTI3,
+	RATE_GROUP_ID_OFDM_CDD3,
+	RATE_GROUP_ID_MCS0_7_CDD3,
+	RATE_GROUP_ID_VHT8_9SS1_CDD3,
+	RATE_GROUP_ID_VHT10_11SS1_CDD3,
+	RATE_GROUP_ID_MCS0_7_STBC_SPEXP2,
+	RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP2,
+	RATE_GROUP_ID_VHT10_11SS1_STBC_SPEXP2,
+	RATE_GROUP_ID_MCS8_15_SPEXP2,
+	RATE_GROUP_ID_VHT8_9SS2_SPEXP2,
+	RATE_GROUP_ID_VHT10_11SS2_SPEXP2,
+	RATE_GROUP_ID_MCS16_23_SPEXP1,
+	RATE_GROUP_ID_VHT8_9SS3_SPEXP1,
+	RATE_GROUP_ID_VHT10_11SS3_SPEXP1,
+	RATE_GROUP_ID_MCS24_31,
+	RATE_GROUP_ID_VHT8_9SS4,
+	RATE_GROUP_ID_VHT10_11SS4,
+	RATE_GROUP_ID_OFDM_TXBF1,
+	RATE_GROUP_ID_MCS0_7_TXBF1,
+	RATE_GROUP_ID_VHT8_9SS1_TXBF1,
+	RATE_GROUP_ID_VHT10_11SS1_TXBF1,
+	RATE_GROUP_ID_MCS8_15_TXBF0,
+	RATE_GROUP_ID_VHT8_9SS2_TXBF0,
+	RATE_GROUP_ID_VHT10_11SS2_TXBF0,
+	RATE_GROUP_ID_OFDM_TXBF2,
+	RATE_GROUP_ID_MCS0_7_TXBF2,
+	RATE_GROUP_ID_VHT8_9SS1_TXBF2,
+	RATE_GROUP_ID_VHT10_11SS1_TXBF2,
+	RATE_GROUP_ID_MCS8_15_TXBF1,
+	RATE_GROUP_ID_VHT8_9SS2_TXBF1,
+	RATE_GROUP_ID_VHT10_11SS2_TXBF1,
+	RATE_GROUP_ID_MCS16_23_TXBF0,
+	RATE_GROUP_ID_VHT8_9SS3_TXBF0,
+	RATE_GROUP_ID_VHT10_11SS3_TXBF0,
+	RATE_GROUP_ID_OFDM_TXBF3,
+	RATE_GROUP_ID_MCS0_7_TXBF3,
+	RATE_GROUP_ID_VHT8_9SS1_TXBF3,
+	RATE_GROUP_ID_VHT10_11SS1_TXBF3,
+	RATE_GROUP_ID_MCS8_15_TXBF2,
+	RATE_GROUP_ID_VHT8_9SS2_TXBF2,
+	RATE_GROUP_ID_VHT10_11SS2_TXBF2,
+	RATE_GROUP_ID_MCS16_23_TXBF1,
+	RATE_GROUP_ID_VHT8_9SS3_TXBF1,
+	RATE_GROUP_ID_VHT10_11SS3_TXBF1,
+	RATE_GROUP_ID_MCS24_31_TXBF0,
+	RATE_GROUP_ID_VHT8_9SS4_TXBF0,
+	RATE_GROUP_ID_VHT10_11SS4_TXBF0,
+	RATE_GROUP_ID_COUNT
+} clm_rate_group_id_t;
+
+typedef enum reg_rate_index {
+	NO_RATE = -1,
+	DSSS1, DSSS2, DSSS5, DSSS11,
+	OFDM6, OFDM9, OFDM12, OFDM18,
+	OFDM24, OFDM36, OFDM48, OFDM54,
+	MCS0, MCS1, MCS2, MCS3,
+	MCS4, MCS5, MCS6, MCS7,
+	VHT8SS1, VHT9SS1,VHT10SS1, VHT11SS1,
+	DSSS1_MULTI1, DSSS2_MULTI1, DSSS5_MULTI1, DSSS11_MULTI1,
+	OFDM6_CDD1, OFDM9_CDD1, OFDM12_CDD1, OFDM18_CDD1,
+	OFDM24_CDD1, OFDM36_CDD1, OFDM48_CDD1, OFDM54_CDD1,
+	MCS0_CDD1, MCS1_CDD1, MCS2_CDD1, MCS3_CDD1,
+	MCS4_CDD1, MCS5_CDD1, MCS6_CDD1, MCS7_CDD1,
+	VHT8SS1_CDD1, VHT9SS1_CDD1, VHT10SS1_CDD1, VHT11SS1_CDD1,
+	MCS0_STBC, MCS1_STBC, MCS2_STBC, MCS3_STBC,
+	MCS4_STBC, MCS5_STBC, MCS6_STBC, MCS7_STBC,
+	VHT8SS1_STBC, VHT9SS1_STBC, VHT10SS1_STBC, VHT11SS1_STBC,
+	MCS8, MCS9, MCS10, MCS11,
+	MCS12, MCS13, MCS14, MCS15,
+	VHT8SS2, VHT9SS2, VHT10SS2, VHT11SS2,
+	DSSS1_MULTI2, DSSS2_MULTI2, DSSS5_MULTI2, DSSS11_MULTI2,
+	OFDM6_CDD2, OFDM9_CDD2, OFDM12_CDD2, OFDM18_CDD2,
+	OFDM24_CDD2, OFDM36_CDD2, OFDM48_CDD2, OFDM54_CDD2,
+	MCS0_CDD2, MCS1_CDD2, MCS2_CDD2, MCS3_CDD2,
+	MCS4_CDD2, MCS5_CDD2, MCS6_CDD2, MCS7_CDD2,
+	VHT8SS1_CDD2, VHT9SS1_CDD2, VHT10SS1_CDD2, VHT11SS1_CDD2,
+	MCS0_STBC_SPEXP1, MCS1_STBC_SPEXP1, MCS2_STBC_SPEXP1, MCS3_STBC_SPEXP1,
+	MCS4_STBC_SPEXP1, MCS5_STBC_SPEXP1, MCS6_STBC_SPEXP1, MCS7_STBC_SPEXP1,
+	VHT8SS1_STBC_SPEXP1, VHT9SS1_STBC_SPEXP1, VHT10SS1_STBC_SPEXP1, VHT11SS1_STBC_SPEXP1,
+	MCS8_SPEXP1, MCS9_SPEXP1, MCS10_SPEXP1, MCS11_SPEXP1,
+	MCS12_SPEXP1, MCS13_SPEXP1, MCS14_SPEXP1, MCS15_SPEXP1,
+	VHT8SS2_SPEXP1, VHT9SS2_SPEXP1, VHT10SS2_SPEXP1, VHT11SS2_SPEXP1,
+	MCS16, MCS17, MCS18, MCS19,
+	MCS20, MCS21, MCS22, MCS23,
+	VHT8SS3, VHT9SS3, VHT10SS3, VHT11SS3,
+	DSSS1_MULTI3, DSSS2_MULTI3, DSSS5_MULTI3, DSSS11_MULTI3,
+	OFDM6_CDD3, OFDM9_CDD3, OFDM12_CDD3, OFDM18_CDD3,
+	OFDM24_CDD3, OFDM36_CDD3, OFDM48_CDD3, OFDM54_CDD3,
+	MCS0_CDD3, MCS1_CDD3, MCS2_CDD3, MCS3_CDD3,
+	MCS4_CDD3, MCS5_CDD3, MCS6_CDD3, MCS7_CDD3,
+	VHT8SS1_CDD3, VHT9SS1_CDD3, VHT10SS1_CDD3, VHT11SS1_CDD3,
+	MCS0_STBC_SPEXP2, MCS1_STBC_SPEXP2, MCS2_STBC_SPEXP2, MCS3_STBC_SPEXP2,
+	MCS4_STBC_SPEXP2, MCS5_STBC_SPEXP2, MCS6_STBC_SPEXP2, MCS7_STBC_SPEXP2,
+	VHT8SS1_STBC_SPEXP2, VHT9SS1_STBC_SPEXP2, VHT10SS1_STBC_SPEXP2, VHT11SS1_STBC_SPEXP2,
+	MCS8_SPEXP2, MCS9_SPEXP2, MCS10_SPEXP2, MCS11_SPEXP2,
+	MCS12_SPEXP2, MCS13_SPEXP2, MCS14_SPEXP2, MCS15_SPEXP2,
+	VHT8SS2_SPEXP2, VHT9SS2_SPEXP2, VHT10SS2_SPEXP2, VHT11SS2_SPEXP2,
+	MCS16_SPEXP1, MCS17_SPEXP1, MCS18_SPEXP1, MCS19_SPEXP1,
+	MCS20_SPEXP1, MCS21_SPEXP1, MCS22_SPEXP1, MCS23_SPEXP1,
+	VHT8SS3_SPEXP1, VHT9SS3_SPEXP1, VHT10SS3_SPEXP1, VHT11SS3_SPEXP1,
+	MCS24, MCS25, MCS26, MCS27,
+	MCS28, MCS29, MCS30, MCS31,
+	VHT8SS4, VHT9SS4, VHT10SS4, VHT11SS4,
+	OFDM6_TXBF1, OFDM9_TXBF1, OFDM12_TXBF1, OFDM18_TXBF1,
+	OFDM24_TXBF1, OFDM36_TXBF1, OFDM48_TXBF1, OFDM54_TXBF1,
+	MCS0_TXBF1, MCS1_TXBF1, MCS2_TXBF1, MCS3_TXBF1,
+	MCS4_TXBF1, MCS5_TXBF1, MCS6_TXBF1, MCS7_TXBF1,
+	VHT8SS1_TXBF1, VHT9SS1_TXBF1, VHT10SS1_TXBF1, VHT11SS1_TXBF1,
+	MCS8_TXBF0, MCS9_TXBF0, MCS10_TXBF0, MCS11_TXBF0,
+	MCS12_TXBF0, MCS13_TXBF0, MCS14_TXBF0, MCS15_TXBF0,
+	VHT8SS2_TXBF0, VHT9SS2_TXBF0, VHT10SS2_TXBF0, VHT11SS2_TXBF0,
+	OFDM6_TXBF2, OFDM9_TXBF2, OFDM12_TXBF2, OFDM18_TXBF2,
+	OFDM24_TXBF2, OFDM36_TXBF2, OFDM48_TXBF2, OFDM54_TXBF2,
+	MCS0_TXBF2, MCS1_TXBF2, MCS2_TXBF2, MCS3_TXBF2,
+	MCS4_TXBF2, MCS5_TXBF2, MCS6_TXBF2, MCS7_TXBF2,
+	VHT8SS1_TXBF2, VHT9SS1_TXBF2, VHT10SS1_TXBF2, VHT11SS1_TXBF2,
+	MCS8_TXBF1, MCS9_TXBF1, MCS10_TXBF1, MCS11_TXBF1,
+	MCS12_TXBF1, MCS13_TXBF1, MCS14_TXBF1, MCS15_TXBF1,
+	VHT8SS2_TXBF1, VHT9SS2_TXBF1, VHT10SS2_TXBF1, VHT11SS2_TXBF1,
+	MCS16_TXBF0, MCS17_TXBF0, MCS18_TXBF0, MCS19_TXBF0,
+	MCS20_TXBF0, MCS21_TXBF0, MCS22_TXBF0, MCS23_TXBF0,
+	VHT8SS3_TXBF0, VHT9SS3_TXBF0, VHT10SS3_TXBF0, VHT11SS3_TXBF0,
+	OFDM6_TXBF3, OFDM9_TXBF3, OFDM12_TXBF3, OFDM18_TXBF3,
+	OFDM24_TXBF3, OFDM36_TXBF3, OFDM48_TXBF3, OFDM54_TXBF3,
+	MCS0_TXBF3, MCS1_TXBF3, MCS2_TXBF3, MCS3_TXBF3,
+	MCS4_TXBF3, MCS5_TXBF3, MCS6_TXBF3, MCS7_TXBF3,
+	VHT8SS1_TXBF3, VHT9SS1_TXBF3, VHT10SS1_TXBF3, VHT11SS1_TXBF3,
+	MCS8_TXBF2, MCS9_TXBF2, MCS10_TXBF2, MCS11_TXBF2,
+	MCS12_TXBF2, MCS13_TXBF2, MCS14_TXBF2, MCS15_TXBF2,
+	VHT8SS2_TXBF2, VHT9SS2_TXBF2, VHT10SS2_TXBF2, VHT11SS2_TXBF2,
+	MCS16_TXBF1, MCS17_TXBF1, MCS18_TXBF1, MCS19_TXBF1,
+	MCS20_TXBF1, MCS21_TXBF1, MCS22_TXBF1, MCS23_TXBF1,
+	VHT8SS3_TXBF1, VHT9SS3_TXBF1, VHT10SS3_TXBF1, VHT11SS3_TXBF1,
+	MCS24_TXBF0, MCS25_TXBF0, MCS26_TXBF0, MCS27_TXBF0,
+	MCS28_TXBF0, MCS29_TXBF0, MCS30_TXBF0, MCS31_TXBF0,
+	VHT8SS4_TXBF0, VHT9SS4_TXBF0, VHT10SS4_TXBF0, VHT11SS4_TXBF0,
+} reg_rate_index_t;
+
+typedef enum ppr_rate_type {
+	PPR_RATE_DSSS,
+	PPR_RATE_OFDM,
+	PPR_RATE_HT,
+	PPR_RATE_VHT,
+} ppr_rate_type_t;
+
+typedef struct ppr_tbl {
+	char label[23];
+	clm_rate_group_id_t id;
+//	clm_rates_t         rate;
+} ppr_tbl_t;
+
+typedef struct ppr_group {
+	clm_rate_group_id_t	id;
+	wl_tx_chains_t		chain;
+	wl_tx_mode_t		mode;
+	wl_tx_nss_t		nss;
+	ppr_rate_type_t		rate_type;
+	reg_rate_index_t	first_rate;
+} ppr_group_t;
+
+static const ppr_group_t ppr_group_table[] = {
+	/*group id				chains			mode			nss		rate type		offset-first*/
+	{RATE_GROUP_ID_DSSS,			WL_TX_CHAINS_1,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_DSSS,		DSSS1},
+	{RATE_GROUP_ID_OFDM,			WL_TX_CHAINS_1,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6},
+	{RATE_GROUP_ID_MCS0_7,			WL_TX_CHAINS_1,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0},
+	{RATE_GROUP_ID_VHT8_9SS1,		WL_TX_CHAINS_1,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0},
+	{RATE_GROUP_ID_VHT10_11SS1,		WL_TX_CHAINS_1,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0},
+	{RATE_GROUP_ID_DSSS_MULTI1,		WL_TX_CHAINS_2,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_DSSS,		DSSS1_MULTI1},
+	{RATE_GROUP_ID_OFDM_CDD1,		WL_TX_CHAINS_2,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6_CDD1},
+	{RATE_GROUP_ID_MCS0_7_CDD1,		WL_TX_CHAINS_2,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD1},
+	{RATE_GROUP_ID_VHT8_9SS1_CDD1,		WL_TX_CHAINS_2,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD1},
+	{RATE_GROUP_ID_VHT10_11SS1_CDD1,	WL_TX_CHAINS_2,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD1},
+	{RATE_GROUP_ID_MCS0_7_STBC,		WL_TX_CHAINS_2,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC},
+	{RATE_GROUP_ID_VHT8_9SS1_STBC,		WL_TX_CHAINS_2,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC},
+	{RATE_GROUP_ID_VHT10_11SS1_STBC,	WL_TX_CHAINS_2,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC},
+	{RATE_GROUP_ID_MCS8_15,			WL_TX_CHAINS_2,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8},
+	{RATE_GROUP_ID_VHT8_9SS2,		WL_TX_CHAINS_2,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8},
+	{RATE_GROUP_ID_VHT10_11SS2,		WL_TX_CHAINS_2,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8},
+	{RATE_GROUP_ID_DSSS_MULTI2,		WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_DSSS,		DSSS1_MULTI2},
+	{RATE_GROUP_ID_OFDM_CDD2,		WL_TX_CHAINS_3,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6_CDD2},
+	{RATE_GROUP_ID_MCS0_7_CDD2,		WL_TX_CHAINS_3,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD2},
+	{RATE_GROUP_ID_VHT8_9SS1_CDD2,		WL_TX_CHAINS_3,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD2},
+	{RATE_GROUP_ID_VHT10_11SS1_CDD2,	WL_TX_CHAINS_3,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD2},
+	{RATE_GROUP_ID_MCS0_7_STBC_SPEXP1,	WL_TX_CHAINS_3,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC_SPEXP1},
+	{RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP1,	WL_TX_CHAINS_3,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC_SPEXP1},
+	{RATE_GROUP_ID_VHT10_11SS1_STBC_SPEXP1,	WL_TX_CHAINS_3,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC_SPEXP1},
+	{RATE_GROUP_ID_MCS8_15_SPEXP1,		WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_SPEXP1},
+	{RATE_GROUP_ID_VHT8_9SS2_SPEXP1,	WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_SPEXP1},
+	{RATE_GROUP_ID_VHT10_11SS2_SPEXP1,	WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_SPEXP1},
+	{RATE_GROUP_ID_MCS16_23,		WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16},
+	{RATE_GROUP_ID_VHT8_9SS3,		WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16},
+	{RATE_GROUP_ID_VHT10_11SS3,		WL_TX_CHAINS_3,		WL_TX_MODE_NONE,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16},
+	{RATE_GROUP_ID_DSSS_MULTI3,		WL_TX_CHAINS_4,		WL_TX_MODE_NONE,	WL_TX_NSS_1,	PPR_RATE_DSSS,		DSSS1_MULTI3},
+	{RATE_GROUP_ID_OFDM_CDD3,		WL_TX_CHAINS_4,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6_CDD3},
+	{RATE_GROUP_ID_MCS0_7_CDD3,		WL_TX_CHAINS_4,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD3},
+	{RATE_GROUP_ID_VHT8_9SS1_CDD3,		WL_TX_CHAINS_4,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD3},
+	{RATE_GROUP_ID_VHT10_11SS1_CDD3,	WL_TX_CHAINS_4,		WL_TX_MODE_CDD,		WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_CDD3},
+	{RATE_GROUP_ID_MCS0_7_STBC_SPEXP2,	WL_TX_CHAINS_4,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC_SPEXP2},
+	{RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP2,	WL_TX_CHAINS_4,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC_SPEXP2},
+	{RATE_GROUP_ID_VHT10_11SS1_STBC_SPEXP2,	WL_TX_CHAINS_4,		WL_TX_MODE_STBC,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS0_STBC_SPEXP2},
+	{RATE_GROUP_ID_MCS8_15_SPEXP2,		WL_TX_CHAINS_4,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_SPEXP2},
+	{RATE_GROUP_ID_VHT8_9SS2_SPEXP2,	WL_TX_CHAINS_4,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_SPEXP2},
+	{RATE_GROUP_ID_VHT10_11SS2_SPEXP2,	WL_TX_CHAINS_4,		WL_TX_MODE_NONE,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_SPEXP2},
+	{RATE_GROUP_ID_MCS16_23_SPEXP1,		WL_TX_CHAINS_4,		WL_TX_MODE_NONE,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16_SPEXP1},
+	{RATE_GROUP_ID_VHT8_9SS3_SPEXP1,	WL_TX_CHAINS_4,		WL_TX_MODE_NONE,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16_SPEXP1},
+	{RATE_GROUP_ID_VHT10_11SS3_SPEXP1,	WL_TX_CHAINS_4,		WL_TX_MODE_NONE,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16_SPEXP1},
+	{RATE_GROUP_ID_MCS24_31,		WL_TX_CHAINS_4,		WL_TX_MODE_NONE,	WL_TX_NSS_4,	PPR_RATE_VHT,		MCS24},
+	{RATE_GROUP_ID_VHT8_9SS4,		WL_TX_CHAINS_4,		WL_TX_MODE_NONE,	WL_TX_NSS_4,	PPR_RATE_VHT,		MCS24},
+	{RATE_GROUP_ID_VHT10_11SS4,		WL_TX_CHAINS_4,		WL_TX_MODE_NONE,	WL_TX_NSS_4,	PPR_RATE_VHT,		MCS24},
+	{RATE_GROUP_ID_OFDM_TXBF1,		WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6_TXBF1},
+	{RATE_GROUP_ID_MCS0_7_TXBF1,		WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF1},
+	{RATE_GROUP_ID_VHT8_9SS1_TXBF1,		WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF1},
+	{RATE_GROUP_ID_VHT10_11SS1_TXBF1,	WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF1},
+	{RATE_GROUP_ID_MCS8_15_TXBF0,		WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF0},
+	{RATE_GROUP_ID_VHT8_9SS2_TXBF0,		WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF0},
+	{RATE_GROUP_ID_VHT10_11SS2_TXBF0,	WL_TX_CHAINS_2,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF0},
+	{RATE_GROUP_ID_OFDM_TXBF2,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6_TXBF2},
+	{RATE_GROUP_ID_MCS0_7_TXBF2,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF2},
+	{RATE_GROUP_ID_VHT8_9SS1_TXBF2,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF2},
+	{RATE_GROUP_ID_VHT10_11SS1_TXBF2,	WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF2},
+	{RATE_GROUP_ID_MCS8_15_TXBF1,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF1},
+	{RATE_GROUP_ID_VHT8_9SS2_TXBF1,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF1},
+	{RATE_GROUP_ID_VHT10_11SS2_TXBF1,	WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF1},
+	{RATE_GROUP_ID_MCS16_23_TXBF0,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16_TXBF0},
+	{RATE_GROUP_ID_VHT8_9SS3_TXBF0,		WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16_TXBF0},
+	{RATE_GROUP_ID_VHT10_11SS3_TXBF0,	WL_TX_CHAINS_3,		WL_TX_MODE_TXBF,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16_TXBF0},
+	{RATE_GROUP_ID_OFDM_TXBF3,		WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_OFDM,		OFDM6_TXBF3},
+	{RATE_GROUP_ID_MCS0_7_TXBF3,		WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF3},
+	{RATE_GROUP_ID_VHT8_9SS1_TXBF3,		WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF3},
+	{RATE_GROUP_ID_VHT10_11SS1_TXBF3,	WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_1,	PPR_RATE_VHT,		MCS0_TXBF3},
+	{RATE_GROUP_ID_MCS8_15_TXBF2,		WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF2},
+	{RATE_GROUP_ID_VHT8_9SS2_TXBF2,		WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF2},
+	{RATE_GROUP_ID_VHT10_11SS2_TXBF2,	WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_2,	PPR_RATE_VHT,		MCS8_TXBF2},
+	{RATE_GROUP_ID_MCS16_23_TXBF1,		WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16_TXBF1},
+	{RATE_GROUP_ID_VHT8_9SS3_TXBF1,		WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16_TXBF1},
+	{RATE_GROUP_ID_VHT10_11SS3_TXBF1,	WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_3,	PPR_RATE_VHT,		MCS16_TXBF1},
+	{RATE_GROUP_ID_MCS24_31_TXBF0,		WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_4,	PPR_RATE_VHT,		MCS24_TXBF0},
+	{RATE_GROUP_ID_VHT8_9SS4_TXBF0,		WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_4,	PPR_RATE_VHT,		MCS24_TXBF0},
+	{RATE_GROUP_ID_VHT10_11SS4_TXBF0,	WL_TX_CHAINS_4,		WL_TX_MODE_TXBF,	WL_TX_NSS_4,	PPR_RATE_VHT,		MCS24_TXBF0},
+};
+
+static const ppr_tbl_t ppr_table[] = {
+	/* Label			Rate Group ID */
+	{"DSSS1",			RATE_GROUP_ID_DSSS},
+	{"DSSS2",			RATE_GROUP_ID_DSSS},
+	{"DSSS5",			RATE_GROUP_ID_DSSS},
+	{"DSSS11",			RATE_GROUP_ID_DSSS},
+	{"OFDM6",			RATE_GROUP_ID_OFDM},
+	{"OFDM9",			RATE_GROUP_ID_OFDM},
+	{"OFDM12",			RATE_GROUP_ID_OFDM},
+	{"OFDM18",			RATE_GROUP_ID_OFDM},
+	{"OFDM24",			RATE_GROUP_ID_OFDM},
+	{"OFDM36",			RATE_GROUP_ID_OFDM},
+	{"OFDM48",			RATE_GROUP_ID_OFDM},
+	{"OFDM54",			RATE_GROUP_ID_OFDM},
+	{"MCS0",			RATE_GROUP_ID_MCS0_7},
+	{"MCS1",			RATE_GROUP_ID_MCS0_7},
+	{"MCS2",			RATE_GROUP_ID_MCS0_7},
+	{"MCS3",			RATE_GROUP_ID_MCS0_7},
+	{"MCS4",			RATE_GROUP_ID_MCS0_7},
+	{"MCS5",			RATE_GROUP_ID_MCS0_7},
+	{"MCS6",			RATE_GROUP_ID_MCS0_7},
+	{"MCS7",			RATE_GROUP_ID_MCS0_7},
+	{"VHT8SS1",			RATE_GROUP_ID_VHT8_9SS1},
+	{"VHT9SS1",			RATE_GROUP_ID_VHT8_9SS1},
+	{"VHT10SS1",			RATE_GROUP_ID_VHT10_11SS1},
+	{"VHT11SS1",			RATE_GROUP_ID_VHT10_11SS1},
+	{"DSSS1_MULTI1",		RATE_GROUP_ID_DSSS_MULTI1},
+	{"DSSS2_MULTI1",		RATE_GROUP_ID_DSSS_MULTI1},
+	{"DSSS5_MULTI1",		RATE_GROUP_ID_DSSS_MULTI1},
+	{"DSSS11_MULTI1",		RATE_GROUP_ID_DSSS_MULTI1},
+	{"OFDM6_CDD1",			RATE_GROUP_ID_OFDM_CDD1},
+	{"OFDM9_CDD1",			RATE_GROUP_ID_OFDM_CDD1},
+	{"OFDM12_CDD1",			RATE_GROUP_ID_OFDM_CDD1},
+	{"OFDM18_CDD1",			RATE_GROUP_ID_OFDM_CDD1},
+	{"OFDM24_CDD1",			RATE_GROUP_ID_OFDM_CDD1},
+	{"OFDM36_CDD1",			RATE_GROUP_ID_OFDM_CDD1},
+	{"OFDM48_CDD1",			RATE_GROUP_ID_OFDM_CDD1},
+	{"OFDM54_CDD1",			RATE_GROUP_ID_OFDM_CDD1},
+	{"MCS0_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1},
+	{"MCS1_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1},
+	{"MCS2_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1},
+	{"MCS3_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1},
+	{"MCS4_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1},
+	{"MCS5_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1},
+	{"MCS6_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1},
+	{"MCS7_CDD1",			RATE_GROUP_ID_MCS0_7_CDD1},
+	{"VHT8SS1_CDD1",		RATE_GROUP_ID_VHT8_9SS1_CDD1},
+	{"VHT9SS1_CDD1",		RATE_GROUP_ID_VHT8_9SS1_CDD1},
+	{"VHT10SS1_CDD1",		RATE_GROUP_ID_VHT10_11SS1_CDD1},
+	{"VHT11SS1_CDD1",		RATE_GROUP_ID_VHT10_11SS1_CDD1},
+	{"MCS0_STBC",			RATE_GROUP_ID_MCS0_7_STBC},
+	{"MCS1_STBC",			RATE_GROUP_ID_MCS0_7_STBC},
+	{"MCS2_STBC",			RATE_GROUP_ID_MCS0_7_STBC},
+	{"MCS3_STBC",			RATE_GROUP_ID_MCS0_7_STBC},
+	{"MCS4_STBC",			RATE_GROUP_ID_MCS0_7_STBC},
+	{"MCS5_STBC",			RATE_GROUP_ID_MCS0_7_STBC},
+	{"MCS6_STBC",			RATE_GROUP_ID_MCS0_7_STBC},
+	{"MCS7_STBC",			RATE_GROUP_ID_MCS0_7_STBC},
+	{"VHT8SS1_STBC",		RATE_GROUP_ID_VHT8_9SS1_STBC},
+	{"VHT9SS1_STBC",		RATE_GROUP_ID_VHT8_9SS1_STBC},
+	{"VHT10SS1_STBC",		RATE_GROUP_ID_VHT10_11SS1_STBC},
+	{"VHT11SS1_STBC",		RATE_GROUP_ID_VHT10_11SS1_STBC},
+	{"MCS8",			RATE_GROUP_ID_MCS8_15},
+	{"MCS9",			RATE_GROUP_ID_MCS8_15},
+	{"MCS10",			RATE_GROUP_ID_MCS8_15},
+	{"MCS11",			RATE_GROUP_ID_MCS8_15},
+	{"MCS12",			RATE_GROUP_ID_MCS8_15},
+	{"MCS13",			RATE_GROUP_ID_MCS8_15},
+	{"MCS14",			RATE_GROUP_ID_MCS8_15},
+	{"MCS15",			RATE_GROUP_ID_MCS8_15},
+	{"VHT8SS2",			RATE_GROUP_ID_VHT8_9SS2},
+	{"VHT9SS2",			RATE_GROUP_ID_VHT8_9SS2},
+	{"VHT10SS2",			RATE_GROUP_ID_VHT10_11SS2},
+	{"VHT11SS2",			RATE_GROUP_ID_VHT10_11SS2},
+	{"DSSS1_MULTI2",		RATE_GROUP_ID_DSSS_MULTI2},
+	{"DSSS2_MULTI2",		RATE_GROUP_ID_DSSS_MULTI2},
+	{"DSSS5_MULTI2",		RATE_GROUP_ID_DSSS_MULTI2},
+	{"DSSS11_MULTI2",		RATE_GROUP_ID_DSSS_MULTI2},
+	{"OFDM6_CDD2",			RATE_GROUP_ID_OFDM_CDD2},
+	{"OFDM9_CDD2",			RATE_GROUP_ID_OFDM_CDD2},
+	{"OFDM12_CDD2",			RATE_GROUP_ID_OFDM_CDD2},
+	{"OFDM18_CDD2",			RATE_GROUP_ID_OFDM_CDD2},
+	{"OFDM24_CDD2",			RATE_GROUP_ID_OFDM_CDD2},
+	{"OFDM36_CDD2",			RATE_GROUP_ID_OFDM_CDD2},
+	{"OFDM48_CDD2",			RATE_GROUP_ID_OFDM_CDD2},
+	{"OFDM54_CDD2",			RATE_GROUP_ID_OFDM_CDD2},
+	{"MCS0_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2},
+	{"MCS1_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2},
+	{"MCS2_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2},
+	{"MCS3_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2},
+	{"MCS4_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2},
+	{"MCS5_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2},
+	{"MCS6_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2},
+	{"MCS7_CDD2",			RATE_GROUP_ID_MCS0_7_CDD2},
+	{"VHT8SS1_CDD2",		RATE_GROUP_ID_VHT8_9SS1_CDD2},
+	{"VHT9SS1_CDD2",		RATE_GROUP_ID_VHT8_9SS1_CDD2},
+	{"VHT10SS1_CDD2",		RATE_GROUP_ID_VHT10_11SS1_CDD2},
+	{"VHT11SS1_CDD2",		RATE_GROUP_ID_VHT10_11SS1_CDD2},
+	{"MCS0_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1},
+	{"MCS1_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1},
+	{"MCS2_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1},
+	{"MCS3_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1},
+	{"MCS4_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1},
+	{"MCS5_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1},
+	{"MCS6_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1},
+	{"MCS7_STBC_SPEXP1",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP1},
+	{"VHT8SS1_STBC_SPEXP1",		RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP1},
+	{"VHT9SS1_STBC_SPEXP1",		RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP1},
+	{"VHT10SS1_STBC_SPEXP1",	RATE_GROUP_ID_VHT10_11SS1_STBC_SPEXP1},
+	{"VHT11SS1_STBC_SPEXP1",	RATE_GROUP_ID_VHT10_11SS1_STBC_SPEXP1},
+	{"MCS8_SPEXP1",			RATE_GROUP_ID_MCS8_15_SPEXP1},
+	{"MCS9_SPEXP1",			RATE_GROUP_ID_MCS8_15_SPEXP1},
+	{"MCS10_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1},
+	{"MCS11_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1},
+	{"MCS12_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1},
+	{"MCS13_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1},
+	{"MCS14_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1},
+	{"MCS15_SPEXP1",		RATE_GROUP_ID_MCS8_15_SPEXP1},
+	{"VHT8SS2_SPEXP1",		RATE_GROUP_ID_VHT8_9SS2_SPEXP1},
+	{"VHT9SS2_SPEXP1",		RATE_GROUP_ID_VHT8_9SS2_SPEXP1},
+	{"VHT10SS2_SPEXP1",		RATE_GROUP_ID_VHT10_11SS2_SPEXP1},
+	{"VHT11SS2_SPEXP1",		RATE_GROUP_ID_VHT10_11SS2_SPEXP1},
+	{"MCS16",			RATE_GROUP_ID_MCS16_23},
+	{"MCS17",			RATE_GROUP_ID_MCS16_23},
+	{"MCS18",			RATE_GROUP_ID_MCS16_23},
+	{"MCS19",			RATE_GROUP_ID_MCS16_23},
+	{"MCS20",			RATE_GROUP_ID_MCS16_23},
+	{"MCS21",			RATE_GROUP_ID_MCS16_23},
+	{"MCS22",			RATE_GROUP_ID_MCS16_23},
+	{"MCS23",			RATE_GROUP_ID_MCS16_23},
+	{"VHT8SS3",			RATE_GROUP_ID_VHT8_9SS3},
+	{"VHT9SS3",			RATE_GROUP_ID_VHT8_9SS3},
+	{"VHT10SS3",			RATE_GROUP_ID_VHT10_11SS3},
+	{"VHT11SS3",			RATE_GROUP_ID_VHT10_11SS3},
+	{"DSSS1_MULTI3",		RATE_GROUP_ID_DSSS_MULTI3},
+	{"DSSS2_MULTI3",		RATE_GROUP_ID_DSSS_MULTI3},
+	{"DSSS5_MULTI3",		RATE_GROUP_ID_DSSS_MULTI3},
+	{"DSSS11_MULTI3",		RATE_GROUP_ID_DSSS_MULTI3},
+	{"OFDM6_CDD3",			RATE_GROUP_ID_OFDM_CDD3},
+	{"OFDM9_CDD3",			RATE_GROUP_ID_OFDM_CDD3},
+	{"OFDM12_CDD3",			RATE_GROUP_ID_OFDM_CDD3},
+	{"OFDM18_CDD3",			RATE_GROUP_ID_OFDM_CDD3},
+	{"OFDM24_CDD3",			RATE_GROUP_ID_OFDM_CDD3},
+	{"OFDM36_CDD3",			RATE_GROUP_ID_OFDM_CDD3},
+	{"OFDM48_CDD3",			RATE_GROUP_ID_OFDM_CDD3},
+	{"OFDM54_CDD3",			RATE_GROUP_ID_OFDM_CDD3},
+	{"MCS0_CDD3",			RATE_GROUP_ID_MCS0_7_CDD3},
+	{"MCS1_CDD3",			RATE_GROUP_ID_MCS0_7_CDD3},
+	{"MCS2_CDD3",			RATE_GROUP_ID_MCS0_7_CDD3},
+	{"MCS3_CDD3",			RATE_GROUP_ID_MCS0_7_CDD3},
+	{"MCS4_CDD3",			RATE_GROUP_ID_MCS0_7_CDD3},
+	{"MCS5_CDD3",			RATE_GROUP_ID_MCS0_7_CDD3},
+	{"MCS6_CDD3",			RATE_GROUP_ID_MCS0_7_CDD3},
+	{"MCS7_CDD3",			RATE_GROUP_ID_MCS0_7_CDD3},
+	{"VHT8SS1_CDD3",		RATE_GROUP_ID_VHT8_9SS1_CDD3},
+	{"VHT9SS1_CDD3",		RATE_GROUP_ID_VHT8_9SS1_CDD3},
+	{"VHT10SS1_CDD3",		RATE_GROUP_ID_VHT10_11SS1_CDD3},
+	{"VHT11SS1_CDD3",		RATE_GROUP_ID_VHT10_11SS1_CDD3},
+	{"MCS0_STBC_SPEXP2",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP2},
+	{"MCS1_STBC_SPEXP2",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP2},
+	{"MCS2_STBC_SPEXP2",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP2},
+	{"MCS3_STBC_SPEXP2",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP2},
+	{"MCS4_STBC_SPEXP2",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP2},
+	{"MCS5_STBC_SPEXP2",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP2},
+	{"MCS6_STBC_SPEXP2",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP2},
+	{"MCS7_STBC_SPEXP2",		RATE_GROUP_ID_MCS0_7_STBC_SPEXP2},
+	{"VHT8SS1_STBC_SPEXP2",		RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP2},
+	{"VHT9SS1_STBC_SPEXP2",		RATE_GROUP_ID_VHT8_9SS1_STBC_SPEXP2},
+	{"VHT10SS1_STBC_SPEXP2",	RATE_GROUP_ID_VHT10_11SS1_STBC_SPEXP2},
+	{"VHT11SS1_STBC_SPEXP2",	RATE_GROUP_ID_VHT10_11SS1_STBC_SPEXP2},
+	{"MCS8_SPEXP2",			RATE_GROUP_ID_MCS8_15_SPEXP2},
+	{"MCS9_SPEXP2",			RATE_GROUP_ID_MCS8_15_SPEXP2},
+	{"MCS10_SPEXP2",		RATE_GROUP_ID_MCS8_15_SPEXP2},
+	{"MCS11_SPEXP2",		RATE_GROUP_ID_MCS8_15_SPEXP2},
+	{"MCS12_SPEXP2",		RATE_GROUP_ID_MCS8_15_SPEXP2},
+	{"MCS13_SPEXP2",		RATE_GROUP_ID_MCS8_15_SPEXP2},
+	{"MCS14_SPEXP2",		RATE_GROUP_ID_MCS8_15_SPEXP2},
+	{"MCS15_SPEXP2",		RATE_GROUP_ID_MCS8_15_SPEXP2},
+	{"VHT8SS2_SPEXP2",		RATE_GROUP_ID_VHT8_9SS2_SPEXP2},
+	{"VHT9SS2_SPEXP2",		RATE_GROUP_ID_VHT8_9SS2_SPEXP2},
+	{"VHT10SS2_SPEXP2",		RATE_GROUP_ID_VHT10_11SS2_SPEXP2},
+	{"VHT11SS2_SPEXP2",		RATE_GROUP_ID_VHT10_11SS2_SPEXP2},
+	{"MCS16_SPEXP1",		RATE_GROUP_ID_MCS16_23},
+	{"MCS17_SPEXP1",		RATE_GROUP_ID_MCS16_23},
+	{"MCS18_SPEXP1",		RATE_GROUP_ID_MCS16_23},
+	{"MCS19_SPEXP1",		RATE_GROUP_ID_MCS16_23},
+	{"MCS20_SPEXP1",		RATE_GROUP_ID_MCS16_23},
+	{"MCS21_SPEXP1",		RATE_GROUP_ID_MCS16_23},
+	{"MCS22_SPEXP1",		RATE_GROUP_ID_MCS16_23},
+	{"MCS23_SPEXP1",		RATE_GROUP_ID_MCS16_23},
+	{"VHT8SS3_SPEXP1",		RATE_GROUP_ID_VHT8_9SS3},
+	{"VHT9SS3_SPEXP1",		RATE_GROUP_ID_VHT8_9SS3},
+	{"VHT10SS3_SPEXP1",		RATE_GROUP_ID_VHT10_11SS3},
+	{"VHT11SS3_SPEXP1",		RATE_GROUP_ID_VHT10_11SS3},
+	{"MCS24",			RATE_GROUP_ID_MCS24_31},
+	{"MCS25",			RATE_GROUP_ID_MCS24_31},
+	{"MCS26",			RATE_GROUP_ID_MCS24_31},
+	{"MCS27",			RATE_GROUP_ID_MCS24_31},
+	{"MCS28",			RATE_GROUP_ID_MCS24_31},
+	{"MCS29",			RATE_GROUP_ID_MCS24_31},
+	{"MCS30",			RATE_GROUP_ID_MCS24_31},
+	{"MCS31",			RATE_GROUP_ID_MCS24_31},
+	{"VHT8SS4",			RATE_GROUP_ID_VHT8_9SS4},
+	{"VHT9SS4",			RATE_GROUP_ID_VHT8_9SS4},
+	{"VHT10SS4",			RATE_GROUP_ID_VHT10_11SS4},
+	{"VHT11SS4",			RATE_GROUP_ID_VHT10_11SS4},
+	{"OFDM6_TXBF1",			RATE_GROUP_ID_OFDM_TXBF1},
+	{"OFDM9_TXBF1",			RATE_GROUP_ID_OFDM_TXBF1},
+	{"OFDM12_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1},
+	{"OFDM18_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1},
+	{"OFDM24_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1},
+	{"OFDM36_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1},
+	{"OFDM48_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1},
+	{"OFDM54_TXBF1",		RATE_GROUP_ID_OFDM_TXBF1},
+	{"MCS0_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1},
+	{"MCS1_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1},
+	{"MCS2_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1},
+	{"MCS3_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1},
+	{"MCS4_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1},
+	{"MCS5_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1},
+	{"MCS6_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1},
+	{"MCS7_TXBF1",			RATE_GROUP_ID_MCS0_7_TXBF1},
+	{"VHT8SS1_TXBF1",		RATE_GROUP_ID_VHT8_9SS1_TXBF1},
+	{"VHT9SS1_TXBF1",		RATE_GROUP_ID_VHT8_9SS1_TXBF1},
+	{"VHT10SS1_TXBF1",		RATE_GROUP_ID_VHT10_11SS1_TXBF1},
+	{"VHT11SS1_TXBF1",		RATE_GROUP_ID_VHT10_11SS1_TXBF1},
+	{"MCS8_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0},
+	{"MCS9_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0},
+	{"MCS10_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0},
+	{"MCS11_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0},
+	{"MCS12_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0},
+	{"MCS13_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0},
+	{"MCS14_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0},
+	{"MCS15_TXBF0",			RATE_GROUP_ID_MCS8_15_TXBF0},
+	{"VHT8SS2_TXBF0",		RATE_GROUP_ID_VHT8_9SS2_TXBF0},
+	{"VHT9SS2_TXBF0",		RATE_GROUP_ID_VHT8_9SS2_TXBF0},
+	{"VHT10SS2_TXBF0",		RATE_GROUP_ID_VHT10_11SS2_TXBF0},
+	{"VHT11SS2_TXBF0",		RATE_GROUP_ID_VHT10_11SS2_TXBF0},
+	{"OFDM6_TXBF2",			RATE_GROUP_ID_OFDM_TXBF2},
+	{"OFDM9_TXBF2",			RATE_GROUP_ID_OFDM_TXBF2},
+	{"OFDM12_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2},
+	{"OFDM18_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2},
+	{"OFDM24_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2},
+	{"OFDM36_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2},
+	{"OFDM48_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2},
+	{"OFDM54_TXBF2",		RATE_GROUP_ID_OFDM_TXBF2},
+	{"MCS0_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2},
+	{"MCS1_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2},
+	{"MCS2_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2},
+	{"MCS3_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2},
+	{"MCS4_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2},
+	{"MCS5_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2},
+	{"MCS6_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2},
+	{"MCS7_TXBF2",			RATE_GROUP_ID_MCS0_7_TXBF2},
+	{"VHT8SS1_TXBF2",		RATE_GROUP_ID_VHT8_9SS1_TXBF2},
+	{"VHT9SS1_TXBF2",		RATE_GROUP_ID_VHT8_9SS1_TXBF2},
+	{"VHT10SS1_TXBF2",		RATE_GROUP_ID_VHT10_11SS1_TXBF2},
+	{"VHT11SS1_TXBF2",		RATE_GROUP_ID_VHT10_11SS1_TXBF2},
+	{"MCS8_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1},
+	{"MCS9_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1},
+	{"MCS10_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1},
+	{"MCS11_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1},
+	{"MCS12_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1},
+	{"MCS13_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1},
+	{"MCS14_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1},
+	{"MCS15_TXBF1",			RATE_GROUP_ID_MCS8_15_TXBF1},
+	{"VHT8SS2_TXBF1",		RATE_GROUP_ID_VHT8_9SS2_TXBF1},
+	{"VHT9SS2_TXBF1",		RATE_GROUP_ID_VHT8_9SS2_TXBF1},
+	{"VHT10SS2_TXBF1",		RATE_GROUP_ID_VHT10_11SS2_TXBF1},
+	{"VHT11SS2_TXBF1",		RATE_GROUP_ID_VHT10_11SS2_TXBF1},
+	{"MCS16_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0},
+	{"MCS17_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0},
+	{"MCS18_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0},
+	{"MCS19_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0},
+	{"MCS20_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0},
+	{"MCS21_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0},
+	{"MCS22_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0},
+	{"MCS23_TXBF0",			RATE_GROUP_ID_MCS16_23_TXBF0},
+	{"VHT8SS3_TXBF0",		RATE_GROUP_ID_VHT8_9SS3_TXBF0},
+	{"VHT9SS3_TXBF0",		RATE_GROUP_ID_VHT8_9SS3_TXBF0},
+	{"VHT10SS3_TXBF0",		RATE_GROUP_ID_VHT10_11SS3_TXBF0},
+	{"VHT11SS3_TXBF0",		RATE_GROUP_ID_VHT10_11SS3_TXBF0},
+	{"OFDM6_TXBF3",			RATE_GROUP_ID_OFDM_TXBF3},
+	{"OFDM9_TXBF3",			RATE_GROUP_ID_OFDM_TXBF3},
+	{"OFDM12_TXBF3",		RATE_GROUP_ID_OFDM_TXBF3},
+	{"OFDM18_TXBF3",		RATE_GROUP_ID_OFDM_TXBF3},
+	{"OFDM24_TXBF3",		RATE_GROUP_ID_OFDM_TXBF3},
+	{"OFDM36_TXBF3",		RATE_GROUP_ID_OFDM_TXBF3},
+	{"OFDM48_TXBF3",		RATE_GROUP_ID_OFDM_TXBF3},
+	{"OFDM54_TXBF3",		RATE_GROUP_ID_OFDM_TXBF3},
+	{"MCS0_TXBF3",			RATE_GROUP_ID_MCS0_7_TXBF3},
+	{"MCS1_TXBF3",			RATE_GROUP_ID_MCS0_7_TXBF3},
+	{"MCS2_TXBF3",			RATE_GROUP_ID_MCS0_7_TXBF3},
+	{"MCS3_TXBF3",			RATE_GROUP_ID_MCS0_7_TXBF3},
+	{"MCS4_TXBF3",			RATE_GROUP_ID_MCS0_7_TXBF3},
+	{"MCS5_TXBF3",			RATE_GROUP_ID_MCS0_7_TXBF3},
+	{"MCS6_TXBF3",			RATE_GROUP_ID_MCS0_7_TXBF3},
+	{"MCS7_TXBF3",			RATE_GROUP_ID_MCS0_7_TXBF3},
+	{"VHT8SS1_TXBF3",		RATE_GROUP_ID_VHT8_9SS1_TXBF3},
+	{"VHT9SS1_TXBF3",		RATE_GROUP_ID_VHT8_9SS1_TXBF3},
+	{"VHT10SS1_TXBF3",		RATE_GROUP_ID_VHT10_11SS1_TXBF3},
+	{"VHT11SS1_TXBF3",		RATE_GROUP_ID_VHT10_11SS1_TXBF3},
+	{"MCS8_TXBF2",			RATE_GROUP_ID_MCS8_15_TXBF2},
+	{"MCS9_TXBF2",			RATE_GROUP_ID_MCS8_15_TXBF2},
+	{"MCS10_TXBF2",			RATE_GROUP_ID_MCS8_15_TXBF2},
+	{"MCS11_TXBF2",			RATE_GROUP_ID_MCS8_15_TXBF2},
+	{"MCS12_TXBF2",			RATE_GROUP_ID_MCS8_15_TXBF2},
+	{"MCS13_TXBF2",			RATE_GROUP_ID_MCS8_15_TXBF2},
+	{"MCS14_TXBF2",			RATE_GROUP_ID_MCS8_15_TXBF2},
+	{"MCS15_TXBF2",			RATE_GROUP_ID_MCS8_15_TXBF2},
+	{"VHT8SS2_TXBF2",		RATE_GROUP_ID_VHT8_9SS2_TXBF2},
+	{"VHT9SS2_TXBF2",		RATE_GROUP_ID_VHT8_9SS2_TXBF2},
+	{"VHT10SS2_TXBF2",		RATE_GROUP_ID_VHT10_11SS2_TXBF2},
+	{"VHT11SS2_TXBF2",		RATE_GROUP_ID_VHT10_11SS2_TXBF2},
+	{"MCS16_TXBF1",			RATE_GROUP_ID_MCS16_23_TXBF1},
+	{"MCS17_TXBF1",			RATE_GROUP_ID_MCS16_23_TXBF1},
+	{"MCS18_TXBF1",			RATE_GROUP_ID_MCS16_23_TXBF1},
+	{"MCS19_TXBF1",			RATE_GROUP_ID_MCS16_23_TXBF1},
+	{"MCS20_TXBF1",			RATE_GROUP_ID_MCS16_23_TXBF1},
+	{"MCS21_TXBF1",			RATE_GROUP_ID_MCS16_23_TXBF1},
+	{"MCS22_TXBF1",			RATE_GROUP_ID_MCS16_23_TXBF1},
+	{"MCS23_TXBF1",			RATE_GROUP_ID_MCS16_23_TXBF1},
+	{"VHT8SS3_TXBF1",		RATE_GROUP_ID_VHT8_9SS3_TXBF1},
+	{"VHT9SS3_TXBF1",		RATE_GROUP_ID_VHT8_9SS3_TXBF1},
+	{"VHT10SS3_TXBF1",		RATE_GROUP_ID_VHT10_11SS3_TXBF1},
+	{"VHT11SS3_TXBF1",		RATE_GROUP_ID_VHT10_11SS3_TXBF1},
+	{"MCS24_TXBF0",			RATE_GROUP_ID_MCS24_31_TXBF0},
+	{"MCS25_TXBF0",			RATE_GROUP_ID_MCS24_31_TXBF0},
+	{"MCS26_TXBF0",			RATE_GROUP_ID_MCS24_31_TXBF0},
+	{"MCS27_TXBF0",			RATE_GROUP_ID_MCS24_31_TXBF0},
+	{"MCS28_TXBF0",			RATE_GROUP_ID_MCS24_31_TXBF0},
+	{"MCS29_TXBF0",			RATE_GROUP_ID_MCS24_31_TXBF0},
+	{"MCS30_TXBF0",			RATE_GROUP_ID_MCS24_31_TXBF0},
+	{"MCS31_TXBF0",			RATE_GROUP_ID_MCS24_31_TXBF0},
+	{"VHT8SS4_TXBF0",		RATE_GROUP_ID_VHT8_9SS4_TXBF0},
+	{"VHT9SS4_TXBF0",		RATE_GROUP_ID_VHT8_9SS4_TXBF0},
+	{"VHT10SS4_TXBF0",		RATE_GROUP_ID_VHT10_11SS4_TXBF0},
+	{"VHT11SS4_TXBF0",		RATE_GROUP_ID_VHT10_11SS4_TXBF0},
+};
+
+#define MHZ_TO_HALF_MHZ 2
+
+const char *get_clm_rate_group_label(int rategroup);
+const char *get_reg_rate_string_from_ratespec(int ratespec);
+reg_rate_index_t get_reg_rate_index_from_ratespec(int ratespec);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _WLU_RATES_MATRIX_H_ */
diff --git a/wl/src/wl/exe/wlu_remote.h b/wl/src/wl/exe/wlu_remote.h
new file mode 100644
index 0000000..879466c
--- /dev/null
+++ b/wl/src/wl/exe/wlu_remote.h
@@ -0,0 +1,247 @@
+/*
+ * OS independent remote wl declarations
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_remote.h 535847 2015-02-19 19:01:29Z $
+ */
+#ifndef _wlu_remote_h
+#define _wlu_remote_h
+#include <wlioctl.h>
+
+#if defined(__FreeBSD__) && defined(RWL_SOCKET)
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif /* defined(__FreeBSD__) && defined(RWL_SOCKET) */
+
+/* Remote wl declararions */
+#define NO_REMOTE       0
+#define REMOTE_SERIAL 	1
+#define REMOTE_SOCKET 	2
+#define REMOTE_WIFI     3
+#define REMOTE_DONGLE   4
+#define SHELL_CMD       -1 /* Invalid cmd id for shell */
+#define ASD_CMD       	-2 /* Cmd id for ASD command */
+#define SERVER_RESPONSE_MAX_BUF_LEN 8192
+#define SHELL_RESP_SIZE 1024
+#define CTRLC_PACKET 0xDEADBEAF
+#define CTRLC_FLAG -4
+#define VISTA_CMD	-3 /* cmd id for remote vista */
+
+/* For cross OS support */
+/* For autonegotiation to work, these defines should be
+ * the same for client and server.
+ */
+#define UNKNOWN_OS	0
+#define LINUX_OS  	1
+#define WIN32_OS  	2
+#define MAC_OSX		3
+#define BACKLOG 	4
+#define WINVISTA_OS	5
+#define INDONGLE	6
+#define INVALID_OS	7	/* Should be last */
+
+/* Used in cdc_ioctl_t.flags field */
+#define REMOTE_SET_IOCTL			1
+#define REMOTE_GET_IOCTL			2
+#define REMOTE_REPLY				4
+#define REMOTE_SHELL_CMD			8
+#define REMOTE_FINDSERVER_IOCTL		16 /* Find remote server */
+#define REMOTE_ASD_CMD				32 /* ASD integration */
+#define RDHD_SET_IOCTL			64
+#define RDHD_GET_IOCTL			128
+#define REMOTE_VISTA_CMD			256 /* for remote vista specific commands */
+#define REMOTE_NEGOTIATE_CMD			512 /* for RWL negotiation */
+#define NEGOTIATE_GET_OS			0   /* detect remote OS */
+#define RWL_WIFI_DEFAULT_TYPE 		0x00
+#define RWL_WIFI_DEFAULT_SUBTYPE 	0x00
+#define RWL_ACTION_FRAME_DATA_SIZE 	1024	/* fixed size for the wifi frame data */
+#define RWL_WIFI_CDC_HEADER_OFFSET 	0
+#define RWL_WIFI_FRAG_DATA_SIZE 	960 /* max size of the frag data */
+#define RWL_DEFAULT_WIFI_FRAG_COUNT 127 /* maximum fragment count */
+#define RWL_WIFI_RETRY				5	/* CMD retry count for wifi */
+#define RWL_WIFI_RX_RETRY			20  /* WIFI response rerty count */
+#define RWL_WIFI_SEND				5   /* WIFI frame sent count */
+#define RWL_WIFI_RETRY_DELAY   		1000 /* wifi specific retry delay  */
+#define RWL_WIFI_SEND_DELAY			100  /* delay between two frames */
+#define RWL_WIFI_RX_DELAY			250  /*  wait between send and receive */
+#define RWL_WIFI_RX_SHELL_DELAY		1000 /* delay added for shell cmd response read */
+#define RWL_CHANNEL_RX_SCAN_DELAY	10  /* Delay between findserver rx calls */
+#define RWL_CHANNEL_SCAN_WAIT		250 /* Sleep time in between the channel scans */
+#define RWL_WIFI_BUF_LEN			64
+#define RWL_WIFI_SHELL_CMD			1
+#define RWL_WIFI_WL_CMD            	0
+#define RWL_WIFI_FIND_SER_CMD 		"findserver"
+#define RWL_WIFI_ACTION_CMD   		"wifiaction"
+#define RWL_WIFI_GET_ACTION_CMD         "rwlwifivsaction"
+#define RWL_DONGLE_SET_CMD			"dongleset"
+#define DATA_FRAME_LEN				960
+/* wl & shell cmd work fine for 960 (512+256+128+64) */
+
+
+/*
+ * Information about the action frame data fields in the
+ * dot11_action_wifi_vendor_specific
+ * cdc struct (1 to 16. This does not include status flag. Since this
+ * is not directly visible to the driver code we cant use sizeof struct
+ * cdc_ioctl_t. Hence Ref MAC address offset starts from byte 17.
+ * REF MAC ADDR (6 bytes (MAC Address len) from byte 17 to 22)
+ * DUT MAC ADDR (6 bytes after the REF MAC Address byte 23 to 28)
+ * unused (byte 29 to 49)
+ * REF/Client Channel offset (50)
+ * DUT/Server channel offset (51)
+ * ---------------------------------------------------------------------------------------
+ * cdc struct|REF MAC ADDR|DUT_MAC_ADDR|un used|REF Channel|DUT channel|Action frame Data|
+ * 1---------17-----------23-------------------50----------51----------52----------------1040
+ * REF MAC addr after CDC struct without status flag (status flag not used by wifi)
+ */
+#define RWL_ACTION_WIFI_CATEGORY	127  /* Vendor Specific category value for wifi */
+#define RWL_REF_MAC_ADDRESS_OFFSET	17
+#define RWL_DUT_MAC_ADDRESS_OFFSET	23
+#define RWL_WIFI_CLIENT_CHANNEL_OFFSET	50
+#define RWL_WIFI_SERVER_CHANNEL_OFFSET	51
+
+#define SUCCESS 					1
+#define FAIL   						-1
+#define NO_PACKET        			-2
+#define SERIAL_PORT_ERR  			-3
+
+#define DEFAULT_SERVER_PORT   		8000
+
+#define WL_MAX_BUF_LEN 				(127 * 1024)
+#define MAX_VISTA_ARGC				10
+#define HOST_TO_NETWORK				TRUE
+#define NETWORK_TO_HOST				FALSE
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ				16
+#endif
+
+#if defined(WIN32) || defined(LINUX)
+/* We don't want the server to allocate bigger buffers for some of the commands
+ * like scanresults. Server can still allocate 8K memory and send the response
+ * in fragments. This is used in case of Get commands only.
+ */
+#define SERVER_RESPONSE_MAX_BUF_LEN 8192
+#endif
+/* Used to set the cmds for wifi specific init */
+typedef struct remote_wifi_cmds {
+	uint32	cmd;		/* common ioctl definition */
+	char	*data;		/* max size of the data length */
+	int		value;
+} remote_wifi_cmds_t;
+
+/* Added for debug utility support */
+#define ERR		stderr
+#define OUTPUT	stdout
+
+#define DEBUG_DEFAULT	0x0001
+#define DEBUG_ERR		0x0001
+#define DEBUG_INFO		0x0002
+#define DEBUG_DBG		0x0004
+
+/* #ifdef TARGETOS_symbian */
+#define DPRINT_ERR	if (defined_debug & DEBUG_ERR) \
+			    fprintf
+#define DPRINT_INFO	if (defined_debug & DEBUG_INFO) \
+			    fprintf
+#define DPRINT_DBG	if (defined_debug & DEBUG_DBG) \
+			    fprintf
+extern unsigned short defined_debug;
+#ifdef WIN32
+/* Function defined in wlu.c for client and wlu_server_ce.c for server */
+extern int wl_atoip(const char *a, struct ipv4_addr *n);
+#endif
+/* Function defined to do host to network and network to host conversions */
+void rwl_swap_header(rem_ioctl_t *rem_ptr, bool host_to_network);
+
+/* Macros to access remote type */
+extern int remote_type;
+#define rwl_get_remote_type()		(remote_type)
+#define rwl_set_remote_type(type)	(remote_type = type)
+
+/* Macros to access server IP and port globals */
+extern char *g_rwl_servIP;
+#define rwl_get_server_ip()			(g_rwl_servIP)
+#define rwl_set_server_ip(ip) 		(g_rwl_servIP = ip)
+extern unsigned short g_rwl_servport;
+#define rwl_get_server_port()		(g_rwl_servport)
+#define rwl_set_server_port(port) 	(g_rwl_servport = port)
+
+extern int rwl_read_serial_port(void* hndle, char* read_buf, uint data_size, uint *numread);
+extern int rwl_write_serial_port(void* hndle, char* write_buf, unsigned long size,
+unsigned long *numwritten);
+extern void rwl_sleep(int delay);
+extern void* rwl_open_transport(int remote_type, char *port, int ReadTotalTimeout, int debug);
+extern int rwl_close_transport(int remote_type, void * handle);
+extern int rwl_poll_serial_buffer(void *hndle);
+extern int rwl_serial_handle_timeout(void);
+extern void rwl_sync_delay(uint noframes);
+
+#ifdef RWL_SOCKET
+extern int rwl_connectsocket(int SocketDes, struct sockaddr* SerAddr, int SizeOfAddr);
+extern  int rwl_acceptconnection(int SocketDes, struct sockaddr *ClientAddr, int *SizeOfAddr);
+extern int rwl_send_to_streamsocket(int SocketDes, const char* SendBuff, int data_size, int Flag);
+extern int rwl_receive_from_streamsocket(int SocketDes, char* RecvBuff, int data_size, int Flag);
+extern int rwl_init_server_socket_setup(int argc, char** argv, uint remote_type);
+extern int rwl_GetifAddr(char *ifname, struct sockaddr_in* sa);
+#endif /* RWL_SOCKET */
+
+#if defined(LINUX)
+extern int set_interface(void *wl, char *intf_name);
+#endif /* defined(LINUX) */
+
+/* Win32 specific function wlu_pipe_win32.c */
+extern int rwl_init_ws2_32dll(void);
+extern int rwl_terminate_ws2_32dll(void);
+
+/* Function definitions for wlu_client_shared.c and wlu_server_shared.c */
+extern int rwl_var_getbuf(void *wl, const char *iovar, void *param, int param_len, void **bufptr);
+extern int rwl_var_setbuf(void *wl, const char *iovar, void *param, int param_len);
+extern int rwl_var_send_vs_actionframe(void* wl, const char* iovar, void* param, int param_len);
+
+/* Function definitions for wlu_ndis.c/wlu_linux.c  and wlu_server_ce.c/wlu_server_linux.c  */
+extern int wl_get(void *wl, int cmd, void *buf, int len);
+extern int wl_set(void *wl, int cmd, void *buf, int len);
+#ifdef RWLASD
+typedef unsigned char BYTE;
+extern void wfa_dut_init(BYTE **tBuf, BYTE **rBuf, BYTE **paBuf, BYTE **cBuf, struct timeval **);
+extern int remote_asd_exec(unsigned char* command, int* cmd_len);
+void wfa_dut_deinit(void);
+#endif
+extern int get_ctrlc_header(void *wl);
+extern int remote_tx_response(void *wl, void *buf_ptr, int cmd);
+extern rem_ioctl_t *g_rem_ptr;
+extern int g_rwl_hndle;
+#if defined(LINUX)
+/* Variable to indiate if the server child has completed execution */
+extern volatile sig_atomic_t g_sig_chld;
+#endif
+
+extern int rwl_check_port_number(char *s, int len);
+
+/*
+ * Separate paths are defined for android and linux machines
+ * / filesystem on android is read only memory
+ */
+#ifndef WIN32
+#ifdef TARGETENV_android
+#define SH_PATH "/data/busybox/sh"
+#define SHELL_RESP_PATH  "/data/local/RWL/" /* Default path for storing files for shell response */
+#define	TEMPLATE         "/data/local/RWL/SyncXXXXXX"
+#else
+#define SHELL_RESP_PATH  "/tmp/RWL/" /* Default path for storing files for shell response */
+#define	TEMPLATE         "/tmp/RWL/SyncXXXXXX"
+#define SH_PATH "/bin/sh"
+#endif
+#endif /* !WIN32 */
+#endif /* _wlu_remote_h */
diff --git a/wl/src/wl/exe/wlu_server_linux.c b/wl/src/wl/exe/wlu_server_linux.c
new file mode 100644
index 0000000..0163bf9
--- /dev/null
+++ b/wl/src/wl/exe/wlu_server_linux.c
@@ -0,0 +1,400 @@
+/*
+ * Wl server for linux
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_server_linux.c 659779 2016-09-15 23:33:28Z $
+ */
+
+/* Revision History:Linux port of Remote wl server
+ *
+ * Date        Author         Description
+ *
+ * 27-Dec-2007 Suganthi        Version 0.1
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+#ifndef TARGETENV_android
+#include <linux/types.h>
+#endif
+
+#include <linux/sockios.h>
+#include <linux/ethtool.h>
+
+#include <typedefs.h>
+#include <wlioctl.h>
+#include <dhdioctl.h>
+#include <proto/ethernet.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#include <bcmcdc.h>
+#include <proto/802.11.h>
+#include "wlu_remote.h"
+
+
+#define DEV_TYPE_LEN    3 /* length for devtype 'wl'/'et' */
+#define BUF_LENGTH		1000
+
+#define dtoh32(i) i
+
+
+#ifdef IL_BIGENDIAN
+bool swap = FALSE;
+#endif
+const char *rwl_server_name;
+void *g_wl_handle;
+unsigned short defined_debug = DEBUG_ERR | DEBUG_INFO;
+extern int remote_server_exec(int argc, char **argv, void *ifr);
+
+/* Global to have the PID of the current sync command
+ * This is required in case the sync command fails to respond,
+ * the alarm handler shall kill the PID upon a timeout
+ */
+int g_shellsync_pid;
+unsigned char g_return_stat = 0;
+
+static void
+syserr(char *s)
+{
+	fprintf(stderr, "%s: ", rwl_server_name);
+	perror(s);
+	exit(errno);
+}
+/* The handler for DHD commands */
+int
+dhd_ioctl(void *dhd, int cmd, void *buf, int len, bool set)
+{
+	struct ifreq *ifr = (struct ifreq *) dhd;
+	dhd_ioctl_t ioc;
+	int ret = 0;
+	int s;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	/* do it */
+	ioc.cmd = cmd;
+	ioc.buf = buf;
+	ioc.len = len;
+	ioc.set = set;
+	ioc.driver = DHD_IOCTL_MAGIC;
+	ifr->ifr_data = (caddr_t) &ioc;
+	if ((ret = ioctl(s, SIOCDEVPRIVATE, ifr)) < 0) {
+		if (cmd != DHD_GET_MAGIC) {
+			ret = BCME_IOCTL_ERROR;
+		}
+	}
+	/* cleanup */
+	close(s);
+	return ret;
+}
+
+int
+wl_ioctl(void *wl, int cmd, void *buf, int len, bool set)
+{
+	struct ifreq *ifr = (struct ifreq *) wl;
+	wl_ioctl_t ioc;
+	int ret = 0;
+	int s;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	/* do it */
+	ioc.cmd = cmd;
+	ioc.buf = buf;
+	ioc.len = len;
+	ioc.set = set;
+	ifr->ifr_data = (caddr_t) &ioc;
+	if ((ret = ioctl(s, SIOCDEVPRIVATE, ifr)) < 0) {
+		if (cmd != WLC_GET_MAGIC) {
+			ret = BCME_IOCTL_ERROR;
+		}
+	}
+	/* cleanup */
+	close(s);
+	return ret;
+}
+
+/* Functions copied from wlu.c to check for the driver adapter in the server machine */
+int
+wl_check(void *wl)
+{
+	int ret;
+	int val;
+
+	if ((ret = wl_ioctl(wl, WLC_GET_MAGIC, &val, sizeof(int), FALSE)) < 0)
+		return ret;
+#ifdef IL_BIGENDIAN
+	/* Detect if IOCTL swapping is necessary */
+	if (val == (int)bcmswap32(WLC_IOCTL_MAGIC))
+	{
+		val = bcmswap32(val);
+		swap = TRUE;
+	}
+#endif
+	if (val != WLC_IOCTL_MAGIC)
+		return -1;
+	if ((ret = wl_ioctl(wl, WLC_GET_VERSION, &val, sizeof(int), FALSE)) < 0)
+		return ret;
+	val = dtoh32(val);
+
+	if (val > WLC_IOCTL_VERSION) {
+		fprintf(stderr, "Version mismatch, please upgrade\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int
+wl_get_dev_type(char *name, void *buf, int len)
+{
+	int s;
+	int ret;
+	struct ifreq ifr;
+	struct ethtool_drvinfo info;
+
+	/* open socket to kernel */
+	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+		syserr("socket");
+
+	/* get device type */
+	memset(&info, 0, sizeof(info));
+	info.cmd = ETHTOOL_GDRVINFO;
+	ifr.ifr_data = (caddr_t)&info;
+	strncpy(ifr.ifr_name, name, IFNAMSIZ);
+	if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
+	/* print a good diagnostic if not superuser */
+		if (errno == EPERM)
+			syserr("wl_get_dev_type");
+		*(char *)buf = '\0';
+	} else {
+		strncpy(buf, info.driver, len);
+	}
+	close(s);
+	return ret;
+}
+
+static void
+wl_find_adapter(struct ifreq *ifr)
+{
+	char proc_net_dev[] = "/proc/net/dev";
+	FILE *fp;
+	char buf[BUF_LENGTH], *c, *name;
+	char dev_type[DEV_TYPE_LEN];
+
+	ifr->ifr_name[0] = '\0';
+
+	if (!(fp = fopen(proc_net_dev, "r")))
+		return;
+
+	/* eat first two lines */
+	if (!fgets(buf, sizeof(buf), fp) ||
+	    !fgets(buf, sizeof(buf), fp)) {
+		fclose(fp);
+		return;
+	}
+
+	while (fgets(buf, sizeof(buf), fp)) {
+		c = buf;
+		while (isspace(*c))
+			c++;
+		if (!(name = strsep(&c, ":")))
+			continue;
+		strncpy(ifr->ifr_name, name, IFNAMSIZ-1);
+		ifr->ifr_name[IFNAMSIZ-1] = 0;
+
+		/*
+		 * If no -i interface, prioritize ethX, not say wl1.2
+		 * wlanX is Android
+		 */
+		if (!strncmp(name, "wl", 2) && strncmp(name, "wlan", 4)) {
+			continue;
+		}
+
+		if (wl_get_dev_type(name, dev_type, DEV_TYPE_LEN) >= 0 &&
+			!strncmp(dev_type, "wl", 2))
+		if (wl_check((void *) ifr) == 0)
+				break;
+		ifr->ifr_name[0] = '\0';
+	}
+
+	fclose(fp);
+}
+
+int
+wl_get(void *wl, int cmd, void *buf, int len)
+{
+	int error;
+
+	error = wl_ioctl(wl, cmd, buf, len, FALSE);
+
+	return error;
+}
+
+int
+wl_set(void *wl, int cmd, void *buf, int len)
+{
+	int error;
+
+	error = wl_ioctl(wl,  cmd, buf, len, TRUE);
+
+	return error;
+}
+
+extern int set_ctrlc;
+void handle_ctrlc(int unused)
+{
+	UNUSED_PARAMETER(unused);
+	set_ctrlc = 1;
+	return;
+}
+
+volatile sig_atomic_t g_sig_chld = 1;
+void rwl_chld_handler(int num)
+{
+	int child_status;
+
+	UNUSED_PARAMETER(num);
+	/* g_return_stat is being set with the return status of sh commands */
+	waitpid(g_shellsync_pid, &child_status, WNOHANG);
+	if (WIFEXITED(child_status))
+		g_return_stat = WEXITSTATUS(child_status);
+	else if (g_rem_ptr->msg.flags == (unsigned)CTRLC_FLAG)
+		g_return_stat = 0;
+	else
+		g_return_stat = 1;
+	g_sig_chld = 0;
+}
+
+/* Alarm handler called after SHELL_TIMEOUT value
+ * This handler kills the non-responsive shell process
+ * with the PID value g_shellsync_pid
+ */
+static void
+sigalrm_handler(int s)
+{
+	UNUSED_PARAMETER(s);
+
+	if (g_shellsync_pid) {
+		kill(g_shellsync_pid, SIGINT);
+	}
+#ifdef RWL_SOCKET
+	g_sig_chld = 0;
+#endif
+}
+
+static void
+def_handler(int s)
+{
+	UNUSED_PARAMETER(s);
+	kill(g_shellsync_pid, SIGKILL);
+	exit(0);
+}
+
+static void
+pipe_handler(int s)
+{
+	UNUSED_PARAMETER(s);
+	kill(g_shellsync_pid, SIGKILL);
+}
+
+int
+main(int argc, char **argv)
+{
+	int err = 0;
+	struct ifreq *ifr;
+
+	rwl_server_name = argv[0];
+
+	if ((ifr = calloc(1, sizeof(*ifr))) == NULL)
+	{
+		DPRINT_ERR(ERR, "wl_server: Unable to allocate memory for handle\n");
+		exit(1);
+	}
+
+	memset(ifr, 0, sizeof(*ifr));
+#ifdef PCIE_MFGTEST
+	/* For router platform hardcode to eth1 */
+	strcpy(ifr->ifr_name, "eth1");
+#endif /* PCIE_MFGTEST */
+
+	/* use default interface */
+	if (!ifr->ifr_name[0])
+		wl_find_adapter(ifr);
+	/* validate the interface */
+	if (!ifr->ifr_name[0] || wl_check((void *)ifr)) {
+		DPRINT_INFO(OUTPUT, "wl_server: wl driver adapter not found\n");
+	}
+	g_wl_handle = ifr;
+
+	/* Register signal handlers */
+	signal(SIGCHLD, rwl_chld_handler);
+	signal(SIGALRM, sigalrm_handler);
+	signal(SIGTERM, def_handler);
+	signal(SIGPIPE, pipe_handler);
+	signal(SIGABRT, def_handler);
+#ifdef RWL_DONGLE
+	signal(SIGINT, handle_ctrlc);
+#endif
+	/* Main server process for all transport types */
+	err = remote_server_exec(argc, argv, ifr);
+	free(ifr);
+	return err;
+}
+
+/*
+ * Funtion to store old interface.
+ */
+void
+store_old_interface(void *wl, char *old_intf_name)
+{
+	strcpy(old_intf_name, ((struct ifreq *)wl)->ifr_name);
+}
+
+/*
+ * Function to set interface.
+ */
+int
+set_interface(void *wl, char *intf_name)
+{
+	struct ifreq *ifr = (struct ifreq *)wl;
+
+	if (strlen(intf_name) != 0) {
+		strncpy(ifr->ifr_name, intf_name, strlen(intf_name) + 1);
+		return BCME_OK;
+	}
+	else {
+		DPRINT_DBG(OUTPUT, "Default Interface will be used ... \n");
+		return BCME_ERROR;
+	}
+}
diff --git a/wl/src/wl/exe/wlu_server_shared.c b/wl/src/wl/exe/wlu_server_shared.c
new file mode 100644
index 0000000..9fdcb7d
--- /dev/null
+++ b/wl/src/wl/exe/wlu_server_shared.c
@@ -0,0 +1,1177 @@
+/*
+ * File Name: wlu_server_shared.c
+ * Common server specific functions for linux and win32
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_server_shared.c 570087 2015-07-09 22:10:06Z $
+ */
+
+/*
+ * Description: Main Server specific wrappers
+ * This module implements all the server specific functions
+ * for Win32 and Linux
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef TARGETOS_symbian
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+
+#else
+#if !defined(TARGETOS_nucleus)
+#include <malloc.h>
+#endif
+#endif /* TARGETOS_symbian */
+#include <assert.h>
+
+#include <errno.h>
+#ifndef WIN32
+#if !defined(TARGETOS_nucleus)
+#include <sys/types.h>
+#include <sys/socket.h>
+#if  !defined(TARGETOS_symbian)
+#include <arpa/inet.h>
+#include <net/if.h>
+#endif
+#include <unistd.h>
+#include <netdb.h>
+#include <signal.h>
+#endif /* TARGETOS_nucleus */
+#endif /* WIN32 */
+
+#ifdef WIN32
+#include <windows.h>
+#include <winioctl.h>
+#include <ntddndis.h>
+#include <typedefs.h>
+#include <epictrl.h>
+#include <irelay.h>
+#include <proto/ethernet.h>
+#include <nuiouser.h>
+#include <bcmendian.h>
+#include <oidencap.h>
+#include <bcmutils.h>
+#include <proto/802.11.h>
+#endif /* WIN32 */
+
+#include <bcmcdc.h>
+#include <wlioctl.h>
+#include <typedefs.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)
+#include <rwl_wifi.h>
+#endif /* defined(RWL_WIFI) || defined(WIFI_REFLECTOR) */
+#include "wlu.h"
+#include "wlu_remote.h"
+#include "wlu_pipe.h"
+#include "wlu_server_shared.h"
+#ifdef RWLASD
+extern int g_serv_sock_desc;
+#endif
+int g_rwl_hndle;
+int set_ctrlc = 0;
+
+#ifdef RWL_DONGLE
+static rem_ioctl_t loc_cdc;
+static const char* cmdname = "remote";
+static const char* dongleset = "dongleset";
+#endif
+
+#if defined(LINUX)
+extern void store_old_interface(void *wl, char *old_intf_name);
+extern int wl_check(void *wl);
+#endif /* defined(LINUX) */
+
+extern void handle_ctrlc(int unused);
+/* Function: rwl_transport_setup
+ * This will do the initialization for
+ * for all the transports
+ */
+static int
+rwl_transport_setup(int argc, char** argv)
+{
+	int transport_descriptor = -1;
+
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(argv);
+
+#ifdef RWL_SOCKET
+	/* This function will parse the socket command line arguments
+	 * & open the socket in listen mode
+	 */
+	remote_type = REMOTE_SOCKET;
+	transport_descriptor = rwl_init_server_socket_setup(argc, argv, remote_type);
+
+	if (transport_descriptor < 0) {
+		DPRINT_ERR(ERR, "wl_socket_server:Transport setup failed \n");
+	}
+#endif /* RWL_SOCKET */
+#if defined(RWL_DONGLE) || defined(RWL_WIFI) || defined(RWL_SERIAL)
+	g_rem_pkt_ptr = &g_rem_pkt;
+	transport_descriptor = 0;
+
+#ifdef RWL_WIFI
+	remote_type = REMOTE_WIFI;
+#endif
+
+#ifdef RWL_DONGLE
+	remote_type = REMOTE_DONGLE;
+#endif /* RWL_DONGLE */
+#ifdef RWL_SERIAL
+	remote_type = REMOTE_SERIAL;
+	if (argc < 2) {
+		DPRINT_ERR(ERR, "Port name is required from the command line\n");
+	} else {
+		(void)*argv++;
+		DPRINT_DBG(OUTPUT, "Port name is %s\n", *argv);
+		transport_descriptor = *(int*) rwl_open_transport(remote_type, *argv, 0, 0);
+	}
+#endif  /* RWL_SERIAL */
+#endif /* RWL_DONGLE ||RWL_SERIAL ||RWL_WIFI */
+#ifdef RWLASD
+	g_serv_sock_desc = transport_descriptor;
+#endif
+	return transport_descriptor;
+
+}
+
+/* Function: remote_rx_header
+ * This function will receive the CDC header from client
+ * for socket transport
+ * It will receive the command or ioctl from dongle driver for
+ * dongle UART serial transport and wifi transport.
+ * Arguments: wl - handle to driver
+ *          : Des - Socket Descriptor to pass in AcceptConnection
+ *          : g_rwl_hndle - Return socket handle that is used for transmission
+ *          :           and reception of data in case of socket
+ *                        In case of serial, it is just a return value
+ */
+static int
+remote_rx_header(void *wl, int trans_Des)
+{
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(trans_Des);
+
+#ifdef RWL_SOCKET
+	{
+		struct sockaddr_in ClientAddress;
+		int SizeOfCliAdd = sizeof(ClientAddress);
+
+		/* Get the socket handle g_rwl_hndle for transmission & reception */
+		if ((g_rwl_hndle = rwl_acceptconnection(trans_Des,
+		                                        (struct sockaddr *)&ClientAddress,
+		                                        &SizeOfCliAdd)) == BCME_ERROR) {
+			return BCME_ERROR;
+		}
+
+		/* Get CDC header in order to determine buffer requirements */
+		if ((g_rem_ptr = remote_CDC_rx_hdr((void *)&g_rwl_hndle, 0)) == NULL) {
+			DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
+			return BCME_ERROR;
+		}
+	}
+#endif /* RWL_SOCKET */
+
+#ifdef RWL_DONGLE
+	{
+		void *pkt_ptr = NULL;
+		int error;
+
+		/* wl driver is polled after every 200 ms (POLLING_TIME) */
+		rwl_sleep(POLLING_TIME);
+
+		if ((error = rwl_var_getbuf(wl, cmdname, NULL, 0, &pkt_ptr)) < 0) {
+			DPRINT_ERR(ERR, "No packet in wl driver\r\n");
+			return BCME_ERROR;
+		}
+
+		DPRINT_DBG(OUTPUT, "Polling the wl driver, error status=%d\n", error);
+
+		if ((*(int *)pkt_ptr) == 0) {
+			DPRINT_DBG(ERR, "packet not received\n");
+			return BCME_ERROR;
+		}
+
+		DPRINT_DBG(OUTPUT, "packet received\n");
+
+		/* Extract CDC header in order to determine buffer requirements */
+		memcpy(g_rem_pkt_ptr, pkt_ptr, sizeof(rem_packet_t));
+		g_rem_ptr = &g_rem_pkt_ptr->rem_cdc;
+	}
+#endif /* RWL_DONGLE */
+
+#ifdef RWL_SERIAL
+	{
+		if (g_rwl_hndle == -1) {
+			DPRINT_ERR(ERR, "failed to open com port.\r\n");
+			return BCME_ERROR;
+		}
+
+		if ((g_rem_ptr = remote_CDC_rx_hdr((void *)&g_rwl_hndle, 1)) == NULL) {
+			DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
+			return BCME_ERROR;
+		}
+	}
+#endif  /* RWL_SERIAL */
+
+#ifdef RWL_WIFI
+	{
+		/* Poll the driver for the valid action frame and update the CDC + data  */
+		dot11_action_wifi_vendor_specific_t *list;
+		size_t cdc_and_actionframe_copy_length;
+
+		if ((list = rwl_wifi_allocate_actionframe()) == NULL) {
+			DPRINT_DBG(OUTPUT, "remote_rx_header: Failed to allocate frame \n");
+			return BCME_ERROR;
+		}
+
+		if (remote_CDC_DATA_wifi_rx((void *)wl, list) < 0) {
+			free(list);
+			return BCME_ERROR;
+		}
+
+		/* copy the valid length of the data to the g_rem_pkt_ptr */
+		cdc_and_actionframe_copy_length = sizeof(rem_packet_t) > sizeof(list->data[0])?
+			sizeof(list->data[0]): sizeof(rem_packet_t);
+		memcpy(g_rem_pkt_ptr, &list->data[0], cdc_and_actionframe_copy_length);
+		g_rem_ptr = &g_rem_pkt_ptr->rem_cdc;
+		free(list);
+	}
+#endif /* RWL_WIFI */
+
+	rwl_swap_header(g_rem_ptr, NETWORK_TO_HOST);
+
+	DPRINT_INFO(OUTPUT, "%d %d %d %d\r\n", g_rem_ptr->msg.cmd,
+	g_rem_ptr->msg.len, g_rem_ptr->msg.flags, g_rem_ptr->data_len);
+
+	return SUCCESS;
+
+}
+
+/* Function: remote_rx_data
+ * This function will receive the data from client
+ * for different transports
+ * In case of socket the data comes from a open TCP socket
+ * However in case of dongle UART or wi-fi the data is accessed
+ * from the driver buffers.
+ */
+int
+remote_rx_data(void* buf_ptr)
+{
+#if defined(RWL_SOCKET) || defined(RWL_SERIAL)
+
+	if ((remote_CDC_rx((void *)&g_rwl_hndle, g_rem_ptr, buf_ptr,
+	                             g_rem_ptr->msg.len, 0)) == BCME_ERROR) {
+		DPRINT_ERR(ERR, "Reading CDC %d data bytes failed\n", g_rem_ptr->msg.len);
+		return BCME_ERROR;
+	}
+#elif defined(RWL_DONGLE) || defined(RWL_WIFI)
+	if (g_rem_ptr->data_len != 0) {
+		int length = g_rem_ptr->data_len;
+		if (g_rem_ptr->data_len > g_rem_ptr->msg.len) {
+			length = g_rem_ptr->msg.len;
+		}
+		memcpy(buf_ptr, g_rem_pkt_ptr->message, length);
+	}
+	else
+		buf_ptr = NULL;
+#else
+	UNUSED_PARAMETER(buf_ptr);
+#endif /* RWL_SOCKET || RWL_SERIAL */
+	return SUCCESS;
+}
+
+#ifdef RWL_DONGLE
+/*
+ * Function to send the serial response to wl driver
+ * The function calculates the no of frames based on the DATA_FRAME_LEN
+ * adds cdc header to every frame, copies the header and fragmented frame
+ * into rem_buf_ptr and sends the packet down to wl driver
+ */
+
+static int
+rwl_serial_fragmented_tx(void* wl, rem_ioctl_t *rem_ptr, uchar *buf_ptr, int error)
+{
+	rem_ioctl_t *loc_ptr = &loc_cdc;
+	uchar* rem_buf_ptr;
+	uint noframes = 1;    /* Default noframes = 1 */
+	uint count;
+	uint frame_count;
+	uint rem_bytes;
+
+	loc_ptr->msg.cmd = error;
+	loc_ptr->msg.flags = REMOTE_REPLY;
+	loc_ptr->msg.len = rem_ptr->msg.len;
+	loc_ptr->data_len = rem_ptr->data_len;
+
+	/* Fragment the result if it is more than DATA_FRAME_LEN (960) */
+	if (loc_ptr->msg.len > DATA_FRAME_LEN) {
+		/* Calculate no of frames */
+		noframes = (loc_ptr->msg.len)/DATA_FRAME_LEN;
+		if ((loc_ptr->msg.len) % DATA_FRAME_LEN > 0) {
+			noframes += 1;
+			rem_bytes = (loc_ptr->msg.len) % DATA_FRAME_LEN;
+		} else {
+			rem_bytes = DATA_FRAME_LEN;
+		}
+	} else {
+		rem_bytes = loc_ptr->msg.len;
+	}
+	DPRINT_INFO(OUTPUT, "No of frames = %d, rem_bytes:%d\n", noframes, rem_bytes);
+	count = 0;
+	frame_count = noframes;
+	rem_buf_ptr = (uchar*)malloc(DONGLE_TX_FRAME_SIZE + REMOTE_SIZE);
+
+	while (count < noframes) {
+		memset(rem_buf_ptr, 0, DONGLE_TX_FRAME_SIZE + REMOTE_SIZE);
+		/* Send reply to client */
+		rem_ptr->msg.cmd = loc_ptr->msg.cmd;
+		rem_ptr->msg.flags = loc_ptr->msg.flags;
+		rem_ptr->msg.len = loc_ptr->msg.len;
+
+		if (frame_count == 1)
+			rem_ptr->data_len = rem_bytes;
+		else
+			rem_ptr->data_len = DATA_FRAME_LEN;
+
+		DPRINT_DBG(OUTPUT, "GET--rem_ptr->data_len=%d\n", rem_ptr->data_len);
+
+		/* Copy CDC Header */
+		memcpy(rem_buf_ptr, (uchar*)rem_ptr, REMOTE_SIZE);
+
+		/* Copy Data now */
+		memcpy(&rem_buf_ptr[REMOTE_SIZE], &buf_ptr[count*DATA_FRAME_LEN],
+		                                              rem_ptr->data_len);
+		count++;
+		frame_count--;
+
+		DPRINT_INFO(OUTPUT, "FRAME %d\n", count);
+		DPRINT_INFO(OUTPUT, "%d %d  %d  %d\n", rem_ptr->msg.cmd, rem_ptr->msg.len,
+			rem_ptr->msg.flags, rem_ptr->data_len);
+
+		rwl_sync_delay(noframes);
+
+		if ((error = rwl_var_setbuf(wl, cmdname, rem_buf_ptr,
+		            DONGLE_TX_FRAME_SIZE+REMOTE_SIZE)) < 0) {
+			DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", error);
+			if (rem_buf_ptr)
+				free(rem_buf_ptr);
+			return BCME_ERROR;
+		}
+		else
+			DPRINT_INFO(OUTPUT, "Packet sent to wl driver,error=%d\n", error);
+	}
+
+	if (rem_buf_ptr)
+		free(rem_buf_ptr);
+
+	return error;
+}
+
+/* This function transmits the response to the dongle driver in the case
+ * of serial dongle transport.
+ * In the case of big response, it calls the rwl_serial_fragmented_response
+ * function to fragment the response and sends down to the driver.
+ */
+
+static int
+remote_CDC_dongle_tx(void *wl, uint cmd, uchar *buf, uint buf_len, uint data_len, uint flags)
+{
+	int error;
+	rem_ioctl_t resp_rem_cdc;
+
+	if (flags & REMOTE_SET_IOCTL) {
+		uchar* rem_buf_ptr;
+		/* for set commands message length and data length should be set to zero
+		 * unlike Get Ioctl which will have valid data and message length
+		 */
+		resp_rem_cdc.msg.len = 0;
+		resp_rem_cdc.data_len = 0;
+		resp_rem_cdc.msg.cmd = cmd;
+		resp_rem_cdc.msg.flags = REMOTE_REPLY;
+
+		DPRINT_INFO(OUTPUT, "Set:Resp packet:%d %d %d %d\n", resp_rem_cdc.msg.cmd,
+		resp_rem_cdc.msg.len, resp_rem_cdc.msg.flags, resp_rem_cdc.data_len);
+
+		if ((rem_buf_ptr = (uchar*)malloc(DONGLE_TX_FRAME_SIZE + REMOTE_SIZE)) == NULL) {
+			DPRINT_ERR(ERR, "malloc failed for remote_CDC_dongle_tx\n");
+			return BCME_ERROR;
+		}
+
+		/* Send reply to client here */
+		memcpy(rem_buf_ptr, (char*)(&resp_rem_cdc), REMOTE_SIZE);
+		if ((error = rwl_var_setbuf((void*)wl, cmdname, rem_buf_ptr,
+		                 DONGLE_TX_FRAME_SIZE + REMOTE_SIZE)) < 0) {
+			DPRINT_ERR(ERR, "unable to send SET results to driver=%d\n", error);
+		} else
+			DPRINT_INFO(OUTPUT, "Packet sent to wl driver, error=%d\n", error);
+
+		if (rem_buf_ptr)
+			free(rem_buf_ptr);
+
+	} else { /* GET_IOCTL */
+		resp_rem_cdc.msg.cmd = cmd;
+		resp_rem_cdc.msg.len = buf_len;
+		resp_rem_cdc.msg.flags = flags;
+		resp_rem_cdc.data_len = data_len;
+		if ((error = rwl_serial_fragmented_tx(wl, &resp_rem_cdc, buf, cmd)) < 0)
+			DPRINT_ERR(ERR, "wl_server_serial: Return error code failed\n");
+	}
+	return error;
+}
+#endif /* RWL_DONGLE */
+
+/* This function gets the command send by the client from the dongle driver */
+int
+rwl_var_getbuf(void* wl, const char* iovar, void* param, int param_len, void** buf_ptr)
+{
+	int len;
+
+	memset(rwl_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy((char*)rwl_buf, iovar);
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&rwl_buf[len], param, param_len);
+
+	*buf_ptr = rwl_buf;
+
+	return wl_get(wl, WLC_GET_VAR, &rwl_buf[0], WLC_IOCTL_MAXLEN);
+}
+
+/* This function will send the buffer to the dongle driver */
+int
+rwl_var_setbuf(void* wl, const char* iovar, void* param, int param_len)
+{
+	int len;
+
+	memset(rwl_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy((char*)rwl_buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy(&rwl_buf[len], param, param_len);
+
+	len  += param_len;
+
+	DPRINT_DBG(OUTPUT, "setbuf:%s, len:%d\n", rwl_buf, len);
+
+	return wl_set(wl, WLC_SET_VAR, &rwl_buf[0], len);
+}
+
+/* This function will send the buffer to the dongle driver */
+int
+rwl_var_send_vs_actionframe(void* wl, const char* iovar, void* param, int param_len)
+{
+	int len;
+
+	memset(rwl_buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy((char*) rwl_buf, iovar);
+
+	/* include the null */
+	len = strlen(iovar) + 1;
+
+	if (param_len)
+		memcpy((void*)&rwl_buf[len+ OFFSETOF(wl_action_frame_t, data)], param, param_len);
+
+	/* Set the PacketID (not used by remote WL */
+	memset((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, packetId)], 0, 4);
+
+	/* Set the dest addr */
+	memcpy((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, da)],
+	(void*)&rwlea,
+	ETHER_ADDR_LEN);
+
+	/*  set the length */
+	memcpy((void*)&rwl_buf[len + OFFSETOF(wl_action_frame_t, len)], (void*) &param_len, 2);
+
+	len  += param_len + ETHER_ADDR_LEN + 2 + 4;
+
+	DPRINT_DBG(OUTPUT, "setbuf:%s, len:%d\n", rwl_buf, len);
+
+	return wl_set(wl, WLC_SET_VAR, &rwl_buf[0], len);
+}
+/*
+ * This function is used for transmitting the response over different
+ * transports.
+ * In case of socket the data is directly sent to the client which is waiting on a open socket.
+ * In case of socket the data is sent in one big chunk unlike other transports
+ *
+ * In case of serial the data is sent to the driver using remote_CDC_dongle_tx function
+ * which in turn may fragment the data and send it in chunks to the client.
+ *
+ * In case of wi-fi the data is sent to the driver using the remote_CDC_tx. However
+ * in this case the data is converted into 802.11 Action frames and sent using wi-fi driver.
+ * Arguments: wl - Driver handle
+ *            hndle - Socket handle for socket transport.
+ */
+int
+remote_tx_response(void *wl, void* buf_ptr, int cmd)
+{
+	int error = -1;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(buf_ptr);
+	UNUSED_PARAMETER(cmd);
+
+#if defined(RWL_SOCKET) || defined(RWL_SERIAL)
+	if ((error = remote_CDC_tx((void*)&g_rwl_hndle, cmd, buf_ptr, g_rem_ptr->msg.len,
+	                                  g_rem_ptr->msg.len, REMOTE_REPLY, 0)) < 0)
+		DPRINT_ERR(ERR, "wl_server: Return results failed\n");
+#endif /* RWL_SOCKET || RWL_SERIAL */
+
+#ifdef RWL_DONGLE
+	if ((error = remote_CDC_dongle_tx(wl, cmd, buf_ptr, g_rem_ptr->msg.len,
+	                          g_rem_ptr->data_len, g_rem_ptr->msg.flags)) < 0)
+		DPRINT_ERR(ERR, "wl_server: Return results failed\n");
+#endif /* RWL_DONGLE */
+
+#ifdef RWL_WIFI
+	/* Purge all the queued cmd's , this to ensure late response time out at */
+	/* client side and client might issue the next cmd if server is slow */
+	if ((error = rwl_wifi_purge_actionframes(wl)) < 0)
+		return error;
+	if ((g_rem_ptr->msg.flags & REMOTE_SHELL_CMD) ||
+		(g_rem_ptr->msg.flags & REMOTE_GET_IOCTL)||
+		(g_rem_ptr->msg.flags & REMOTE_ASD_CMD) ||
+		(g_rem_ptr->msg.flags & REMOTE_VISTA_CMD)) {
+		if ((error = remote_CDC_tx(wl, cmd, buf_ptr, g_rem_ptr->msg.len,
+			g_rem_ptr->msg.len, REMOTE_REPLY, 0)) < 0)
+			DPRINT_ERR(ERR, "Wifi_server: Return results failed\n");
+	} else {
+		if ((error = remote_CDC_tx(wl, cmd, buf_ptr, 0, 0, REMOTE_REPLY, 0)) < 0)
+			DPRINT_ERR(ERR, "Failed due to bad flag %d\n", g_rem_ptr->msg.flags);
+	}
+#endif /* RWL_WIFI */
+	return error;
+}
+
+/* Close the Socket handle */
+void close_sock_handle(int hndle)
+{
+#ifdef RWL_SOCKET
+	rwl_close_pipe(remote_type, (void*)&hndle);
+#else
+	UNUSED_PARAMETER(hndle);
+#endif
+}
+
+
+/*
+ * Send the response to the remote if the channel of the server matches with the
+ * server channel.
+ */
+void remote_wifi_response(void* wl)
+{
+#ifdef RWL_WIFI
+	dot11_action_wifi_vendor_specific_t *list;
+
+	if ((list = rwl_wifi_allocate_actionframe()) == NULL) {
+		DPRINT_DBG(OUTPUT, "remote_wifi_response: Failed to allocate frame \n");
+		return;
+	}
+
+	/* it's sync frame and received from client */
+	memcpy((char*)&list->data[RWL_WIFI_CDC_HEADER_OFFSET],
+	&g_rem_pkt_ptr[RWL_WIFI_CDC_HEADER_OFFSET], REMOTE_SIZE);
+	memcpy((char*)&list->data[REMOTE_SIZE], g_rem_pkt_ptr->message,
+	RWL_WIFI_FRAG_DATA_SIZE);
+	list->type = RWL_WIFI_FIND_MY_PEER;
+	/* Store the client mac addr */
+	memcpy((void*)&rwlea, (void*)&list->data[RWL_DUT_MAC_ADDRESS_OFFSET], ETHER_ADDR_LEN);
+	/* send the response to client if server is on the same channel */
+	rwl_wifi_find_server_response(wl, list);
+
+	free(list);
+#else
+	UNUSED_PARAMETER(wl);
+#endif /* RWL_WIFI */
+	return;
+}
+
+/* Function to check IN-dongle mode firmware */
+int
+rwl_iovar_check(void *wl)
+{
+	void *ptr;
+#ifdef RWL_WIFI
+	dot11_action_wifi_vendor_specific_t rec_frame;
+
+	/* Check for indongle mode firmware */
+	return rwl_var_getbuf(wl, RWL_WIFI_GET_ACTION_CMD, &rec_frame,
+	RWL_WIFI_ACTION_FRAME_SIZE, &ptr);
+#endif
+	UNUSED_PARAMETER(ptr);
+	UNUSED_PARAMETER(wl);
+#ifdef RWL_DONGLE
+	return rwl_var_getbuf(wl, "remote", NULL, 0, &ptr);
+#else
+	return 0;
+#endif
+}
+
+
+#ifndef TARGETOS_symbian
+/* Function to get a ctrl-c packet */
+int
+get_ctrlc_header(void *wl)
+{
+#if defined(RWL_SOCKET) || defined(RWL_SERIAL)
+	fd_set fdset;
+	struct timeval tv;
+	UNUSED_PARAMETER(wl);
+	FD_ZERO(&fdset);
+	FD_SET((unsigned)g_rwl_hndle, &fdset);
+	tv.tv_sec = 0;
+	tv.tv_usec = 0;
+	if ((select(g_rwl_hndle+1, &fdset, NULL, NULL, &tv)) > 0) {
+		if (FD_ISSET(g_rwl_hndle, &fdset)) {
+			remote_CDC_rx_hdr((void *)&g_rwl_hndle, 0);
+			return BCME_OK;
+		}
+	}
+	return BCME_ERROR;
+
+#else
+	return remote_rx_header(wl, 0);
+#endif /* if defined(RWL_SOCKET) || defined(RWL_SERIAL) */
+}
+#endif /* TARGETOS_symbian */
+
+/* Main server module common for all transports
+ * This module will do the initial transport setups.
+ * Then it receives the command from client in CDC format
+ * and transmits the response back to the client.
+ * In the case of socket, it receives the command from the client
+ * and sends the response directly to the client via TCP socket.
+ *
+ * In the case of serial & wifi , it receives the command from the driver
+ * and sends the response to the driver.
+ */
+#if defined(PCIE_MFGTEST)
+	char *fw_download_path = "/tmp/media/nand/rtecdc.bin";
+	char *nvram_download_path = "/tmp/media/nand/nvram.txt";
+#endif
+int
+remote_server_exec(int argc, char **argv, void *wl)
+{
+	int err;
+	int transport_descriptor;
+	char *async_cmd_flag = NULL;
+	int skip;
+	int download_flag = 0;
+	FILE *fp = NULL;
+#if defined(PCIE_MFGTEST)
+	char *fn = fw_download_path;
+	char *fw = nvram_download_path;
+#else
+	char *fn = "dwnldfile.bin";
+	char *fw = "nvram.txt";
+#endif
+
+#if defined(LINUX) || defined(OLYMPIC_RWL)
+	char old_intf_name[IFNAMSIZ];
+#endif
+#ifdef WIN32
+	char shell_fname[MAX_SHELL_FILE_LENGTH];
+	DWORD dwlen;
+#endif
+#ifdef RWL_DONGLE
+	int uart_enable = 1;
+	/* To set dongle flag when dongle server starts */
+	if ((err = rwl_var_setbuf(wl, dongleset, &uart_enable,
+		sizeof(int))) < 0) {
+			DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", err);
+	}
+#endif
+	if (rwl_iovar_check (wl) < 0) {
+		DPRINT_ERR(ERR, "wl_server: RWL_WIFI/RWL_DONGLE not defined ");
+		DPRINT_ERR(ERR, "Or In-Dongle mode enabled\n");
+		exit(0);
+	}
+	/* Initialise for all the transports - socket, serial, and wifi
+	 * In Socket transport, main socket handler will be returned.
+	 */
+	if ((transport_descriptor = rwl_transport_setup(argc, argv)) < 0)
+		return BCME_ERROR;
+
+#ifdef RWL_WIFI
+	remote_wifi_ser_init_cmds(wl);
+#endif
+	/* Create a directory /tmp/RWL for the shell response files */
+	if (rwl_create_dir() < 0)
+		return BCME_ERROR;
+
+
+#ifdef RWLASD
+	/* DUT initialization function */
+	wfa_dut_init(&trafficBuf, &respBuf, &parmsVal, &xcCmdBuf, &toutvalp);
+#endif
+
+#if defined(LINUX)
+	/* Copy old interface name to restore it */
+	store_old_interface(wl, old_intf_name);
+#endif /* defined(LINUX) */
+
+	while (1) {
+		uchar *buf_ptr = NULL;
+#if defined(LINUX)
+		char *errstr = NULL;
+#endif
+#ifdef VISTA_SERVER
+		int index;
+		char *vista_buf[MAX_VISTA_ARGC];
+#endif
+#ifdef RWL_SERIAL
+		g_rwl_hndle = transport_descriptor;
+#else
+		g_rwl_hndle = -1;
+#endif
+#ifdef RWL_DONGLE
+		if (set_ctrlc) {
+			uart_enable = 0;
+			if ((err = rwl_var_setbuf(wl, dongleset, &uart_enable,
+				sizeof(int))) < 0) {
+				DPRINT_INFO(OUTPUT, "Unable to send to wl driver,error=%d\n", err);
+			}
+			set_ctrlc = 0;
+			exit(0);
+		}
+#endif /* RWL_DONGLE */
+
+		/* Receive the CDC header */
+		if ((remote_rx_header(wl, transport_descriptor)) == BCME_ERROR) {
+			DPRINT_DBG(OUTPUT, "\n Waiting for client to transmit command\n");
+			continue;
+		}
+
+		DPRINT_INFO(OUTPUT, "REC : cmd %d\t msg len %d  msg flag %d\t msg status %d\n",
+		            g_rem_ptr->msg.cmd, g_rem_ptr->msg.len,
+		            g_rem_ptr->msg.flags, g_rem_ptr->msg.status);
+
+#ifdef RWL_WIFI
+		/* send the response to remote if it is findserver cmd, this is specific to wifi */
+		if (g_rem_ptr->msg.flags & REMOTE_FINDSERVER_IOCTL) {
+			remote_wifi_response(wl);
+			continue;
+		}
+#endif /* RWL_WIFI */
+
+		/*
+		 * Allocate buffer only if there is a response message expected.
+		 * Some commands such as up/down do not output anything.
+		 */
+		if (g_rem_ptr->msg.len) {
+			if ((buf_ptr = malloc(g_rem_ptr->msg.len)) == NULL) {
+				DPRINT_ERR(ERR, "malloc of %d bytes failed\n", g_rem_ptr->msg.len);
+				continue;
+			}
+		}
+
+		/* Receive the data */
+		if ((err = remote_rx_data(buf_ptr)) == BCME_ERROR) {
+			if (buf_ptr)
+				free(buf_ptr);
+			continue;
+		}
+
+		/* Process RWL negotiate commands */
+		if (g_rem_ptr->msg.flags & REMOTE_NEGOTIATE_CMD) {
+			if (g_rem_ptr->msg.cmd == NEGOTIATE_GET_OS) {
+				if (g_rem_ptr->msg.len >= sizeof(int)) {
+#if defined(LINUX)
+					*(int*)buf_ptr = LINUX_OS;
+#elif defined(VISTA_SERVER)
+					*(int*)buf_ptr = WINVISTA_OS;
+#elif defined(WIN32)
+					*(int*)buf_ptr = WIN32_OS;
+#else
+					*(int*)buf_ptr = UNKNOWN_OS;
+#endif
+					g_rem_ptr->msg.len = sizeof(int);
+
+					DPRINT_INFO(OUTPUT, "RESP : os type %d\n", *(int*)buf_ptr);
+					if (remote_tx_response(wl, buf_ptr, 0) < 0)
+						DPRINT_ERR(ERR, "\nReturn results failed\n");
+				}
+			}
+#ifdef RWL_SOCKET
+			close_sock_handle(g_rwl_hndle);
+#endif /* RWL_SOCKET */
+			if (buf_ptr)
+				free(buf_ptr);
+			continue;
+		}
+
+		/* Process command */
+		if (g_rem_ptr->msg.flags & REMOTE_SHELL_CMD) {
+			/* Get the response length first and get the response buffer in case of
+			 * synchronous shell commands and the buf_ptr will have the response file
+			 * name. In case of asynchronous shell commands, buf_ptr
+			 * will be get updated by the remote_shell_execute function.
+			 */
+			need_speedy_response = 1;
+#ifndef WIN32
+			if (buf_ptr) {
+				async_cmd_flag = strstr((char*)buf_ptr, "%");
+			}
+			if ((err = remote_shell_execute((char*)buf_ptr, wl)) > 0) {
+				if (async_cmd_flag)
+					g_rem_ptr->msg.len = err;
+			}
+			/* Sync shell command: No need to send response from here */
+			else {
+#ifdef RWL_SOCKET
+				/* Transmitted to client. Then close the handle &
+				 * get the new handle for next transmission & reception.
+				 */
+				close_sock_handle(g_rwl_hndle);
+#endif /* RWL_SOCKET */
+				continue;
+			}
+#else
+			if ((err = remote_shell_execute((char*)buf_ptr, wl)) != SUCCESS) {
+				DPRINT_ERR(ERR, "Error in executing shell command\n");
+				if (buf_ptr)
+					free(buf_ptr);
+#ifdef RWL_SOCKET
+				/* Transmitted to client. Then close the handle &
+				 * get the new handle for next transmission & reception.
+				 */
+				close_sock_handle(g_rwl_hndle);
+#endif /* RWL_SOCKET */
+				continue;
+			}
+			/* Get the response from the temporary file */
+			if ((err = remote_shell_get_resp(shell_fname, wl)) != SUCCESS) {
+				DPRINT_ERR(ERR, "Error in executing shell command\n");
+			}
+			if (buf_ptr)
+				free(buf_ptr);
+#ifdef RWL_SOCKET
+			/* Transmitted to client. Then close the handle &
+			 * get the new handle for next transmission & reception.
+			 */
+			close_sock_handle(g_rwl_hndle);
+#endif /* RWL_SOCKET */
+			continue;
+#endif	/* WIN32 */
+		} /* REMOTE_SHELL_CMD */
+
+#ifdef RWLASD
+		if (g_rem_ptr->msg.flags & REMOTE_ASD_CMD) {
+			if ((err = remote_asd_exec(buf_ptr, (int *)&g_rem_ptr->msg.len)) < 0) {
+				DPRINT_ERR(ERR, "Error in executing asd command\n");
+			}
+		} /* REMOTE_ASD_CMD */
+#endif
+
+/*
+ * added to take care of OID base problem for cross OS RWL cleint server
+ * In case of LX Server and WIN32 client OID base need to be removed
+ * In case of WIN32 server and LX client OID base need to be added
+ */
+		if (!(g_rem_ptr->msg.flags & REMOTE_ASD_CMD)) {
+#if defined(LINUX)
+		if (g_rem_ptr->msg.cmd > MAX_IOVAR)
+			g_rem_ptr->msg.cmd -= WL_OID_BASE;
+#endif
+#if defined(WIN32)
+		if (g_rem_ptr->msg.cmd < MAX_IOVAR)
+			g_rem_ptr->msg.cmd += WL_OID_BASE;
+#endif
+		}
+#ifdef VISTA_SERVER
+		if (g_rem_ptr->msg.flags & REMOTE_VISTA_CMD) {
+			vista_buf[0] = strtok(buf_ptr, " \t\n");
+			for (index = 1; (vista_buf[index] = strtok(NULL, " \t\n")) != NULL;
+				index++);
+			if ((err = remote_vista_exec(wl, vista_buf)) < 0) {
+				DPRINT_ERR(ERR, "Error in executing vista command\n");
+			}
+			memcpy(buf_ptr, vista_buf[0], strlen(vista_buf[0]));
+			g_rem_ptr->msg.len = strlen(vista_buf[0]);
+		} /* REMOTE_VISTA_CMD */
+#endif /* VISTA_SERVER */
+
+#ifndef OLYMPIC_RWL
+#if defined(LINUX)
+#ifndef RWL_DONGLE
+		if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL ||
+			g_rem_ptr->msg.flags & REMOTE_SET_IOCTL) {
+			if (strlen(g_rem_ptr->intf_name) != 0) {
+				struct ifreq ifr;
+				/* validate the interface */
+				memset(&ifr, 0, sizeof(ifr));
+				if (g_rem_ptr->intf_name)
+					strncpy(ifr.ifr_name, g_rem_ptr->intf_name, IFNAMSIZ);
+
+				if (wl_check((void *)&ifr)) {
+					DPRINT_ERR(ERR, "%s: wl driver adapter not found\n",
+						g_rem_ptr->intf_name);
+					/* Signal end of command output */
+					g_rem_ptr->msg.len = 0;
+					remote_tx_response(wl, NULL, BCME_NODEVICE);
+					if (buf_ptr)
+						free(buf_ptr);
+#ifdef RWL_SOCKET
+					close_sock_handle(g_rwl_hndle);
+#endif
+					continue;
+				}
+
+				if (set_interface(wl, g_rem_ptr->intf_name) == BCME_OK)
+					DPRINT_DBG(OUTPUT, "\n %s Interface will be used \n",
+						(char *)wl);
+			}
+		}
+#endif /* ifndef RWL_DONGLE */
+#endif /* defined(LINUX) */
+#endif /* ifndef OLYMPIC_RWL */
+		if (g_rem_ptr->msg.flags & REMOTE_SET_IOCTL ||
+			g_rem_ptr->msg.flags & RDHD_SET_IOCTL) {
+#ifdef WIN32
+#if defined(RWL_DONGLE) || defined(RWL_WIFI)
+			/* For commands with msg length as zero initialize the buffer to null */
+			if (g_rem_ptr->msg.len == 0)
+				buf_ptr = NULL;
+#endif
+#else
+			if (g_rem_ptr->msg.len == 0)
+				buf_ptr = NULL;
+#endif /* WIN32 */
+
+#if defined(LINUX) || defined(TARGETOS_symbian) || defined(TARGETOS_nucleus)
+#ifdef OLYMPIC_RWL
+			set_interface(wl, old_intf_name);
+#endif
+			if (g_rem_ptr->msg.flags & REMOTE_SET_IOCTL) {
+				if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr &&
+				    !strncmp((const char *)buf_ptr,
+					     "init", g_rem_ptr->msg.len)) {
+					DPRINT_INFO(OUTPUT, "REC : init command\n");
+					err = 0;
+				} else if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr &&
+				   !strncmp((const char *)buf_ptr,
+					    "download", g_rem_ptr->msg.len)) {
+					DPRINT_INFO(OUTPUT, "REC : download command\n");
+					download_flag =  download_flag? 0: 1;
+					if (download_flag) {
+						DPRINT_INFO(OUTPUT, "download started\n");
+						if (!(fp = fopen(fn, "wb"))) {
+							DPRINT_ERR(ERR, "Failed to open file\n");
+							err = -2;
+						}
+					} else {
+						DPRINT_INFO(OUTPUT, "download completed\n");
+						if (fp != NULL) {
+							(void)fclose(fp);
+							fp = NULL;
+						}
+					}
+					err = 0;
+				} else if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr &&
+					!strncmp((const char *)buf_ptr,
+						"nvdownload", g_rem_ptr->msg.len)) {
+					DPRINT_INFO(OUTPUT, "REC : nvram download command\n");
+					download_flag =  download_flag? 0: 1;
+					if (download_flag) {
+						DPRINT_INFO(OUTPUT, "nvram download started\n");
+						if (!(fp = fopen(fw, "wb"))) {
+							DPRINT_ERR(ERR, "Failed to open file\n");
+							err = -2;
+						}
+					} else {
+						DPRINT_INFO(OUTPUT, "nvram download completed\n");
+						if (fp != NULL) {
+							(void)fclose(fp);
+							fp = NULL;
+						}
+					}
+					err = 0;
+				} else if (g_rem_ptr->msg.cmd == WLC_SET_VAR && buf_ptr &&
+				   !strncmp((const char *)buf_ptr,
+					    "membytes", g_rem_ptr->msg.len)) {
+					DPRINT_INFO(OUTPUT, "REC : membytes command\n");
+					skip = strlen("membytes ") + 8;
+					if (fp != NULL)
+						fwrite(buf_ptr + skip, 1,
+						       g_rem_ptr->msg.len - skip, fp);
+					else
+						DPRINT_ERR(ERR, "Download file has been closed.\n");
+					err = 0;
+				} else {
+					err = wl_ioctl(wl, g_rem_ptr->msg.cmd,
+					       (void *)buf_ptr, g_rem_ptr->msg.len, TRUE);
+					DPRINT_INFO(OUTPUT, "SEND : cmd %d\t msg len %d\n",
+					    g_rem_ptr->msg.cmd, g_rem_ptr->msg.len);
+					DPRINT_INFO(OUTPUT, "error code: %d\n", err);
+				}
+			}
+#if defined(LINUX)
+			if (err == BCME_IOCTL_ERROR) {
+				if (rwl_var_getbuf(wl, "bcmerrorstr", NULL, 0, (void**)&errstr)) {
+					DPRINT_ERR(ERR, "Error in executing wl_ioctl\r\n");
+				} else {
+					DPRINT_ERR(ERR, "%s\n", errstr);
+				}
+				DPRINT_ERR(ERR, "Setting Default Interface1 \n");
+				set_interface(wl, old_intf_name);
+			}
+
+			if (g_rem_ptr->msg.flags & RDHD_SET_IOCTL) {
+				err = dhd_ioctl(wl, g_rem_ptr->msg.cmd,
+				(void *)buf_ptr, g_rem_ptr->msg.len, TRUE);
+			}
+#endif /* LINUX */
+
+#elif WIN32
+			dwlen = g_rem_ptr->msg.len;
+			if (g_rem_ptr->msg.flags & RDHD_SET_IOCTL) {
+				g_rem_ptr->msg.cmd = g_rem_ptr->msg.cmd
+					- WL_OID_BASE + OID_DHD_IOCTLS;
+			}
+
+			err = (int)ir_setinformation(wl, g_rem_ptr->msg.cmd,
+			                       buf_ptr, &dwlen);
+#endif 
+			g_rem_ptr->msg.flags = REMOTE_SET_IOCTL;
+
+		} /* RDHD/REMOTE_SET_IOCTL */
+
+		if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL ||
+			g_rem_ptr->msg.flags & RDHD_GET_IOCTL) {
+#if defined(LINUX) || defined(TARGETOS_symbian) || defined(TARGETOS_nucleus)
+			if (g_rem_ptr->msg.cmd == WLC_GET_VAR && buf_ptr &&
+				strncmp((const char *)buf_ptr, "exit", g_rem_ptr->msg.len) == 0) {
+					/* exit command from remote client terminates server */
+					free(buf_ptr);
+					break;
+			}
+			if (g_rem_ptr->msg.flags & REMOTE_GET_IOCTL)
+				err = wl_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr,
+					g_rem_ptr->msg.len, FALSE);
+#ifdef PCIE_MFGTEST
+			if (err == CMD_ERR &&
+				g_rem_ptr->msg.cmd == WLC_GET_MAGIC &&
+				g_rem_ptr->msg.len == 4) {
+				err = 0;
+				DPRINT_ERR(ERR, "----command error \n");
+				buf_ptr[0] = WLC_IOCTL_MAGIC & 0xff; // 0x77
+				buf_ptr[1] = (WLC_IOCTL_MAGIC >> 8) & 0xff; // 0x6c
+				buf_ptr[2] = (WLC_IOCTL_MAGIC >> 16) & 0xff; // 0xe4;
+				buf_ptr[3] = (WLC_IOCTL_MAGIC >> 24) & 0xff; // 0x14;
+			}
+#endif /* PCIE_MFGTEST */
+#if defined(LINUX)
+			if (err == BCME_IOCTL_ERROR) {
+#ifdef PCIE_MFGTEST
+				if (g_rem_ptr->msg.cmd == WLC_GET_VERSION &&
+					g_rem_ptr->msg.len == 4) {
+					err = 0;
+					DPRINT_ERR(ERR, "---getversion \n");
+					buf_ptr[0] = WLC_IOCTL_VERSION & 0xff;
+					buf_ptr[1] = (WLC_IOCTL_VERSION >> 8) & 0xff;
+					buf_ptr[2] = (WLC_IOCTL_VERSION >> 16) & 0xff;
+					buf_ptr[3] = (WLC_IOCTL_VERSION >> 24) & 0xff;
+				}
+				else {
+					DPRINT_ERR(ERR, "REMOTE_GET_IOCTL::Error in executing"
+							" wl_ioctl\n");
+					DPRINT_ERR(ERR, "Setting Default Interface \n");
+					set_interface(wl, old_intf_name);
+				}
+#else
+				if (rwl_var_getbuf(wl, "bcmerrorstr", NULL, 0, (void**)&errstr)) {
+					DPRINT_ERR(ERR,
+						"REMOTE_GET_IOCTL::Error in executing wl_ioctl\n");
+				} else {
+					DPRINT_ERR(ERR, "%s\n", errstr);
+				}
+				DPRINT_ERR(ERR, "Setting Default Interface \n");
+				set_interface(wl, old_intf_name);
+#endif /* PCIE_MFGTEST */
+			}
+
+			if (g_rem_ptr->msg.flags & RDHD_GET_IOCTL)
+				err = dhd_ioctl(wl, g_rem_ptr->msg.cmd, (void *)buf_ptr,
+					g_rem_ptr->msg.len, FALSE);
+#endif /* LINUX */
+#elif WIN32
+			if (g_rem_ptr->msg.cmd == (WL_OID_BASE + WLC_GET_VAR) &&
+				strncmp(buf_ptr, "exit", g_rem_ptr->msg.len) == 0) {
+					/* exit command from remote client terminates server */
+					if (buf_ptr) {
+						free(buf_ptr);
+					}
+					break;
+			}
+
+			dwlen = g_rem_ptr->msg.len;
+			if (g_rem_ptr->msg.flags & RDHD_GET_IOCTL) {
+				g_rem_ptr->msg.cmd = g_rem_ptr->msg.cmd -
+					WL_OID_BASE + OID_DHD_IOCTLS;
+				}
+
+			err = (int)ir_queryinformation(wl,
+			g_rem_ptr->msg.cmd, buf_ptr, &dwlen);
+
+#endif /* defined(LINUX) || defined(TARGETOS_symbian) || defined(TARGETOS_nucleus) */
+			g_rem_ptr->msg.flags = REMOTE_GET_IOCTL;
+		} /* REMOTE_GET_IOCTL */
+		DPRINT_INFO(OUTPUT, "RESP : cmd %d\t msg len %d\n",
+		g_rem_ptr->msg.cmd, g_rem_ptr->msg.len);
+#if defined(LINUX)
+		/* setting back default interface  */
+		set_interface(wl, old_intf_name);
+#endif /*  defined(LINUX) */
+		/* Transmit the response results */
+		if (remote_tx_response(wl, buf_ptr, err) < 0) {
+			DPRINT_ERR(ERR, "\nReturn results failed\n");
+		}
+
+#ifdef RWL_SOCKET
+		if (g_rem_ptr->msg.flags != REMOTE_SHELL_CMD)
+		/* Transmitted to client. Then close the handle & get the new handle
+		 * for next transmission & reception. In case of shell commands this
+		 * should be closed in respective shellproc files.
+		 */
+		close_sock_handle(g_rwl_hndle);
+#endif /* RWL_SOCKET */
+
+		if (buf_ptr) {
+			free(buf_ptr);
+		}
+	} /* end of while */
+#if defined(RWL_SOCKET)
+	/* Close the main handle for socket */
+	close_sock_handle(transport_descriptor);
+#elif defined(RWL_SERIAL)
+	/* Close the main handle for serial pipe  */
+	rwl_close_pipe(remote_type, (void*)&transport_descriptor);
+#endif
+
+#ifdef RWLASD
+	wfa_dut_deinit();
+#endif
+
+	return err;
+}
diff --git a/wl/src/wl/exe/wlu_server_shared.h b/wl/src/wl/exe/wlu_server_shared.h
new file mode 100644
index 0000000..e697022
--- /dev/null
+++ b/wl/src/wl/exe/wlu_server_shared.h
@@ -0,0 +1,76 @@
+/*
+ * wl server declarations
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_server_shared.h 514727 2014-11-12 03:02:48Z $
+ */
+
+#ifndef _wlu_server_shared_h
+#define _wlu_server_shared_h
+
+#if defined(LINUX) || defined(SYMBIAN)
+	extern int wl_ioctl(void *wl, int cmd, void *buf, int len, bool set);
+#endif
+
+#if defined(LINUX)
+	extern int dhd_ioctl(void *dhd, int cmd, void *buf, int len, bool set);
+#endif
+
+#ifdef RWLASD
+/* streams' buffers */
+BYTE *xcCmdBuf = NULL, *parmsVal = NULL;
+BYTE *trafficBuf = NULL, *respBuf = NULL;
+struct timeval *toutvalp = NULL;
+#endif
+
+#define POLLING_TIME      			200
+#define DONGLE_TX_FRAME_SIZE   		1024
+#define MESSAGE_LENGTH				1024
+#define MAX_SHELL_FILE_LENGTH       50
+#define MAX_IOVAR				10000
+int remote_type = NO_REMOTE;
+rem_ioctl_t *g_rem_ptr;
+
+#if defined(LINUX) || defined(SYMBIAN) || defined(TARGETOS_nucleus)
+extern int wl_ioctl(void *wl, int cmd, void *buf, int len, bool set);
+#endif
+
+/* Function prototypes from shellpoc_linux.c/shell_ce.c */
+extern int rwl_create_dir(void);
+extern int remote_shell_execute(char *buf_ptr, void *wl);
+extern int remote_shell_get_resp(char* shell_fname, void *wl);
+extern void rwl_wifi_find_server_response(void *wl, dot11_action_wifi_vendor_specific_t *rec_frame);
+extern dot11_action_wifi_vendor_specific_t *rwl_wifi_allocate_actionframe(void);
+
+/* Common code for serial and wifi */
+#if defined(RWL_DONGLE) || defined(RWL_WIFI) || defined(RWL_SERIAL)
+typedef struct rem_packet {
+	rem_ioctl_t rem_cdc;
+	uchar message[MESSAGE_LENGTH];
+} rem_packet_t;
+#define REMOTE_PACKET_SIZE sizeof(rem_packet_t)
+
+rem_packet_t *g_rem_pkt_ptr;
+rem_packet_t g_rem_pkt;
+#endif
+
+static struct ether_addr rwlea;
+
+static union {
+	uchar bufdata[WLC_IOCTL_MAXLEN];
+	uint32 alignme;
+} bufstruct_wlu;
+static uchar* rwl_buf = (uchar*) &bufstruct_wlu.bufdata;
+extern int need_speedy_response;
+
+#endif /* _wlu_server_shared_h_ */
diff --git a/wl/src/wl/exe/wlu_subcounters.c b/wl/src/wl/exe/wlu_subcounters.c
new file mode 100644
index 0000000..62c8f88
--- /dev/null
+++ b/wl/src/wl/exe/wlu_subcounters.c
@@ -0,0 +1,2164 @@
+/*
+ * Availability support functions
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: $
+ */
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include <bcmutils.h>
+#include <wlioctl.h>
+#include <wlioctl_utils.h>
+#include "wlu_cmd.h"
+#include "wlu.h"
+
+#define CAT_TX    (1<<0) /**< counter is transmit related */
+#define CAT_RX    (1<<1) /**< counter is receive related */
+#define CAT_ERR   (1<<2) /**< counter signals a non optimal condition */
+#define CAT_UCAST (1<<3) /**< unicast specific counter */
+#define CAT_MCAST (1<<4) /**< multicast or broadcast specific counter */
+#define CAT_AMPDU (1<<5) /**< AMPDU specific counter */
+#define CAT_UCODE (1<<6) /**< Counter is generated by ucode (contained in SHM in d11 core) */
+#define CAT_CTRL  (1<<7) /**< Counters related to d11 control or mgmt frames */
+#define CAT_SEC   (1<<8) /**< Counters related to security/encryption */
+#define CAT_ASSOC (1<<9) /**< Counters related to authentication/association */
+
+#define PRINIT() prcnt_init()
+#define PRNL1()  prcnt_prnl1(p_cnt_filters)
+
+#define PRFMT1(name) #name " %u "  /* converts into the 'default' counters printf format string */
+
+/** prints one string without arguments */
+#define PRSTR(name, str)					\
+	if (prcnt_filter1(p_cnt_filters, #name)) {		\
+		printf("%s", str);				\
+		at_start_of_line = FALSE;			\
+	}
+
+/** prints one variable with dtoh32 conversion */
+#define PRVALV1(name)						\
+	if (prcnt_filter(p_cnt_filters, #name, cnt_v1->name)) {	\
+		printf(PRFMT1(name), dtoh32(cnt_v1->name));	\
+		at_start_of_line = FALSE;			\
+	}
+
+#define PRVAL(name)						\
+	if (prcnt_filter(p_cnt_filters, #name, cnt->name)) {	\
+		printf(PRFMT1(name), dtoh32(cnt->name));	\
+		at_start_of_line = FALSE;			\
+	}
+/** prints one variable with dtoh32 conversion */
+#define PRVAL_RENAME(name, prname)				\
+	if (prcnt_filter(p_cnt_filters, #name, cnt->name)) {	\
+		printf(PRFMT1(prname), dtoh32(cnt->name));	\
+		at_start_of_line = FALSE;			\
+	}
+
+/** Safe value print for only valid counter values, and when the counter is within len */
+#define PRVALSF(name) \
+	if ((dtoh32(cnt->name) != INVALID_CNT_VAL) &&		\
+	    (len > ((uint8 *)&cnt->name - (uint8 *)cnt)))	\
+	    PRVAL(name)
+
+/** prints one variable with dtoh32 conversion */
+#define PRVALSF_RENAME(varname, prname)				\
+	if (dtoh32(cnt->varname) != INVALID_CNT_VAL)		\
+		PRVAL_RENAME(varname, prname)
+
+/** prints one variable with dtoh32 conversion */
+#define PRVAL_FMTSTR1(varname, fmtstring, value)		\
+	if (prcnt_filter(p_cnt_filters, #varname, value)) {	\
+		printf(fmtstring, value);			\
+		at_start_of_line = FALSE;			\
+	}
+
+/** prints two variables, no dtoh32 conversion */
+#define PRVAL_FMTSTR2(varname, fmtstring, value1, value2)	\
+	if (prcnt_filter(p_cnt_filters, #varname, value2)) {	\
+		printf(fmtstring, value1, value2);		\
+		at_start_of_line = FALSE;			\
+	}
+
+/** prints one float variable without dtoh32 conversion */
+#define PRVAL_FMTSTR1F(varname, fmtstring, value1)	\
+	if (prcnt_filter(p_cnt_filters, #varname, value1 != 0.0 ? TRUE : FALSE)) {	\
+		printf(fmtstring, value1);						\
+		at_start_of_line = FALSE;						\
+	}
+
+#define PRCNT_MACSTAT_TX_VER_GE11						\
+do {										\
+	/* UCODE SHM counters */						\
+	/* tx start and those that do not end well */				\
+	PRVAL(txallfrm); PRVAL(txbcnfrm); PRVAL(txrtsfrm); PRVAL(txctsfrm);	\
+	PRVAL(txackfrm); PRVAL(txback); PRVAL(txdnlfrm); PRNL1();		\
+	PRVAL(txampdu); PRVAL(txmpdu); PRVAL(txucast);				\
+	PRVAL(rxrsptmout); PRVAL(txinrtstxop); PRVAL(txrtsfail); PRNL1();	\
+	PRVAL_FMTSTR1F(txper_ucastdt, "txper_ucastdt %.1f%% ",			\
+		cnt->txucast > 0 ?						\
+		(float)(1000 - ((cnt->rxackucast + cnt->rxback) * 1000		\
+		 / cnt->txucast))/10 : 0);					\
+	PRVAL_FMTSTR1F(txper_rts, "txper_rts %.1f%%",				\
+		cnt->txrtsfrm > 0 ?						\
+		(float)(1000 - (cnt->rxctsucast * 1000				\
+		/ cnt->txrtsfrm))/10 : 0);					\
+	PRNL1();								\
+	PRSTR(txfunfl, "txfunfl: ");						\
+	for (i = 0; i < NFIFO; i++) {						\
+		PRVAL_FMTSTR1(txfunfl, "%u ", cnt->txfunfl[i]);			\
+	}									\
+	PRVAL(txtplunfl); PRVAL(txphyerror); PRNL1(); PRNL1();			\
+} while (0)
+
+
+#define PRCNT_MACSTAT_RX_VER_GE11						\
+do {										\
+	/* rx with goodfcs */							\
+	PRVAL(rxctlucast); PRVAL(rxrtsucast); PRVAL(rxctsucast);		\
+	PRVAL(rxackucast); PRVAL(rxback); PRNL1();				\
+	PRVAL(rxbeaconmbss); PRVAL(rxdtucastmbss);				\
+	PRVAL(rxmgucastmbss); PRNL1();						\
+	PRVAL(rxbeaconobss); PRVAL(rxdtucastobss); PRVAL(rxdtocast);		\
+	PRVAL(rxmgocast); PRNL1();						\
+	PRVAL(rxctlocast); PRVAL(rxrtsocast); PRVAL(rxctsocast); PRNL1();	\
+	PRVAL(rxctlmcast); PRVAL(rxdtmcast); PRVAL(rxmgmcast); PRNL1(); PRNL1();	\
+										\
+	PRVAL(rxcgprqfrm); PRVAL(rxcgprsqovfl); PRVAL(txcgprsfail);		\
+	PRVAL(txcgprssuc); PRVAL(prs_timeout); PRNL1();				\
+	PRVAL(pktengrxducast); PRVAL(pktengrxdmcast);				\
+	PRVAL(bcntxcancl);							\
+} while (0)
+
+extern int wlu_var_getbuf_minimal(void *wl, const char *iovar, void *param, int param_len,
+		void **bufptr);
+
+/** specifies filters to apply when printing counters */
+struct cnt_filters_s {
+	bool nonzero;		/**< only print nonzero counter values */
+	bool filters_active;	/**< FALSE when user did not supply cmd line options */
+	bool invert_selection;	/**< inverts entire selection */
+	uint32 filter;  /**< only print counters falling into these categorie(s). Ignored if 0. */
+};
+
+typedef struct {
+	char **pbuf_ptr;
+	uint32 cntr_ver;
+	struct cnt_filters_s cnt_filters; /**< specifies filters to apply when printing counters */
+} wl_cnt_cbfn_info_t;
+
+typedef struct counter_offset_info {
+	const char	*name;		/* Name for the counter */
+	uint32		offset;		/* Offset of the counter in structure */
+} counter_offset_info_t;
+
+typedef struct ver_to_cntr_offset_info {
+	counter_offset_info_t	*offset_info_tbl;
+	uint32			cntr_ver;
+} ver_to_cntr_offset_info_t;
+
+/** specifies properties of each counter, so it can be optionally not printed on a criterium */
+struct cnt_properties_s {
+	char *name;
+	uint32 categories; /**< a bitmask, '1' means that counter is a member of that category */
+};
+
+static counter_offset_info_t cntr_offset_info_v6[] = {
+	{"txframe",		OFFSETOF(wl_cnt_ver_6_t, txframe)},
+	{"txbyte",		OFFSETOF(wl_cnt_ver_6_t, txbyte)},
+	{"txretrans",		OFFSETOF(wl_cnt_ver_6_t, txretrans)},
+	{"txerror",		OFFSETOF(wl_cnt_ver_6_t, txerror)},
+	{"txctl",		OFFSETOF(wl_cnt_ver_6_t, txctl)},
+	{"txprshort",		OFFSETOF(wl_cnt_ver_6_t, txprshort)},
+	{"txserr",		OFFSETOF(wl_cnt_ver_6_t, txserr)},
+	{"txnobuf",		OFFSETOF(wl_cnt_ver_6_t, txnobuf)},
+	{"txnoassoc",		OFFSETOF(wl_cnt_ver_6_t, txnoassoc)},
+	{"txrunt",		OFFSETOF(wl_cnt_ver_6_t, txrunt)},
+	{"txchit",		OFFSETOF(wl_cnt_ver_6_t, txchit)},
+	{"txcmiss",		OFFSETOF(wl_cnt_ver_6_t, txcmiss)},
+	{"txuflo",		OFFSETOF(wl_cnt_ver_6_t, txuflo)},
+	{"txphyerr",		OFFSETOF(wl_cnt_ver_6_t, txphyerr)},
+	{"txphycrs",		OFFSETOF(wl_cnt_ver_6_t, txphycrs)},
+	{"rxframe",		OFFSETOF(wl_cnt_ver_6_t, rxframe)},
+	{"rxbyte",		OFFSETOF(wl_cnt_ver_6_t, rxbyte)},
+	{"rxerror",		OFFSETOF(wl_cnt_ver_6_t, rxerror)},
+	{"rxctl",		OFFSETOF(wl_cnt_ver_6_t, rxctl)},
+	{"rxnobuf",		OFFSETOF(wl_cnt_ver_6_t, rxnobuf)},
+	{"rxnondata",		OFFSETOF(wl_cnt_ver_6_t, rxnondata)},
+	{"rxbadds",		OFFSETOF(wl_cnt_ver_6_t, rxbadds)},
+	{"rxbadcm",		OFFSETOF(wl_cnt_ver_6_t, rxbadcm)},
+	{"rxfragerr",		OFFSETOF(wl_cnt_ver_6_t, rxfragerr)},
+	{"rxrunt",		OFFSETOF(wl_cnt_ver_6_t, rxrunt)},
+	{"rxgiant",		OFFSETOF(wl_cnt_ver_6_t, rxgiant)},
+	{"rxnoscb",		OFFSETOF(wl_cnt_ver_6_t, rxnoscb)},
+	{"rxbadproto",		OFFSETOF(wl_cnt_ver_6_t, rxbadproto)},
+	{"rxbadsrcmac",		OFFSETOF(wl_cnt_ver_6_t, rxbadsrcmac)},
+	{"rxbadda",		OFFSETOF(wl_cnt_ver_6_t, rxbadda)},
+	{"rxfilter",		OFFSETOF(wl_cnt_ver_6_t, rxfilter)},
+	{"rxoflo",		OFFSETOF(wl_cnt_ver_6_t, rxoflo)},
+	{"rxuflo[0]",		OFFSETOF(wl_cnt_ver_6_t, rxuflo[0])},
+	{"rxuflo[1]",		OFFSETOF(wl_cnt_ver_6_t, rxuflo[1])},
+	{"rxuflo[2]",		OFFSETOF(wl_cnt_ver_6_t, rxuflo[2])},
+	{"rxuflo[3]",		OFFSETOF(wl_cnt_ver_6_t, rxuflo[3])},
+	{"rxuflo[4]",		OFFSETOF(wl_cnt_ver_6_t, rxuflo[4])},
+	{"rxuflo[5]",		OFFSETOF(wl_cnt_ver_6_t, rxuflo[5])},
+	{"d11cnt_txrts_off",	OFFSETOF(wl_cnt_ver_6_t, d11cnt_txrts_off)},
+	{"d11cnt_rxcrc_off",	OFFSETOF(wl_cnt_ver_6_t, d11cnt_rxcrc_off)},
+	{"d11cnt_txnocts_off",	OFFSETOF(wl_cnt_ver_6_t, d11cnt_txnocts_off)},
+	{"dmade",		OFFSETOF(wl_cnt_ver_6_t, dmade)},
+	{"dmada",		OFFSETOF(wl_cnt_ver_6_t, dmada)},
+	{"dmape",		OFFSETOF(wl_cnt_ver_6_t, dmape)},
+	{"reset",		OFFSETOF(wl_cnt_ver_6_t, reset)},
+	{"tbtt",		OFFSETOF(wl_cnt_ver_6_t, tbtt)},
+	{"txdmawar",		OFFSETOF(wl_cnt_ver_6_t, txdmawar)},
+	{"pkt_callback_reg_fail", OFFSETOF(wl_cnt_ver_6_t, pkt_callback_reg_fail)},
+	{"d11_txfrag",		OFFSETOF(wl_cnt_ver_6_t, txfrag)},
+	{"d11_txmulti",		OFFSETOF(wl_cnt_ver_6_t, txmulti)},
+	{"txfail",		OFFSETOF(wl_cnt_ver_6_t, txfail)},
+	{"d11_txretry",		OFFSETOF(wl_cnt_ver_6_t, txretry)},
+	{"d11_txretrie",	OFFSETOF(wl_cnt_ver_6_t, txretrie)},
+	{"rxdup",		OFFSETOF(wl_cnt_ver_6_t, rxdup)},
+	{"d11_txrts",		OFFSETOF(wl_cnt_ver_6_t, txrts)},
+	{"d11_txnocts",		OFFSETOF(wl_cnt_ver_6_t, txnocts)},
+	{"d11_txnoack",		OFFSETOF(wl_cnt_ver_6_t, txnoack)},
+	{"d11_rxfrag",		OFFSETOF(wl_cnt_ver_6_t, rxfrag)},
+	{"d11_rxmulti",		OFFSETOF(wl_cnt_ver_6_t, rxmulti)},
+	{"rxcrc",		OFFSETOF(wl_cnt_ver_6_t, rxcrc)},
+	{"d11_txfrmsnt",	OFFSETOF(wl_cnt_ver_6_t, txfrmsnt)},
+	{"d11_rxundec",		OFFSETOF(wl_cnt_ver_6_t, rxundec)},
+	{"tkipmicfaill",	OFFSETOF(wl_cnt_ver_6_t, tkipmicfaill)},
+	{"tkipcntrmsr",		OFFSETOF(wl_cnt_ver_6_t, tkipcntrmsr)},
+	{"tkipreplay",		OFFSETOF(wl_cnt_ver_6_t, tkipreplay)},
+	{"ccmpfmterr",		OFFSETOF(wl_cnt_ver_6_t, ccmpfmterr)},
+	{"ccmpreplay",		OFFSETOF(wl_cnt_ver_6_t, ccmpreplay)},
+	{"ccmpundec",		OFFSETOF(wl_cnt_ver_6_t, ccmpundec)},
+	{"fourwayfail",		OFFSETOF(wl_cnt_ver_6_t, fourwayfail)},
+	{"wepundec",		OFFSETOF(wl_cnt_ver_6_t, wepundec)},
+	{"wepicverr",		OFFSETOF(wl_cnt_ver_6_t, wepicverr)},
+	{"decsuccess",		OFFSETOF(wl_cnt_ver_6_t, decsuccess)},
+	{"tkipicverr",		OFFSETOF(wl_cnt_ver_6_t, tkipicverr)},
+	{"wepexcluded",		OFFSETOF(wl_cnt_ver_6_t, wepexcluded)},
+	{"txchanrej",		OFFSETOF(wl_cnt_ver_6_t, txchanrej)},
+	{"psmwds",		OFFSETOF(wl_cnt_ver_6_t, psmwds)},
+	{"phywatchdog",		OFFSETOF(wl_cnt_ver_6_t, phywatchdog)},
+	{"prq_entries_handled",	OFFSETOF(wl_cnt_ver_6_t, prq_entries_handled)},
+	{"prq_undirected_entries", OFFSETOF(wl_cnt_ver_6_t, prq_undirected_entries)},
+	{"prq_bad_entries",	OFFSETOF(wl_cnt_ver_6_t, prq_bad_entries)},
+	{"atim_suppress_count",	OFFSETOF(wl_cnt_ver_6_t, atim_suppress_count)},
+	{"bcn_template_not_ready", OFFSETOF(wl_cnt_ver_6_t, bcn_template_not_ready)},
+	{"bcn_template_not_ready_done",	OFFSETOF(wl_cnt_ver_6_t, bcn_template_not_ready_done)},
+	{"late_tbtt_dpc",	OFFSETOF(wl_cnt_ver_6_t, late_tbtt_dpc)},
+	{"rx1mbps",		OFFSETOF(wl_cnt_ver_6_t, rx1mbps)},
+	{"rx2mbps",		OFFSETOF(wl_cnt_ver_6_t, rx2mbps)},
+	{"rx5mbps5",		OFFSETOF(wl_cnt_ver_6_t, rx5mbps5)},
+	{"rx6mbps",		OFFSETOF(wl_cnt_ver_6_t, rx6mbps)},
+	{"rx9mbps",		OFFSETOF(wl_cnt_ver_6_t, rx9mbps)},
+	{"rx11mbps",		OFFSETOF(wl_cnt_ver_6_t, rx11mbps)},
+	{"rx12mbps",		OFFSETOF(wl_cnt_ver_6_t, rx12mbps)},
+	{"rx18mbps",		OFFSETOF(wl_cnt_ver_6_t, rx18mbps)},
+	{"rx24mbps",		OFFSETOF(wl_cnt_ver_6_t, rx24mbps)},
+	{"rx36mbps",		OFFSETOF(wl_cnt_ver_6_t, rx36mbps)},
+	{"rx48mbps",		OFFSETOF(wl_cnt_ver_6_t, rx48mbps)},
+	{"rx54mbps",		OFFSETOF(wl_cnt_ver_6_t, rx54mbps)},
+	{"rx108mbps",		OFFSETOF(wl_cnt_ver_6_t, rx108mbps)},
+	{"rx162mbps",		OFFSETOF(wl_cnt_ver_6_t, rx162mbps)},
+	{"rx216mbps",		OFFSETOF(wl_cnt_ver_6_t, rx216mbps)},
+	{"rx270mbps",		OFFSETOF(wl_cnt_ver_6_t, rx270mbps)},
+	{"rx324mbps",		OFFSETOF(wl_cnt_ver_6_t, rx324mbps)},
+	{"rx378mbps",		OFFSETOF(wl_cnt_ver_6_t, rx378mbps)},
+	{"rx432mbps",		OFFSETOF(wl_cnt_ver_6_t, rx432mbps)},
+	{"rx486mbps",		OFFSETOF(wl_cnt_ver_6_t, rx486mbps)},
+	{"rx540mbps",		OFFSETOF(wl_cnt_ver_6_t, rx540mbps)},
+	{"rfdisable",		OFFSETOF(wl_cnt_ver_6_t, rfdisable)},
+	{"txexptime",		OFFSETOF(wl_cnt_ver_6_t, txexptime)},
+	{"txmpdu_sgi",		OFFSETOF(wl_cnt_ver_6_t, txmpdu_sgi)},
+	{"rxmpdu_sgi",		OFFSETOF(wl_cnt_ver_6_t, rxmpdu_sgi)},
+	{"txmpdu_stbc",		OFFSETOF(wl_cnt_ver_6_t, txmpdu_stbc)},
+	{"rxmpdu_stbc",		OFFSETOF(wl_cnt_ver_6_t, rxmpdu_stbc)},
+	{"rxundec_mcst",	OFFSETOF(wl_cnt_ver_6_t, rxundec_mcst)},
+	{"tkipmicfaill_mcst",	OFFSETOF(wl_cnt_ver_6_t, tkipmicfaill_mcst)},
+	{"tkipcntrmsr_mcst",	OFFSETOF(wl_cnt_ver_6_t, tkipcntrmsr_mcst)},
+	{"tkipreplay_mcst",	OFFSETOF(wl_cnt_ver_6_t, tkipreplay_mcst)},
+	{"ccmpfmterr_mcst",	OFFSETOF(wl_cnt_ver_6_t, ccmpfmterr_mcst)},
+	{"ccmpreplay_mcst",	OFFSETOF(wl_cnt_ver_6_t, ccmpreplay_mcst)},
+	{"ccmpundec_mcst",	OFFSETOF(wl_cnt_ver_6_t, ccmpundec_mcst)},
+	{"fourwayfail_mcst",	OFFSETOF(wl_cnt_ver_6_t, fourwayfail_mcst)},
+	{"wepundec_mcst",	OFFSETOF(wl_cnt_ver_6_t, wepundec_mcst)},
+	{"wepicverr_mcst",	OFFSETOF(wl_cnt_ver_6_t, wepicverr_mcst)},
+	{"decsuccess_mcst",	OFFSETOF(wl_cnt_ver_6_t, decsuccess_mcst)},
+	{"tkipicverr_mcst",	OFFSETOF(wl_cnt_ver_6_t, tkipicverr_mcst)},
+	{"wepexcluded_mcst",	OFFSETOF(wl_cnt_ver_6_t, wepexcluded_mcst)},
+	/* macstat counters */
+	{"txallfrm",		OFFSETOF(wl_cnt_ver_6_t, txallfrm)},
+	{"txrtsfrm",		OFFSETOF(wl_cnt_ver_6_t, txrtsfrm)},
+	{"txctsfrm",		OFFSETOF(wl_cnt_ver_6_t, txctsfrm)},
+	{"txackfrm",		OFFSETOF(wl_cnt_ver_6_t, txackfrm)},
+	{"txdnlfrm",		OFFSETOF(wl_cnt_ver_6_t, txdnlfrm)},
+	{"txbcnfrm",		OFFSETOF(wl_cnt_ver_6_t, txbcnfrm)},
+	{"txfunfl[0]",		OFFSETOF(wl_cnt_ver_6_t, txfunfl[0])},
+	{"txfunfl[1]",		OFFSETOF(wl_cnt_ver_6_t, txfunfl[1])},
+	{"txfunfl[2]",		OFFSETOF(wl_cnt_ver_6_t, txfunfl[2])},
+	{"txfunfl[3]",		OFFSETOF(wl_cnt_ver_6_t, txfunfl[3])},
+	{"txfunfl[4]",		OFFSETOF(wl_cnt_ver_6_t, txfunfl[4])},
+	{"txfunfl[5]",		OFFSETOF(wl_cnt_ver_6_t, txfunfl[5])},
+	{"txampdu",		OFFSETOF(wl_cnt_ver_6_t, txfbw)},
+	{"txtplunfl",		OFFSETOF(wl_cnt_ver_6_t, txtplunfl)},
+	{"txphyerror",		OFFSETOF(wl_cnt_ver_6_t, txphyerror)},
+	{"pktengrxducast",	OFFSETOF(wl_cnt_ver_6_t, pktengrxducast)},
+	{"pktengrxdmcast",	OFFSETOF(wl_cnt_ver_6_t, pktengrxdmcast)},
+	{"rxfrmtoolong",	OFFSETOF(wl_cnt_ver_6_t, rxfrmtoolong)},
+	{"rxfrmtooshrt",	OFFSETOF(wl_cnt_ver_6_t, rxfrmtooshrt)},
+	{"rxanyerr",		OFFSETOF(wl_cnt_ver_6_t, rxinvmachdr)},
+	{"rxbadfcs",		OFFSETOF(wl_cnt_ver_6_t, rxbadfcs)},
+	{"rxbadplcp",		OFFSETOF(wl_cnt_ver_6_t, rxbadplcp)},
+	{"rxcrsglitch",		OFFSETOF(wl_cnt_ver_6_t, rxcrsglitch)},
+	{"rxstrt",		OFFSETOF(wl_cnt_ver_6_t, rxstrt)},
+	{"rxdtucastmbss",	OFFSETOF(wl_cnt_ver_6_t, rxdfrmucastmbss)},
+	{"rxmgucastmbss",	OFFSETOF(wl_cnt_ver_6_t, rxmfrmucastmbss)},
+	{"rxctlucast",		OFFSETOF(wl_cnt_ver_6_t, rxcfrmucast)},
+	{"rxrtsucast",		OFFSETOF(wl_cnt_ver_6_t, rxrtsucast)},
+	{"rxctsucast",		OFFSETOF(wl_cnt_ver_6_t, rxctsucast)},
+	{"rxackucast",		OFFSETOF(wl_cnt_ver_6_t, rxackucast)},
+	{"rxdtocast",		OFFSETOF(wl_cnt_ver_6_t, rxdfrmocast)},
+	{"rxmgocast",		OFFSETOF(wl_cnt_ver_6_t, rxmfrmocast)},
+	{"rxctlocast",		OFFSETOF(wl_cnt_ver_6_t, rxcfrmocast)},
+	{"rxrtsocast",		OFFSETOF(wl_cnt_ver_6_t, rxrtsocast)},
+	{"rxctsocast",		OFFSETOF(wl_cnt_ver_6_t, rxctsocast)},
+	{"rxdtmcast",		OFFSETOF(wl_cnt_ver_6_t, rxdfrmmcast)},
+	{"rxmgmcast",		OFFSETOF(wl_cnt_ver_6_t, rxmfrmmcast)},
+	{"rxctlmcast",		OFFSETOF(wl_cnt_ver_6_t, rxcfrmmcast)},
+	{"rxbeaconmbss",	OFFSETOF(wl_cnt_ver_6_t, rxbeaconmbss)},
+	{"rxdtucastobss",	OFFSETOF(wl_cnt_ver_6_t, rxdfrmucastobss)},
+	{"rxbeaconobss",	OFFSETOF(wl_cnt_ver_6_t, rxbeaconobss)},
+	{"rxrsptmout",		OFFSETOF(wl_cnt_ver_6_t, rxrsptmout)},
+	{"bcntxcancl",		OFFSETOF(wl_cnt_ver_6_t, bcntxcancl)},
+	{"rxf0ovfl",		OFFSETOF(wl_cnt_ver_6_t, rxf0ovfl)},
+	{"rxf1ovfl",		OFFSETOF(wl_cnt_ver_6_t, rxf1ovfl)},
+	{"rxhlovfl",		OFFSETOF(wl_cnt_ver_6_t, rxf2ovfl)},
+	{"missbcn_dbg",		OFFSETOF(wl_cnt_ver_6_t, txsfovfl)},
+	{"pmqovfl",		OFFSETOF(wl_cnt_ver_6_t, pmqovfl)},
+	{"rxcgprqfrm",		OFFSETOF(wl_cnt_ver_6_t, rxcgprqfrm)},
+	{"rxcgprsqovfl",	OFFSETOF(wl_cnt_ver_6_t, rxcgprsqovfl)},
+	{"txcgprsfail",		OFFSETOF(wl_cnt_ver_6_t, txcgprsfail)},
+	{"txcgprssuc",		OFFSETOF(wl_cnt_ver_6_t, txcgprssuc)},
+	{"prs_timeout",		OFFSETOF(wl_cnt_ver_6_t, prs_timeout)},
+	{"txrtsfail",		OFFSETOF(wl_cnt_ver_6_t, rxnack)},
+	{"txucast",		OFFSETOF(wl_cnt_ver_6_t, frmscons)},
+	{"txinrtstxop",		OFFSETOF(wl_cnt_ver_6_t, txnack)},
+	{"rxback",		OFFSETOF(wl_cnt_ver_6_t, rxback)},
+	{"txback",		OFFSETOF(wl_cnt_ver_6_t, txback)},
+	{"bphy_rxcrsglitch",	OFFSETOF(wl_cnt_ver_6_t, bphy_rxcrsglitch)},
+	{"rxdrop20s",		OFFSETOF(wl_cnt_ver_6_t, rxdrop20s)},
+	{"rxtoolate",		OFFSETOF(wl_cnt_ver_6_t, rxtoolate)},
+	{"bphy_badplcp",	OFFSETOF(wl_cnt_ver_6_t, bphy_badplcp)},
+	{NULL, 0},
+};
+
+static counter_offset_info_t cntr_offset_info_v7[] = {
+	{"txframe",		OFFSETOF(wl_cnt_ver_7_t, txframe)},
+	{"txbyte",		OFFSETOF(wl_cnt_ver_7_t, txbyte)},
+	{"txretrans",		OFFSETOF(wl_cnt_ver_7_t, txretrans)},
+	{"txerror",		OFFSETOF(wl_cnt_ver_7_t, txerror)},
+	{"txctl",		OFFSETOF(wl_cnt_ver_7_t, txctl)},
+	{"txprshort",		OFFSETOF(wl_cnt_ver_7_t, txprshort)},
+	{"txserr",		OFFSETOF(wl_cnt_ver_7_t, txserr)},
+	{"txnobuf",		OFFSETOF(wl_cnt_ver_7_t, txnobuf)},
+	{"txnoassoc",		OFFSETOF(wl_cnt_ver_7_t, txnoassoc)},
+	{"txrunt",		OFFSETOF(wl_cnt_ver_7_t, txrunt)},
+	{"txchit",		OFFSETOF(wl_cnt_ver_7_t, txchit)},
+	{"txcmiss",		OFFSETOF(wl_cnt_ver_7_t, txcmiss)},
+	{"txuflo",		OFFSETOF(wl_cnt_ver_7_t, txuflo)},
+	{"txphyerr",		OFFSETOF(wl_cnt_ver_7_t, txphyerr)},
+	{"txphycrs",		OFFSETOF(wl_cnt_ver_7_t, txphycrs)},
+	{"rxframe",		OFFSETOF(wl_cnt_ver_7_t, rxframe)},
+	{"rxbyte",		OFFSETOF(wl_cnt_ver_7_t, rxbyte)},
+	{"rxerror",		OFFSETOF(wl_cnt_ver_7_t, rxerror)},
+	{"rxctl",		OFFSETOF(wl_cnt_ver_7_t, rxctl)},
+	{"rxnobuf",		OFFSETOF(wl_cnt_ver_7_t, rxnobuf)},
+	{"rxnondata",		OFFSETOF(wl_cnt_ver_7_t, rxnondata)},
+	{"rxbadds",		OFFSETOF(wl_cnt_ver_7_t, rxbadds)},
+	{"rxbadcm",		OFFSETOF(wl_cnt_ver_7_t, rxbadcm)},
+	{"rxfragerr",		OFFSETOF(wl_cnt_ver_7_t, rxfragerr)},
+	{"rxrunt",		OFFSETOF(wl_cnt_ver_7_t, rxrunt)},
+	{"rxgiant",		OFFSETOF(wl_cnt_ver_7_t, rxgiant)},
+	{"rxnoscb",		OFFSETOF(wl_cnt_ver_7_t, rxnoscb)},
+	{"rxbadproto",		OFFSETOF(wl_cnt_ver_7_t, rxbadproto)},
+	{"rxbadsrcmac",		OFFSETOF(wl_cnt_ver_7_t, rxbadsrcmac)},
+	{"rxbadda",		OFFSETOF(wl_cnt_ver_7_t, rxbadda)},
+	{"rxfilter",		OFFSETOF(wl_cnt_ver_7_t, rxfilter)},
+	{"rxoflo",		OFFSETOF(wl_cnt_ver_7_t, rxoflo)},
+	{"rxuflo[0]",		OFFSETOF(wl_cnt_ver_7_t, rxuflo[0])},
+	{"rxuflo[1]",		OFFSETOF(wl_cnt_ver_7_t, rxuflo[1])},
+	{"rxuflo[2]",		OFFSETOF(wl_cnt_ver_7_t, rxuflo[2])},
+	{"rxuflo[3]",		OFFSETOF(wl_cnt_ver_7_t, rxuflo[3])},
+	{"rxuflo[4]",		OFFSETOF(wl_cnt_ver_7_t, rxuflo[4])},
+	{"rxuflo[5]",		OFFSETOF(wl_cnt_ver_7_t, rxuflo[5])},
+	{"d11cnt_txrts_off",	OFFSETOF(wl_cnt_ver_7_t, d11cnt_txrts_off)},
+	{"d11cnt_rxcrc_off",	OFFSETOF(wl_cnt_ver_7_t, d11cnt_rxcrc_off)},
+	{"d11cnt_txnocts_off",	OFFSETOF(wl_cnt_ver_7_t, d11cnt_txnocts_off)},
+	{"dmade",		OFFSETOF(wl_cnt_ver_7_t, dmade)},
+	{"dmada",		OFFSETOF(wl_cnt_ver_7_t, dmada)},
+	{"dmape",		OFFSETOF(wl_cnt_ver_7_t, dmape)},
+	{"reset",		OFFSETOF(wl_cnt_ver_7_t, reset)},
+	{"tbtt",		OFFSETOF(wl_cnt_ver_7_t, tbtt)},
+	{"txdmawar",		OFFSETOF(wl_cnt_ver_7_t, txdmawar)},
+	{"pkt_callback_reg_fail", OFFSETOF(wl_cnt_ver_7_t, pkt_callback_reg_fail)},
+	{"d11_txfrag",		OFFSETOF(wl_cnt_ver_7_t, txfrag)},
+	{"d11_txmulti",		OFFSETOF(wl_cnt_ver_7_t, txmulti)},
+	{"txfail",		OFFSETOF(wl_cnt_ver_7_t, txfail)},
+	{"d11_txretry",		OFFSETOF(wl_cnt_ver_7_t, txretry)},
+	{"d11_txretrie",	OFFSETOF(wl_cnt_ver_7_t, txretrie)},
+	{"rxdup",		OFFSETOF(wl_cnt_ver_7_t, rxdup)},
+	{"d11_txrts",		OFFSETOF(wl_cnt_ver_7_t, txrts)},
+	{"d11_txnocts",		OFFSETOF(wl_cnt_ver_7_t, txnocts)},
+	{"d11_txnoack",		OFFSETOF(wl_cnt_ver_7_t, txnoack)},
+	{"d11_rxfrag",		OFFSETOF(wl_cnt_ver_7_t, rxfrag)},
+	{"d11_rxmulti",		OFFSETOF(wl_cnt_ver_7_t, rxmulti)},
+	{"rxcrc",		OFFSETOF(wl_cnt_ver_7_t, rxcrc)},
+	{"d11_txfrmsnt",	OFFSETOF(wl_cnt_ver_7_t, txfrmsnt)},
+	{"d11_rxundec",		OFFSETOF(wl_cnt_ver_7_t, rxundec)},
+	{"tkipmicfaill",	OFFSETOF(wl_cnt_ver_7_t, tkipmicfaill)},
+	{"tkipcntrmsr",		OFFSETOF(wl_cnt_ver_7_t, tkipcntrmsr)},
+	{"tkipreplay",		OFFSETOF(wl_cnt_ver_7_t, tkipreplay)},
+	{"ccmpfmterr",		OFFSETOF(wl_cnt_ver_7_t, ccmpfmterr)},
+	{"ccmpreplay",		OFFSETOF(wl_cnt_ver_7_t, ccmpreplay)},
+	{"ccmpundec",		OFFSETOF(wl_cnt_ver_7_t, ccmpundec)},
+	{"fourwayfail",		OFFSETOF(wl_cnt_ver_7_t, fourwayfail)},
+	{"wepundec",		OFFSETOF(wl_cnt_ver_7_t, wepundec)},
+	{"wepicverr",		OFFSETOF(wl_cnt_ver_7_t, wepicverr)},
+	{"decsuccess",		OFFSETOF(wl_cnt_ver_7_t, decsuccess)},
+	{"tkipicverr",		OFFSETOF(wl_cnt_ver_7_t, tkipicverr)},
+	{"wepexcluded",		OFFSETOF(wl_cnt_ver_7_t, wepexcluded)},
+	{"txchanrej",		OFFSETOF(wl_cnt_ver_7_t, txchanrej)},
+	{"psmwds",		OFFSETOF(wl_cnt_ver_7_t, psmwds)},
+	{"phywatchdog",		OFFSETOF(wl_cnt_ver_7_t, phywatchdog)},
+	{"prq_entries_handled",	OFFSETOF(wl_cnt_ver_7_t, prq_entries_handled)},
+	{"prq_undirected_entries", OFFSETOF(wl_cnt_ver_7_t, prq_undirected_entries)},
+	{"prq_bad_entries",	OFFSETOF(wl_cnt_ver_7_t, prq_bad_entries)},
+	{"atim_suppress_count",	OFFSETOF(wl_cnt_ver_7_t, atim_suppress_count)},
+	{"bcn_template_not_ready", OFFSETOF(wl_cnt_ver_7_t, bcn_template_not_ready)},
+	{"bcn_template_not_ready_done",	OFFSETOF(wl_cnt_ver_7_t, bcn_template_not_ready_done)},
+	{"late_tbtt_dpc",	OFFSETOF(wl_cnt_ver_7_t, late_tbtt_dpc)},
+	{"rx1mbps",		OFFSETOF(wl_cnt_ver_7_t, rx1mbps)},
+	{"rx2mbps",		OFFSETOF(wl_cnt_ver_7_t, rx2mbps)},
+	{"rx5mbps5",		OFFSETOF(wl_cnt_ver_7_t, rx5mbps5)},
+	{"rx6mbps",		OFFSETOF(wl_cnt_ver_7_t, rx6mbps)},
+	{"rx9mbps",		OFFSETOF(wl_cnt_ver_7_t, rx9mbps)},
+	{"rx11mbps",		OFFSETOF(wl_cnt_ver_7_t, rx11mbps)},
+	{"rx12mbps",		OFFSETOF(wl_cnt_ver_7_t, rx12mbps)},
+	{"rx18mbps",		OFFSETOF(wl_cnt_ver_7_t, rx18mbps)},
+	{"rx24mbps",		OFFSETOF(wl_cnt_ver_7_t, rx24mbps)},
+	{"rx36mbps",		OFFSETOF(wl_cnt_ver_7_t, rx36mbps)},
+	{"rx48mbps",		OFFSETOF(wl_cnt_ver_7_t, rx48mbps)},
+	{"rx54mbps",		OFFSETOF(wl_cnt_ver_7_t, rx54mbps)},
+	{"rx108mbps",		OFFSETOF(wl_cnt_ver_7_t, rx108mbps)},
+	{"rx162mbps",		OFFSETOF(wl_cnt_ver_7_t, rx162mbps)},
+	{"rx216mbps",		OFFSETOF(wl_cnt_ver_7_t, rx216mbps)},
+	{"rx270mbps",		OFFSETOF(wl_cnt_ver_7_t, rx270mbps)},
+	{"rx324mbps",		OFFSETOF(wl_cnt_ver_7_t, rx324mbps)},
+	{"rx378mbps",		OFFSETOF(wl_cnt_ver_7_t, rx378mbps)},
+	{"rx432mbps",		OFFSETOF(wl_cnt_ver_7_t, rx432mbps)},
+	{"rx486mbps",		OFFSETOF(wl_cnt_ver_7_t, rx486mbps)},
+	{"rx540mbps",		OFFSETOF(wl_cnt_ver_7_t, rx540mbps)},
+	{"rfdisable",		OFFSETOF(wl_cnt_ver_7_t, rfdisable)},
+	{"txexptime",		OFFSETOF(wl_cnt_ver_7_t, txexptime)},
+	{"txmpdu_sgi",		OFFSETOF(wl_cnt_ver_7_t, txmpdu_sgi)},
+	{"rxmpdu_sgi",		OFFSETOF(wl_cnt_ver_7_t, rxmpdu_sgi)},
+	{"txmpdu_stbc",		OFFSETOF(wl_cnt_ver_7_t, txmpdu_stbc)},
+	{"rxmpdu_stbc",		OFFSETOF(wl_cnt_ver_7_t, rxmpdu_stbc)},
+	{"rxundec_mcst",	OFFSETOF(wl_cnt_ver_7_t, rxundec_mcst)},
+	{"tkipmicfaill_mcst",	OFFSETOF(wl_cnt_ver_7_t, tkipmicfaill_mcst)},
+	{"tkipcntrmsr_mcst",	OFFSETOF(wl_cnt_ver_7_t, tkipcntrmsr_mcst)},
+	{"tkipreplay_mcst",	OFFSETOF(wl_cnt_ver_7_t, tkipreplay_mcst)},
+	{"ccmpfmterr_mcst",	OFFSETOF(wl_cnt_ver_7_t, ccmpfmterr_mcst)},
+	{"ccmpreplay_mcst",	OFFSETOF(wl_cnt_ver_7_t, ccmpreplay_mcst)},
+	{"ccmpundec_mcst",	OFFSETOF(wl_cnt_ver_7_t, ccmpundec_mcst)},
+	{"fourwayfail_mcst",	OFFSETOF(wl_cnt_ver_7_t, fourwayfail_mcst)},
+	{"wepundec_mcst",	OFFSETOF(wl_cnt_ver_7_t, wepundec_mcst)},
+	{"wepicverr_mcst",	OFFSETOF(wl_cnt_ver_7_t, wepicverr_mcst)},
+	{"decsuccess_mcst",	OFFSETOF(wl_cnt_ver_7_t, decsuccess_mcst)},
+	{"tkipicverr_mcst",	OFFSETOF(wl_cnt_ver_7_t, tkipicverr_mcst)},
+	{"wepexcluded_mcst",	OFFSETOF(wl_cnt_ver_7_t, wepexcluded_mcst)},
+	/* macstat counters */
+	{"txallfrm",		OFFSETOF(wl_cnt_ver_7_t, txallfrm)},
+	{"txrtsfrm",		OFFSETOF(wl_cnt_ver_7_t, txrtsfrm)},
+	{"txctsfrm",		OFFSETOF(wl_cnt_ver_7_t, txctsfrm)},
+	{"txackfrm",		OFFSETOF(wl_cnt_ver_7_t, txackfrm)},
+	{"txdnlfrm",		OFFSETOF(wl_cnt_ver_7_t, txdnlfrm)},
+	{"txbcnfrm",		OFFSETOF(wl_cnt_ver_7_t, txbcnfrm)},
+	{"txfunfl[0]",		OFFSETOF(wl_cnt_ver_7_t, txfunfl[0])},
+	{"txfunfl[1]",		OFFSETOF(wl_cnt_ver_7_t, txfunfl[1])},
+	{"txfunfl[2]",		OFFSETOF(wl_cnt_ver_7_t, txfunfl[2])},
+	{"txfunfl[3]",		OFFSETOF(wl_cnt_ver_7_t, txfunfl[3])},
+	{"txfunfl[4]",		OFFSETOF(wl_cnt_ver_7_t, txfunfl[4])},
+	{"txfunfl[5]",		OFFSETOF(wl_cnt_ver_7_t, txfunfl[5])},
+	{"txtplunfl",		OFFSETOF(wl_cnt_ver_7_t, txtplunfl)},
+	{"txphyerror",		OFFSETOF(wl_cnt_ver_7_t, txphyerror)},
+	{"pktengrxducast",	OFFSETOF(wl_cnt_ver_7_t, pktengrxducast)},
+	{"pktengrxdmcast",	OFFSETOF(wl_cnt_ver_7_t, pktengrxdmcast)},
+	{"rxfrmtoolong",	OFFSETOF(wl_cnt_ver_7_t, rxfrmtoolong)},
+	{"rxfrmtooshrt",	OFFSETOF(wl_cnt_ver_7_t, rxfrmtooshrt)},
+	{"rxanyerr",		OFFSETOF(wl_cnt_ver_7_t, rxinvmachdr)},
+	{"rxbadfcs",		OFFSETOF(wl_cnt_ver_7_t, rxbadfcs)},
+	{"rxbadplcp",		OFFSETOF(wl_cnt_ver_7_t, rxbadplcp)},
+	{"rxcrsglitch",		OFFSETOF(wl_cnt_ver_7_t, rxcrsglitch)},
+	{"rxstrt",		OFFSETOF(wl_cnt_ver_7_t, rxstrt)},
+	{"rxdtucastmbss",	OFFSETOF(wl_cnt_ver_7_t, rxdfrmucastmbss)},
+	{"rxmgucastmbss",	OFFSETOF(wl_cnt_ver_7_t, rxmfrmucastmbss)},
+	{"rxctlucast",		OFFSETOF(wl_cnt_ver_7_t, rxcfrmucast)},
+	{"rxrtsucast",		OFFSETOF(wl_cnt_ver_7_t, rxrtsucast)},
+	{"rxctsucast",		OFFSETOF(wl_cnt_ver_7_t, rxctsucast)},
+	{"rxackucast",		OFFSETOF(wl_cnt_ver_7_t, rxackucast)},
+	{"rxdtocast",		OFFSETOF(wl_cnt_ver_7_t, rxdfrmocast)},
+	{"rxmgocast",		OFFSETOF(wl_cnt_ver_7_t, rxmfrmocast)},
+	{"rxctlocast",		OFFSETOF(wl_cnt_ver_7_t, rxcfrmocast)},
+	{"rxrtsocast",		OFFSETOF(wl_cnt_ver_7_t, rxrtsocast)},
+	{"rxctsocast",		OFFSETOF(wl_cnt_ver_7_t, rxctsocast)},
+	{"rxdtmcast",		OFFSETOF(wl_cnt_ver_7_t, rxdfrmmcast)},
+	{"rxmgmcast",		OFFSETOF(wl_cnt_ver_7_t, rxmfrmmcast)},
+	{"rxctlmcast",		OFFSETOF(wl_cnt_ver_7_t, rxcfrmmcast)},
+	{"rxbeaconmbss",	OFFSETOF(wl_cnt_ver_7_t, rxbeaconmbss)},
+	{"rxdtucastobss",	OFFSETOF(wl_cnt_ver_7_t, rxdfrmucastobss)},
+	{"rxbeaconobss",	OFFSETOF(wl_cnt_ver_7_t, rxbeaconobss)},
+	{"rxrsptmout",		OFFSETOF(wl_cnt_ver_7_t, rxrsptmout)},
+	{"bcntxcancl",		OFFSETOF(wl_cnt_ver_7_t, bcntxcancl)},
+	{"rxf0ovfl",		OFFSETOF(wl_cnt_ver_7_t, rxf0ovfl)},
+	{"rxf1ovfl",		OFFSETOF(wl_cnt_ver_7_t, rxf1ovfl)},
+	{"rxhlovfl",		OFFSETOF(wl_cnt_ver_7_t, rxf2ovfl)},
+	{"missbcn_dbg",		OFFSETOF(wl_cnt_ver_7_t, txsfovfl)},
+	{"pmqovfl",		OFFSETOF(wl_cnt_ver_7_t, pmqovfl)},
+	{"rxcgprqfrm",		OFFSETOF(wl_cnt_ver_7_t, rxcgprqfrm)},
+	{"rxcgprsqovfl",	OFFSETOF(wl_cnt_ver_7_t, rxcgprsqovfl)},
+	{"txcgprsfail",		OFFSETOF(wl_cnt_ver_7_t, txcgprsfail)},
+	{"txcgprssuc",		OFFSETOF(wl_cnt_ver_7_t, txcgprssuc)},
+	{"prs_timeout",		OFFSETOF(wl_cnt_ver_7_t, prs_timeout)},
+	{"txrtsfail",		OFFSETOF(wl_cnt_ver_7_t, rxnack)},
+	{"txucast",		OFFSETOF(wl_cnt_ver_7_t, frmscons)},
+	{"txinrtstxop",		OFFSETOF(wl_cnt_ver_7_t, txnack)},
+	{"bphy_rxcrsglitch",	OFFSETOF(wl_cnt_ver_7_t, bphy_rxcrsglitch)},
+	{NULL, 0},
+};
+
+static counter_offset_info_t cntr_offset_info_v11[] = {
+	{"txframe",		OFFSETOF(wl_cnt_ver_11_t, txframe)},
+	{"txbyte",		OFFSETOF(wl_cnt_ver_11_t, txbyte)},
+	{"txretrans",		OFFSETOF(wl_cnt_ver_11_t, txretrans)},
+	{"txerror",		OFFSETOF(wl_cnt_ver_11_t, txerror)},
+	{"txctl",		OFFSETOF(wl_cnt_ver_11_t, txctl)},
+	{"txprshort",		OFFSETOF(wl_cnt_ver_11_t, txprshort)},
+	{"txserr",		OFFSETOF(wl_cnt_ver_11_t, txserr)},
+	{"txnobuf",		OFFSETOF(wl_cnt_ver_11_t, txnobuf)},
+	{"txnoassoc",		OFFSETOF(wl_cnt_ver_11_t, txnoassoc)},
+	{"txrunt",		OFFSETOF(wl_cnt_ver_11_t, txrunt)},
+	{"txchit",		OFFSETOF(wl_cnt_ver_11_t, txchit)},
+	{"txcmiss",		OFFSETOF(wl_cnt_ver_11_t, txcmiss)},
+	{"txuflo",		OFFSETOF(wl_cnt_ver_11_t, txuflo)},
+	{"txphyerr",		OFFSETOF(wl_cnt_ver_11_t, txphyerr)},
+	{"txphycrs",		OFFSETOF(wl_cnt_ver_11_t, txphycrs)},
+	{"rxframe",		OFFSETOF(wl_cnt_ver_11_t, rxframe)},
+	{"rxbyte",		OFFSETOF(wl_cnt_ver_11_t, rxbyte)},
+	{"rxerror",		OFFSETOF(wl_cnt_ver_11_t, rxerror)},
+	{"rxctl",		OFFSETOF(wl_cnt_ver_11_t, rxctl)},
+	{"rxnobuf",		OFFSETOF(wl_cnt_ver_11_t, rxnobuf)},
+	{"rxnondata",		OFFSETOF(wl_cnt_ver_11_t, rxnondata)},
+	{"rxbadds",		OFFSETOF(wl_cnt_ver_11_t, rxbadds)},
+	{"rxbadcm",		OFFSETOF(wl_cnt_ver_11_t, rxbadcm)},
+	{"rxfragerr",		OFFSETOF(wl_cnt_ver_11_t, rxfragerr)},
+	{"rxrunt",		OFFSETOF(wl_cnt_ver_11_t, rxrunt)},
+	{"rxgiant",		OFFSETOF(wl_cnt_ver_11_t, rxgiant)},
+	{"rxnoscb",		OFFSETOF(wl_cnt_ver_11_t, rxnoscb)},
+	{"rxbadproto",		OFFSETOF(wl_cnt_ver_11_t, rxbadproto)},
+	{"rxbadsrcmac",		OFFSETOF(wl_cnt_ver_11_t, rxbadsrcmac)},
+	{"rxbadda",		OFFSETOF(wl_cnt_ver_11_t, rxbadda)},
+	{"rxfilter",		OFFSETOF(wl_cnt_ver_11_t, rxfilter)},
+	{"rxoflo",		OFFSETOF(wl_cnt_ver_11_t, rxoflo)},
+	{"rxuflo[0]",		OFFSETOF(wl_cnt_ver_11_t, rxuflo[0])},
+	{"rxuflo[1]",		OFFSETOF(wl_cnt_ver_11_t, rxuflo[1])},
+	{"rxuflo[2]",		OFFSETOF(wl_cnt_ver_11_t, rxuflo[2])},
+	{"rxuflo[3]",		OFFSETOF(wl_cnt_ver_11_t, rxuflo[3])},
+	{"rxuflo[4]",		OFFSETOF(wl_cnt_ver_11_t, rxuflo[4])},
+	{"rxuflo[5]",		OFFSETOF(wl_cnt_ver_11_t, rxuflo[5])},
+	{"d11cnt_txrts_off",	OFFSETOF(wl_cnt_ver_11_t, d11cnt_txrts_off)},
+	{"d11cnt_rxcrc_off",	OFFSETOF(wl_cnt_ver_11_t, d11cnt_rxcrc_off)},
+	{"d11cnt_txnocts_off",	OFFSETOF(wl_cnt_ver_11_t, d11cnt_txnocts_off)},
+	{"dmade",		OFFSETOF(wl_cnt_ver_11_t, dmade)},
+	{"dmada",		OFFSETOF(wl_cnt_ver_11_t, dmada)},
+	{"dmape",		OFFSETOF(wl_cnt_ver_11_t, dmape)},
+	{"reset",		OFFSETOF(wl_cnt_ver_11_t, reset)},
+	{"tbtt",		OFFSETOF(wl_cnt_ver_11_t, tbtt)},
+	{"txdmawar",		OFFSETOF(wl_cnt_ver_11_t, txdmawar)},
+	{"pkt_callback_reg_fail", OFFSETOF(wl_cnt_ver_11_t, pkt_callback_reg_fail)},
+	{"d11_txfrag",		OFFSETOF(wl_cnt_ver_11_t, txfrag)},
+	{"d11_txmulti",		OFFSETOF(wl_cnt_ver_11_t, txmulti)},
+	{"txfail",		OFFSETOF(wl_cnt_ver_11_t, txfail)},
+	{"d11_txretry",		OFFSETOF(wl_cnt_ver_11_t, txretry)},
+	{"d11_txretrie",	OFFSETOF(wl_cnt_ver_11_t, txretrie)},
+	{"rxdup",		OFFSETOF(wl_cnt_ver_11_t, rxdup)},
+	{"d11_txrts",		OFFSETOF(wl_cnt_ver_11_t, txrts)},
+	{"d11_txnocts",		OFFSETOF(wl_cnt_ver_11_t, txnocts)},
+	{"d11_txnoack",		OFFSETOF(wl_cnt_ver_11_t, txnoack)},
+	{"d11_rxfrag",		OFFSETOF(wl_cnt_ver_11_t, rxfrag)},
+	{"d11_rxmulti",		OFFSETOF(wl_cnt_ver_11_t, rxmulti)},
+	{"rxcrc",		OFFSETOF(wl_cnt_ver_11_t, rxcrc)},
+	{"d11_txfrmsnt",	OFFSETOF(wl_cnt_ver_11_t, txfrmsnt)},
+	{"d11_rxundec",		OFFSETOF(wl_cnt_ver_11_t, rxundec)},
+	{"tkipmicfaill",	OFFSETOF(wl_cnt_ver_11_t, tkipmicfaill)},
+	{"tkipcntrmsr",		OFFSETOF(wl_cnt_ver_11_t, tkipcntrmsr)},
+	{"tkipreplay",		OFFSETOF(wl_cnt_ver_11_t, tkipreplay)},
+	{"ccmpfmterr",		OFFSETOF(wl_cnt_ver_11_t, ccmpfmterr)},
+	{"ccmpreplay",		OFFSETOF(wl_cnt_ver_11_t, ccmpreplay)},
+	{"ccmpundec",		OFFSETOF(wl_cnt_ver_11_t, ccmpundec)},
+	{"fourwayfail",		OFFSETOF(wl_cnt_ver_11_t, fourwayfail)},
+	{"wepundec",		OFFSETOF(wl_cnt_ver_11_t, wepundec)},
+	{"wepicverr",		OFFSETOF(wl_cnt_ver_11_t, wepicverr)},
+	{"decsuccess",		OFFSETOF(wl_cnt_ver_11_t, decsuccess)},
+	{"tkipicverr",		OFFSETOF(wl_cnt_ver_11_t, tkipicverr)},
+	{"wepexcluded",		OFFSETOF(wl_cnt_ver_11_t, wepexcluded)},
+	{"txchanrej",		OFFSETOF(wl_cnt_ver_11_t, txchanrej)},
+	{"psmwds",		OFFSETOF(wl_cnt_ver_11_t, psmwds)},
+	{"phywatchdog",		OFFSETOF(wl_cnt_ver_11_t, phywatchdog)},
+	{"prq_entries_handled",	OFFSETOF(wl_cnt_ver_11_t, prq_entries_handled)},
+	{"prq_undirected_entries", OFFSETOF(wl_cnt_ver_11_t, prq_undirected_entries)},
+	{"prq_bad_entries",	OFFSETOF(wl_cnt_ver_11_t, prq_bad_entries)},
+	{"atim_suppress_count",	OFFSETOF(wl_cnt_ver_11_t, atim_suppress_count)},
+	{"bcn_template_not_ready", OFFSETOF(wl_cnt_ver_11_t, bcn_template_not_ready)},
+	{"bcn_template_not_ready_done",	OFFSETOF(wl_cnt_ver_11_t, bcn_template_not_ready_done)},
+	{"late_tbtt_dpc",	OFFSETOF(wl_cnt_ver_11_t, late_tbtt_dpc)},
+	{"rx1mbps",		OFFSETOF(wl_cnt_ver_11_t, rx1mbps)},
+	{"rx2mbps",		OFFSETOF(wl_cnt_ver_11_t, rx2mbps)},
+	{"rx5mbps5",		OFFSETOF(wl_cnt_ver_11_t, rx5mbps5)},
+	{"rx6mbps",		OFFSETOF(wl_cnt_ver_11_t, rx6mbps)},
+	{"rx9mbps",		OFFSETOF(wl_cnt_ver_11_t, rx9mbps)},
+	{"rx11mbps",		OFFSETOF(wl_cnt_ver_11_t, rx11mbps)},
+	{"rx12mbps",		OFFSETOF(wl_cnt_ver_11_t, rx12mbps)},
+	{"rx18mbps",		OFFSETOF(wl_cnt_ver_11_t, rx18mbps)},
+	{"rx24mbps",		OFFSETOF(wl_cnt_ver_11_t, rx24mbps)},
+	{"rx36mbps",		OFFSETOF(wl_cnt_ver_11_t, rx36mbps)},
+	{"rx48mbps",		OFFSETOF(wl_cnt_ver_11_t, rx48mbps)},
+	{"rx54mbps",		OFFSETOF(wl_cnt_ver_11_t, rx54mbps)},
+	{"rx108mbps",		OFFSETOF(wl_cnt_ver_11_t, rx108mbps)},
+	{"rx162mbps",		OFFSETOF(wl_cnt_ver_11_t, rx162mbps)},
+	{"rx216mbps",		OFFSETOF(wl_cnt_ver_11_t, rx216mbps)},
+	{"rx270mbps",		OFFSETOF(wl_cnt_ver_11_t, rx270mbps)},
+	{"rx324mbps",		OFFSETOF(wl_cnt_ver_11_t, rx324mbps)},
+	{"rx378mbps",		OFFSETOF(wl_cnt_ver_11_t, rx378mbps)},
+	{"rx432mbps",		OFFSETOF(wl_cnt_ver_11_t, rx432mbps)},
+	{"rx486mbps",		OFFSETOF(wl_cnt_ver_11_t, rx486mbps)},
+	{"rx540mbps",		OFFSETOF(wl_cnt_ver_11_t, rx540mbps)},
+	{"rfdisable",		OFFSETOF(wl_cnt_ver_11_t, rfdisable)},
+	{"txexptime",		OFFSETOF(wl_cnt_ver_11_t, txexptime)},
+	{"txmpdu_sgi",		OFFSETOF(wl_cnt_ver_11_t, txmpdu_sgi)},
+	{"rxmpdu_sgi",		OFFSETOF(wl_cnt_ver_11_t, rxmpdu_sgi)},
+	{"txmpdu_stbc",		OFFSETOF(wl_cnt_ver_11_t, txmpdu_stbc)},
+	{"rxmpdu_stbc",		OFFSETOF(wl_cnt_ver_11_t, rxmpdu_stbc)},
+	{"rxundec_mcst",	OFFSETOF(wl_cnt_ver_11_t, rxundec_mcst)},
+	{"tkipmicfaill_mcst",	OFFSETOF(wl_cnt_ver_11_t, tkipmicfaill_mcst)},
+	{"tkipcntrmsr_mcst",	OFFSETOF(wl_cnt_ver_11_t, tkipcntrmsr_mcst)},
+	{"tkipreplay_mcst",	OFFSETOF(wl_cnt_ver_11_t, tkipreplay_mcst)},
+	{"ccmpfmterr_mcst",	OFFSETOF(wl_cnt_ver_11_t, ccmpfmterr_mcst)},
+	{"ccmpreplay_mcst",	OFFSETOF(wl_cnt_ver_11_t, ccmpreplay_mcst)},
+	{"ccmpundec_mcst",	OFFSETOF(wl_cnt_ver_11_t, ccmpundec_mcst)},
+	{"fourwayfail_mcst",	OFFSETOF(wl_cnt_ver_11_t, fourwayfail_mcst)},
+	{"wepundec_mcst",	OFFSETOF(wl_cnt_ver_11_t, wepundec_mcst)},
+	{"wepicverr_mcst",	OFFSETOF(wl_cnt_ver_11_t, wepicverr_mcst)},
+	{"decsuccess_mcst",	OFFSETOF(wl_cnt_ver_11_t, decsuccess_mcst)},
+	{"tkipicverr_mcst",	OFFSETOF(wl_cnt_ver_11_t, tkipicverr_mcst)},
+	{"wepexcluded_mcst",	OFFSETOF(wl_cnt_ver_11_t, wepexcluded_mcst)},
+	{"dma_hang",		OFFSETOF(wl_cnt_ver_11_t, dma_hang)},
+	{"reinit",		OFFSETOF(wl_cnt_ver_11_t, reinit)},
+	{"pstatxucast",		OFFSETOF(wl_cnt_ver_11_t, pstatxucast)},
+	{"pstatxnoassoc",	OFFSETOF(wl_cnt_ver_11_t, pstatxnoassoc)},
+	{"pstarxucast",		OFFSETOF(wl_cnt_ver_11_t, pstarxucast)},
+	{"pstarxbcmc",		OFFSETOF(wl_cnt_ver_11_t, pstarxbcmc)},
+	{"pstatxbcmc",		OFFSETOF(wl_cnt_ver_11_t, pstatxbcmc)},
+	{"cso_passthrough",	OFFSETOF(wl_cnt_ver_11_t, cso_passthrough)},
+	{"cso_normal",		OFFSETOF(wl_cnt_ver_11_t, cso_normal)},
+	{"chained",		OFFSETOF(wl_cnt_ver_11_t, chained)},
+	{"chainedsz1",		OFFSETOF(wl_cnt_ver_11_t, chainedsz1)},
+	{"unchained",		OFFSETOF(wl_cnt_ver_11_t, unchained)},
+	{"maxchainsz",		OFFSETOF(wl_cnt_ver_11_t, maxchainsz)},
+	{"currchainsz",		OFFSETOF(wl_cnt_ver_11_t, currchainsz)},
+	{"pciereset",		OFFSETOF(wl_cnt_ver_11_t, pciereset)},
+	{"cfgrestore",		OFFSETOF(wl_cnt_ver_11_t, cfgrestore)},
+	{"reinit",		OFFSETOF(wl_cnt_ver_11_t, reinit)},
+	{"reinitreason[0]",	OFFSETOF(wl_cnt_ver_11_t, reinitreason[0])},
+	{"reinitreason[1]",	OFFSETOF(wl_cnt_ver_11_t, reinitreason[1])},
+	{"reinitreason[2]",	OFFSETOF(wl_cnt_ver_11_t, reinitreason[2])},
+	{"reinitreason[3]",	OFFSETOF(wl_cnt_ver_11_t, reinitreason[3])},
+	{"reinitreason[4]",	OFFSETOF(wl_cnt_ver_11_t, reinitreason[4])},
+	{"reinitreason[5]",	OFFSETOF(wl_cnt_ver_11_t, reinitreason[5])},
+	{"reinitreason[6]",	OFFSETOF(wl_cnt_ver_11_t, reinitreason[6])},
+	{"reinitreason[7]",	OFFSETOF(wl_cnt_ver_11_t, reinitreason[7])},
+	{"rxrtry",		OFFSETOF(wl_cnt_ver_11_t, rxrtry)},
+	{"rxmpdu_mu",		OFFSETOF(wl_cnt_ver_11_t, rxmpdu_mu)},
+	{"txbar",		OFFSETOF(wl_cnt_ver_11_t, txbar)},
+	{"rxbar",		OFFSETOF(wl_cnt_ver_11_t, rxbar)},
+	{"txpspoll",		OFFSETOF(wl_cnt_ver_11_t, txpspoll)},
+	{"rxpspoll",		OFFSETOF(wl_cnt_ver_11_t, rxpspoll)},
+	{"txnull",		OFFSETOF(wl_cnt_ver_11_t, txnull)},
+	{"rxnull",		OFFSETOF(wl_cnt_ver_11_t, rxnull)},
+	{"txqosnull",		OFFSETOF(wl_cnt_ver_11_t, txqosnull)},
+	{"rxqosnull",		OFFSETOF(wl_cnt_ver_11_t, rxqosnull)},
+	{"txassocreq",		OFFSETOF(wl_cnt_ver_11_t, txassocreq)},
+	{"rxassocreq",		OFFSETOF(wl_cnt_ver_11_t, rxassocreq)},
+	{"txreassocreq",	OFFSETOF(wl_cnt_ver_11_t, txreassocreq)},
+	{"rxreassocreq",	OFFSETOF(wl_cnt_ver_11_t, rxreassocreq)},
+	{"txdisassoc",		OFFSETOF(wl_cnt_ver_11_t, txdisassoc)},
+	{"rxdisassoc",		OFFSETOF(wl_cnt_ver_11_t, rxdisassoc)},
+	{"txassocrsp",		OFFSETOF(wl_cnt_ver_11_t, txassocrsp)},
+	{"rxassocrsp",		OFFSETOF(wl_cnt_ver_11_t, rxassocrsp)},
+	{"txreassocrsp",	OFFSETOF(wl_cnt_ver_11_t, txreassocrsp)},
+	{"rxreassocrsp",	OFFSETOF(wl_cnt_ver_11_t, rxreassocrsp)},
+	{"txauth",		OFFSETOF(wl_cnt_ver_11_t, txauth)},
+	{"rxauth",		OFFSETOF(wl_cnt_ver_11_t, rxauth)},
+	{"txdeauth",		OFFSETOF(wl_cnt_ver_11_t, txdeauth)},
+	{"rxdeauth",		OFFSETOF(wl_cnt_ver_11_t, rxdeauth)},
+	{"txprobereq",		OFFSETOF(wl_cnt_ver_11_t, txprobereq)},
+	{"rxprobereq",		OFFSETOF(wl_cnt_ver_11_t, rxprobereq)},
+	{"txprobersp",		OFFSETOF(wl_cnt_ver_11_t, txprobersp)},
+	{"rxprobersp",		OFFSETOF(wl_cnt_ver_11_t, rxprobersp)},
+	{"txaction",		OFFSETOF(wl_cnt_ver_11_t, txaction)},
+	{"rxaction",		OFFSETOF(wl_cnt_ver_11_t, rxaction)},
+	/* macstats counters */
+	{"txallfrm",		OFFSETOF(wl_cnt_ver_11_t, txallfrm)},
+	{"txrtsfrm",		OFFSETOF(wl_cnt_ver_11_t, txrtsfrm)},
+	{"txctsfrm",		OFFSETOF(wl_cnt_ver_11_t, txctsfrm)},
+	{"txackfrm",		OFFSETOF(wl_cnt_ver_11_t, txackfrm)},
+	{"txdnlfrm",		OFFSETOF(wl_cnt_ver_11_t, txdnlfrm)},
+	{"txbcnfrm",		OFFSETOF(wl_cnt_ver_11_t, txbcnfrm)},
+	{"txfunfl[0]",		OFFSETOF(wl_cnt_ver_11_t, txfunfl[0])},
+	{"txfunfl[1]",		OFFSETOF(wl_cnt_ver_11_t, txfunfl[1])},
+	{"txfunfl[2]",		OFFSETOF(wl_cnt_ver_11_t, txfunfl[2])},
+	{"txfunfl[3]",		OFFSETOF(wl_cnt_ver_11_t, txfunfl[3])},
+	{"txfunfl[4]",		OFFSETOF(wl_cnt_ver_11_t, txfunfl[4])},
+	{"txfunfl[5]",		OFFSETOF(wl_cnt_ver_11_t, txfunfl[5])},
+	{"txampdu",		OFFSETOF(wl_cnt_ver_11_t, txfbw)},
+	{"txmpdu",		OFFSETOF(wl_cnt_ver_11_t, txmpdu)},
+	{"txtplunfl",		OFFSETOF(wl_cnt_ver_11_t, txtplunfl)},
+	{"txphyerror",		OFFSETOF(wl_cnt_ver_11_t, txphyerror)},
+	{"pktengrxducast",	OFFSETOF(wl_cnt_ver_11_t, pktengrxducast)},
+	{"pktengrxdmcast",	OFFSETOF(wl_cnt_ver_11_t, pktengrxdmcast)},
+	{"rxfrmtoolong",	OFFSETOF(wl_cnt_ver_11_t, rxfrmtoolong)},
+	{"rxfrmtooshrt",	OFFSETOF(wl_cnt_ver_11_t, rxfrmtooshrt)},
+	{"rxanyerr",		OFFSETOF(wl_cnt_ver_11_t, rxinvmachdr)},
+	{"rxbadfcs",		OFFSETOF(wl_cnt_ver_11_t, rxbadfcs)},
+	{"rxbadplcp",		OFFSETOF(wl_cnt_ver_11_t, rxbadplcp)},
+	{"rxcrsglitch",		OFFSETOF(wl_cnt_ver_11_t, rxcrsglitch)},
+	{"rxstrt",		OFFSETOF(wl_cnt_ver_11_t, rxstrt)},
+	{"rxdtucastmbss",	OFFSETOF(wl_cnt_ver_11_t, rxdfrmucastmbss)},
+	{"rxmgucastmbss",	OFFSETOF(wl_cnt_ver_11_t, rxmfrmucastmbss)},
+	{"rxctlucast",		OFFSETOF(wl_cnt_ver_11_t, rxcfrmucast)},
+	{"rxrtsucast",		OFFSETOF(wl_cnt_ver_11_t, rxrtsucast)},
+	{"rxctsucast",		OFFSETOF(wl_cnt_ver_11_t, rxctsucast)},
+	{"rxackucast",		OFFSETOF(wl_cnt_ver_11_t, rxackucast)},
+	{"rxdtocast",		OFFSETOF(wl_cnt_ver_11_t, rxdfrmocast)},
+	{"rxmgocast",		OFFSETOF(wl_cnt_ver_11_t, rxmfrmocast)},
+	{"rxctlocast",		OFFSETOF(wl_cnt_ver_11_t, rxcfrmocast)},
+	{"rxrtsocast",		OFFSETOF(wl_cnt_ver_11_t, rxrtsocast)},
+	{"rxctsocast",		OFFSETOF(wl_cnt_ver_11_t, rxctsocast)},
+	{"rxdtmcast",		OFFSETOF(wl_cnt_ver_11_t, rxdfrmmcast)},
+	{"rxmgmcast",		OFFSETOF(wl_cnt_ver_11_t, rxmfrmmcast)},
+	{"rxctlmcast",		OFFSETOF(wl_cnt_ver_11_t, rxcfrmmcast)},
+	{"rxbeaconmbss",	OFFSETOF(wl_cnt_ver_11_t, rxbeaconmbss)},
+	{"rxdtucastobss",	OFFSETOF(wl_cnt_ver_11_t, rxdfrmucastobss)},
+	{"rxbeaconobss",	OFFSETOF(wl_cnt_ver_11_t, rxbeaconobss)},
+	{"rxrsptmout",		OFFSETOF(wl_cnt_ver_11_t, rxrsptmout)},
+	{"bcntxcancl",		OFFSETOF(wl_cnt_ver_11_t, bcntxcancl)},
+	{"rxnodelim",		OFFSETOF(wl_cnt_ver_11_t, rxnodelim)},
+	{"rxf0ovfl",		OFFSETOF(wl_cnt_ver_11_t, rxf0ovfl)},
+	{"rxf1ovfl",		OFFSETOF(wl_cnt_ver_11_t, rxf1ovfl)},
+	{"rxhlovfl",		OFFSETOF(wl_cnt_ver_11_t, rxf2ovfl)},
+	{"missbcn_dbg",		OFFSETOF(wl_cnt_ver_11_t, txsfovfl)},
+	{"pmqovfl",		OFFSETOF(wl_cnt_ver_11_t, pmqovfl)},
+	{"rxcgprqfrm",		OFFSETOF(wl_cnt_ver_11_t, rxcgprqfrm)},
+	{"rxcgprsqovfl",	OFFSETOF(wl_cnt_ver_11_t, rxcgprsqovfl)},
+	{"txcgprsfail",		OFFSETOF(wl_cnt_ver_11_t, txcgprsfail)},
+	{"txcgprssuc",		OFFSETOF(wl_cnt_ver_11_t, txcgprssuc)},
+	{"prs_timeout",		OFFSETOF(wl_cnt_ver_11_t, prs_timeout)},
+	{"txrtsfail",		OFFSETOF(wl_cnt_ver_11_t, rxnack)},
+	{"txucast",		OFFSETOF(wl_cnt_ver_11_t, frmscons)},
+	{"txinrtstxop",		OFFSETOF(wl_cnt_ver_11_t, txnack)},
+	{"rxback",		OFFSETOF(wl_cnt_ver_11_t, rxback)},
+	{"txback",		OFFSETOF(wl_cnt_ver_11_t, txback)},
+	{"bphy_rxcrsglitch",	OFFSETOF(wl_cnt_ver_11_t, bphy_rxcrsglitch)},
+	{"rxdrop20s",		OFFSETOF(wl_cnt_ver_11_t, rxdrop20s)},
+	{"rxtoolate",		OFFSETOF(wl_cnt_ver_11_t, rxtoolate)},
+	{"bphy_badplcp",	OFFSETOF(wl_cnt_ver_11_t, bphy_badplcp)},
+	{NULL, 0},
+};
+
+
+#define OFFSET_MCST_V30(X) (OFFSETOF(wl_cnt_ge40mcst_v1_t, X) +\
+	sizeof(wl_cnt_wlc_t))
+#define OFFSET_RIRNS_V30(X) (sizeof(wl_cnt_wlc_t) +\
+	WL_CNT_MCST_STRUCT_SZ + OFFSETOF(reinit_rsns_t, X))
+static counter_offset_info_t cntr_offset_info_v30[] = {
+	/* wl counters */
+	{"txframe",		OFFSETOF(wl_cnt_wlc_t, txframe)},
+	{"txbyte",		OFFSETOF(wl_cnt_wlc_t, txbyte)},
+	{"txretrans",		OFFSETOF(wl_cnt_wlc_t, txretrans)},
+	{"txerror",		OFFSETOF(wl_cnt_wlc_t, txerror)},
+	{"txctl",		OFFSETOF(wl_cnt_wlc_t, txctl)},
+	{"txprshort",		OFFSETOF(wl_cnt_wlc_t, txprshort)},
+	{"txserr",		OFFSETOF(wl_cnt_wlc_t, txserr)},
+	{"txnobuf",		OFFSETOF(wl_cnt_wlc_t, txnobuf)},
+	{"txnoassoc",		OFFSETOF(wl_cnt_wlc_t, txnoassoc)},
+	{"txrunt",		OFFSETOF(wl_cnt_wlc_t, txrunt)},
+	{"txchit",		OFFSETOF(wl_cnt_wlc_t, txchit)},
+	{"txcmiss",		OFFSETOF(wl_cnt_wlc_t, txcmiss)},
+	{"txuflo",		OFFSETOF(wl_cnt_wlc_t, txuflo)},
+	{"txphyerr",		OFFSETOF(wl_cnt_wlc_t, txphyerr)},
+	{"txphycrs",		OFFSETOF(wl_cnt_wlc_t, txphycrs)},
+	{"rxframe",		OFFSETOF(wl_cnt_wlc_t, rxframe)},
+	{"rxbyte",		OFFSETOF(wl_cnt_wlc_t, rxbyte)},
+	{"rxerror",		OFFSETOF(wl_cnt_wlc_t, rxerror)},
+	{"rxctl",		OFFSETOF(wl_cnt_wlc_t, rxctl)},
+	{"rxnobuf",		OFFSETOF(wl_cnt_wlc_t, rxnobuf)},
+	{"rxnondata",		OFFSETOF(wl_cnt_wlc_t, rxnondata)},
+	{"rxbadds",		OFFSETOF(wl_cnt_wlc_t, rxbadds)},
+	{"rxbadcm",		OFFSETOF(wl_cnt_wlc_t, rxbadcm)},
+	{"rxfragerr",		OFFSETOF(wl_cnt_wlc_t, rxfragerr)},
+	{"rxrunt",		OFFSETOF(wl_cnt_wlc_t, rxrunt)},
+	{"rxgiant",		OFFSETOF(wl_cnt_wlc_t, rxgiant)},
+	{"rxnoscb",		OFFSETOF(wl_cnt_wlc_t, rxnoscb)},
+	{"rxbadproto",		OFFSETOF(wl_cnt_wlc_t, rxbadproto)},
+	{"rxbadsrcmac",		OFFSETOF(wl_cnt_wlc_t, rxbadsrcmac)},
+	{"rxbadda",		OFFSETOF(wl_cnt_wlc_t, rxbadda)},
+	{"rxfilter",		OFFSETOF(wl_cnt_wlc_t, rxfilter)},
+	{"rxoflo",		OFFSETOF(wl_cnt_wlc_t, rxoflo)},
+	{"rxuflo[0]",		OFFSETOF(wl_cnt_wlc_t, rxuflo[0])},
+	{"rxuflo[1]",		OFFSETOF(wl_cnt_wlc_t, rxuflo[1])},
+	{"rxuflo[2]",		OFFSETOF(wl_cnt_wlc_t, rxuflo[2])},
+	{"rxuflo[3]",		OFFSETOF(wl_cnt_wlc_t, rxuflo[3])},
+	{"rxuflo[4]",		OFFSETOF(wl_cnt_wlc_t, rxuflo[4])},
+	{"rxuflo[5]",		OFFSETOF(wl_cnt_wlc_t, rxuflo[5])},
+	{"d11cnt_txrts_off",	OFFSETOF(wl_cnt_wlc_t, d11cnt_txrts_off)},
+	{"d11cnt_rxcrc_off",	OFFSETOF(wl_cnt_wlc_t, d11cnt_rxcrc_off)},
+	{"d11cnt_txnocts_off",	OFFSETOF(wl_cnt_wlc_t, d11cnt_txnocts_off)},
+	{"dmade",		OFFSETOF(wl_cnt_wlc_t, dmade)},
+	{"dmada",		OFFSETOF(wl_cnt_wlc_t, dmada)},
+	{"dmape",		OFFSETOF(wl_cnt_wlc_t, dmape)},
+	{"reset",		OFFSETOF(wl_cnt_wlc_t, reset)},
+	{"tbtt",		OFFSETOF(wl_cnt_wlc_t, tbtt)},
+	{"txdmawar",		OFFSETOF(wl_cnt_wlc_t, txdmawar)},
+	{"pkt_callback_reg_fail", OFFSETOF(wl_cnt_wlc_t, pkt_callback_reg_fail)},
+	{"d11_txfrag",		OFFSETOF(wl_cnt_wlc_t, txfrag)},
+	{"d11_txmulti",		OFFSETOF(wl_cnt_wlc_t, txmulti)},
+	{"txfail",		OFFSETOF(wl_cnt_wlc_t, txfail)},
+	{"d11_txretry",		OFFSETOF(wl_cnt_wlc_t, txretry)},
+	{"d11_txretrie",	OFFSETOF(wl_cnt_wlc_t, txretrie)},
+	{"rxdup",		OFFSETOF(wl_cnt_wlc_t, rxdup)},
+	{"d11_txrts",		OFFSETOF(wl_cnt_wlc_t, txrts)},
+	{"d11_txnocts",		OFFSETOF(wl_cnt_wlc_t, txnocts)},
+	{"d11_txnoack",		OFFSETOF(wl_cnt_wlc_t, txnoack)},
+	{"d11_rxfrag",		OFFSETOF(wl_cnt_wlc_t, rxfrag)},
+	{"d11_rxmulti",		OFFSETOF(wl_cnt_wlc_t, rxmulti)},
+	{"rxcrc",		OFFSETOF(wl_cnt_wlc_t, rxcrc)},
+	{"d11_txfrmsnt",	OFFSETOF(wl_cnt_wlc_t, txfrmsnt)},
+	{"d11_rxundec",		OFFSETOF(wl_cnt_wlc_t, rxundec)},
+	{"tkipmicfaill",	OFFSETOF(wl_cnt_wlc_t, tkipmicfaill)},
+	{"tkipcntrmsr",		OFFSETOF(wl_cnt_wlc_t, tkipcntrmsr)},
+	{"tkipreplay",		OFFSETOF(wl_cnt_wlc_t, tkipreplay)},
+	{"ccmpfmterr",		OFFSETOF(wl_cnt_wlc_t, ccmpfmterr)},
+	{"ccmpreplay",		OFFSETOF(wl_cnt_wlc_t, ccmpreplay)},
+	{"ccmpundec",		OFFSETOF(wl_cnt_wlc_t, ccmpundec)},
+	{"fourwayfail",		OFFSETOF(wl_cnt_wlc_t, fourwayfail)},
+	{"wepundec",		OFFSETOF(wl_cnt_wlc_t, wepundec)},
+	{"wepicverr",		OFFSETOF(wl_cnt_wlc_t, wepicverr)},
+	{"decsuccess",		OFFSETOF(wl_cnt_wlc_t, decsuccess)},
+	{"tkipicverr",		OFFSETOF(wl_cnt_wlc_t, tkipicverr)},
+	{"wepexcluded",		OFFSETOF(wl_cnt_wlc_t, wepexcluded)},
+	{"txchanrej",		OFFSETOF(wl_cnt_wlc_t, txchanrej)},
+	{"psmwds",		OFFSETOF(wl_cnt_wlc_t, psmwds)},
+	{"phywatchdog",		OFFSETOF(wl_cnt_wlc_t, phywatchdog)},
+	{"prq_entries_handled",	OFFSETOF(wl_cnt_wlc_t, prq_entries_handled)},
+	{"prq_undirected_entries", OFFSETOF(wl_cnt_wlc_t, prq_undirected_entries)},
+	{"prq_bad_entries",	OFFSETOF(wl_cnt_wlc_t, prq_bad_entries)},
+	{"atim_suppress_count",	OFFSETOF(wl_cnt_wlc_t, atim_suppress_count)},
+	{"bcn_template_not_ready", OFFSETOF(wl_cnt_wlc_t, bcn_template_not_ready)},
+	{"bcn_template_not_ready_done",	OFFSETOF(wl_cnt_wlc_t, bcn_template_not_ready_done)},
+	{"late_tbtt_dpc",	OFFSETOF(wl_cnt_wlc_t, late_tbtt_dpc)},
+	{"rx1mbps",		OFFSETOF(wl_cnt_wlc_t, rx1mbps)},
+	{"rx2mbps",		OFFSETOF(wl_cnt_wlc_t, rx2mbps)},
+	{"rx5mbps5",		OFFSETOF(wl_cnt_wlc_t, rx5mbps5)},
+	{"rx6mbps",		OFFSETOF(wl_cnt_wlc_t, rx6mbps)},
+	{"rx9mbps",		OFFSETOF(wl_cnt_wlc_t, rx9mbps)},
+	{"rx11mbps",		OFFSETOF(wl_cnt_wlc_t, rx11mbps)},
+	{"rx12mbps",		OFFSETOF(wl_cnt_wlc_t, rx12mbps)},
+	{"rx18mbps",		OFFSETOF(wl_cnt_wlc_t, rx18mbps)},
+	{"rx24mbps",		OFFSETOF(wl_cnt_wlc_t, rx24mbps)},
+	{"rx36mbps",		OFFSETOF(wl_cnt_wlc_t, rx36mbps)},
+	{"rx48mbps",		OFFSETOF(wl_cnt_wlc_t, rx48mbps)},
+	{"rx54mbps",		OFFSETOF(wl_cnt_wlc_t, rx54mbps)},
+	{"rx108mbps",		OFFSETOF(wl_cnt_wlc_t, rx108mbps)},
+	{"rx162mbps",		OFFSETOF(wl_cnt_wlc_t, rx162mbps)},
+	{"rx216mbps",		OFFSETOF(wl_cnt_wlc_t, rx216mbps)},
+	{"rx270mbps",		OFFSETOF(wl_cnt_wlc_t, rx270mbps)},
+	{"rx324mbps",		OFFSETOF(wl_cnt_wlc_t, rx324mbps)},
+	{"rx378mbps",		OFFSETOF(wl_cnt_wlc_t, rx378mbps)},
+	{"rx432mbps",		OFFSETOF(wl_cnt_wlc_t, rx432mbps)},
+	{"rx486mbps",		OFFSETOF(wl_cnt_wlc_t, rx486mbps)},
+	{"rx540mbps",		OFFSETOF(wl_cnt_wlc_t, rx540mbps)},
+	{"rfdisable",		OFFSETOF(wl_cnt_wlc_t, rfdisable)},
+	{"txexptime",		OFFSETOF(wl_cnt_wlc_t, txexptime)},
+	{"txmpdu_sgi",		OFFSETOF(wl_cnt_wlc_t, txmpdu_sgi)},
+	{"rxmpdu_sgi",		OFFSETOF(wl_cnt_wlc_t, rxmpdu_sgi)},
+	{"txmpdu_stbc",		OFFSETOF(wl_cnt_wlc_t, txmpdu_stbc)},
+	{"rxmpdu_stbc",		OFFSETOF(wl_cnt_wlc_t, rxmpdu_stbc)},
+	{"rxundec_mcst",	OFFSETOF(wl_cnt_wlc_t, rxundec_mcst)},
+	{"tkipmicfaill_mcst",	OFFSETOF(wl_cnt_wlc_t, tkipmicfaill_mcst)},
+	{"tkipcntrmsr_mcst",	OFFSETOF(wl_cnt_wlc_t, tkipcntrmsr_mcst)},
+	{"tkipreplay_mcst",	OFFSETOF(wl_cnt_wlc_t, tkipreplay_mcst)},
+	{"ccmpfmterr_mcst",	OFFSETOF(wl_cnt_wlc_t, ccmpfmterr_mcst)},
+	{"ccmpreplay_mcst",	OFFSETOF(wl_cnt_wlc_t, ccmpreplay_mcst)},
+	{"ccmpundec_mcst",	OFFSETOF(wl_cnt_wlc_t, ccmpundec_mcst)},
+	{"fourwayfail_mcst",	OFFSETOF(wl_cnt_wlc_t, fourwayfail_mcst)},
+	{"wepundec_mcst",	OFFSETOF(wl_cnt_wlc_t, wepundec_mcst)},
+	{"wepicverr_mcst",	OFFSETOF(wl_cnt_wlc_t, wepicverr_mcst)},
+	{"decsuccess_mcst",	OFFSETOF(wl_cnt_wlc_t, decsuccess_mcst)},
+	{"tkipicverr_mcst",	OFFSETOF(wl_cnt_wlc_t, tkipicverr_mcst)},
+	{"wepexcluded_mcst",	OFFSETOF(wl_cnt_wlc_t, wepexcluded_mcst)},
+	{"dma_hang",		OFFSETOF(wl_cnt_wlc_t, dma_hang)},
+	{"reinit",		OFFSETOF(wl_cnt_wlc_t, reinit)},
+	{"pstatxucast",		OFFSETOF(wl_cnt_wlc_t, pstatxucast)},
+	{"pstatxnoassoc",	OFFSETOF(wl_cnt_wlc_t, pstatxnoassoc)},
+	{"pstarxucast",		OFFSETOF(wl_cnt_wlc_t, pstarxucast)},
+	{"pstarxbcmc",		OFFSETOF(wl_cnt_wlc_t, pstarxbcmc)},
+	{"pstatxbcmc",		OFFSETOF(wl_cnt_wlc_t, pstatxbcmc)},
+	{"cso_passthrough",	OFFSETOF(wl_cnt_wlc_t, cso_passthrough)},
+	{"cso_normal",		OFFSETOF(wl_cnt_wlc_t, cso_normal)},
+	{"chained",		OFFSETOF(wl_cnt_wlc_t, chained)},
+	{"chainedsz1",		OFFSETOF(wl_cnt_wlc_t, chainedsz1)},
+	{"unchained",		OFFSETOF(wl_cnt_wlc_t, unchained)},
+	{"maxchainsz",		OFFSETOF(wl_cnt_wlc_t, maxchainsz)},
+	{"currchainsz",		OFFSETOF(wl_cnt_wlc_t, currchainsz)},
+	{"pciereset",		OFFSETOF(wl_cnt_wlc_t, pciereset)},
+	{"cfgrestore",		OFFSETOF(wl_cnt_wlc_t, cfgrestore)},
+	{"reinitreason[0]",	OFFSETOF(wl_cnt_wlc_t, reinitreason[0])},
+	{"reinitreason[1]",	OFFSETOF(wl_cnt_wlc_t, reinitreason[1])},
+	{"reinitreason[2]",	OFFSETOF(wl_cnt_wlc_t, reinitreason[2])},
+	{"reinitreason[3]",	OFFSETOF(wl_cnt_wlc_t, reinitreason[3])},
+	{"reinitreason[4]",	OFFSETOF(wl_cnt_wlc_t, reinitreason[4])},
+	{"reinitreason[5]",	OFFSETOF(wl_cnt_wlc_t, reinitreason[5])},
+	{"reinitreason[6]",	OFFSETOF(wl_cnt_wlc_t, reinitreason[6])},
+	{"reinitreason[7]",	OFFSETOF(wl_cnt_wlc_t, reinitreason[7])},
+	{"rxrtry",		OFFSETOF(wl_cnt_wlc_t, rxrtry)},
+	{"rxmpdu_mu",		OFFSETOF(wl_cnt_wlc_t, rxmpdu_mu)},
+	{"txbar",		OFFSETOF(wl_cnt_wlc_t, txbar)},
+	{"rxbar",		OFFSETOF(wl_cnt_wlc_t, rxbar)},
+	{"txpspoll",		OFFSETOF(wl_cnt_wlc_t, txpspoll)},
+	{"rxpspoll",		OFFSETOF(wl_cnt_wlc_t, rxpspoll)},
+	{"txnull",		OFFSETOF(wl_cnt_wlc_t, txnull)},
+	{"rxnull",		OFFSETOF(wl_cnt_wlc_t, rxnull)},
+	{"txqosnull",		OFFSETOF(wl_cnt_wlc_t, txqosnull)},
+	{"rxqosnull",		OFFSETOF(wl_cnt_wlc_t, rxqosnull)},
+	{"txassocreq",		OFFSETOF(wl_cnt_wlc_t, txassocreq)},
+	{"rxassocreq",		OFFSETOF(wl_cnt_wlc_t, rxassocreq)},
+	{"txreassocreq",	OFFSETOF(wl_cnt_wlc_t, txreassocreq)},
+	{"rxreassocreq",	OFFSETOF(wl_cnt_wlc_t, rxreassocreq)},
+	{"txdisassoc",		OFFSETOF(wl_cnt_wlc_t, txdisassoc)},
+	{"rxdisassoc",		OFFSETOF(wl_cnt_wlc_t, rxdisassoc)},
+	{"txassocrsp",		OFFSETOF(wl_cnt_wlc_t, txassocrsp)},
+	{"rxassocrsp",		OFFSETOF(wl_cnt_wlc_t, rxassocrsp)},
+	{"txreassocrsp",	OFFSETOF(wl_cnt_wlc_t, txreassocrsp)},
+	{"rxreassocrsp",	OFFSETOF(wl_cnt_wlc_t, rxreassocrsp)},
+	{"txauth",		OFFSETOF(wl_cnt_wlc_t, txauth)},
+	{"rxauth",		OFFSETOF(wl_cnt_wlc_t, rxauth)},
+	{"txdeauth",		OFFSETOF(wl_cnt_wlc_t, txdeauth)},
+	{"rxdeauth",		OFFSETOF(wl_cnt_wlc_t, rxdeauth)},
+	{"txprobereq",		OFFSETOF(wl_cnt_wlc_t, txprobereq)},
+	{"rxprobereq",		OFFSETOF(wl_cnt_wlc_t, rxprobereq)},
+	{"txprobersp",		OFFSETOF(wl_cnt_wlc_t, txprobersp)},
+	{"rxprobersp",		OFFSETOF(wl_cnt_wlc_t, rxprobersp)},
+	{"txaction",		OFFSETOF(wl_cnt_wlc_t, txaction)},
+	{"rxaction",		OFFSETOF(wl_cnt_wlc_t, rxaction)},
+	{"ampdu_wds",		OFFSETOF(wl_cnt_wlc_t, ampdu_wds)},
+	{"txlost",		OFFSETOF(wl_cnt_wlc_t, txlost)},
+	{"txdatamcast",		OFFSETOF(wl_cnt_wlc_t, txdatamcast)},
+	{"txdatabcast",		OFFSETOF(wl_cnt_wlc_t, txdatabcast)},
+	{"psmxwds",		OFFSETOF(wl_cnt_wlc_t, psmxwds)},
+	{"rxback",		OFFSETOF(wl_cnt_wlc_t, rxback)},
+	{"txback",		OFFSETOF(wl_cnt_wlc_t, txback)},
+	{"p2p_tbtt",		OFFSETOF(wl_cnt_wlc_t, p2p_tbtt)},
+	{"p2p_tbtt_miss",		OFFSETOF(wl_cnt_wlc_t, p2p_tbtt_miss)},
+	/* macstats counters */
+	{"txallfrm",		OFFSET_MCST_V30(txallfrm)},
+	{"txrtsfrm",		OFFSET_MCST_V30(txrtsfrm)},
+	{"txctsfrm",		OFFSET_MCST_V30(txctsfrm)},
+	{"txackfrm",		OFFSET_MCST_V30(txackfrm)},
+	{"txdnlfrm",		OFFSET_MCST_V30(txdnlfrm)},
+	{"txbcnfrm",		OFFSET_MCST_V30(txbcnfrm)},
+	{"txfunfl[0]",		OFFSET_MCST_V30(txfunfl[0])},
+	{"txfunfl[1]",		OFFSET_MCST_V30(txfunfl[1])},
+	{"txfunfl[2]",		OFFSET_MCST_V30(txfunfl[2])},
+	{"txfunfl[3]",		OFFSET_MCST_V30(txfunfl[3])},
+	{"txfunfl[4]",		OFFSET_MCST_V30(txfunfl[4])},
+	{"txfunfl[5]",		OFFSET_MCST_V30(txfunfl[5])},
+	{"txampdu",		OFFSET_MCST_V30(txampdu)},
+	{"txmpdu",		OFFSET_MCST_V30(txmpdu)},
+	{"txtplunfl",		OFFSET_MCST_V30(txtplunfl)},
+	{"txphyerror",		OFFSET_MCST_V30(txphyerror)},
+	{"pktengrxducast",	OFFSET_MCST_V30(pktengrxducast)},
+	{"pktengrxdmcast",	OFFSET_MCST_V30(pktengrxdmcast)},
+	{"rxfrmtoolong",	OFFSET_MCST_V30(rxfrmtoolong)},
+	{"rxfrmtooshrt",	OFFSET_MCST_V30(rxfrmtooshrt)},
+	{"rxanyerr",		OFFSET_MCST_V30(rxanyerr)},
+	{"rxbadfcs",		OFFSET_MCST_V30(rxbadfcs)},
+	{"rxbadplcp",		OFFSET_MCST_V30(rxbadplcp)},
+	{"rxcrsglitch",		OFFSET_MCST_V30(rxcrsglitch)},
+	{"rxstrt",		OFFSET_MCST_V30(rxstrt)},
+	{"rxdtucastmbss",	OFFSET_MCST_V30(rxdtucastmbss)},
+	{"rxmgucastmbss",	OFFSET_MCST_V30(rxmgucastmbss)},
+	{"rxctlucast",		OFFSET_MCST_V30(rxctlucast)},
+	{"rxrtsucast",		OFFSET_MCST_V30(rxrtsucast)},
+	{"rxctsucast",		OFFSET_MCST_V30(rxctsucast)},
+	{"rxackucast",		OFFSET_MCST_V30(rxackucast)},
+	{"rxdtocast",		OFFSET_MCST_V30(rxdtocast)},
+	{"rxmgocast",		OFFSET_MCST_V30(rxmgocast)},
+	{"rxctlocast",		OFFSET_MCST_V30(rxctlocast)},
+	{"rxrtsocast",		OFFSET_MCST_V30(rxrtsocast)},
+	{"rxctsocast",		OFFSET_MCST_V30(rxctsocast)},
+	{"rxdtmcast",		OFFSET_MCST_V30(rxdtmcast)},
+	{"rxmgmcast",		OFFSET_MCST_V30(rxmgmcast)},
+	{"rxctlmcast",		OFFSET_MCST_V30(rxctlmcast)},
+	{"rxbeaconmbss",	OFFSET_MCST_V30(rxbeaconmbss)},
+	{"rxdtucastobss",	OFFSET_MCST_V30(rxdtucastobss)},
+	{"rxbeaconobss",	OFFSET_MCST_V30(rxbeaconobss)},
+	{"rxrsptmout",		OFFSET_MCST_V30(rxrsptmout)},
+	{"bcntxcancl",		OFFSET_MCST_V30(bcntxcancl)},
+	{"rxnodelim",		OFFSET_MCST_V30(rxnodelim)},
+	{"rxf0ovfl",		OFFSET_MCST_V30(rxf0ovfl)},
+	{"rxf1ovfl",		OFFSET_MCST_V30(rxf1ovfl)},
+	{"rxhlovfl",		OFFSET_MCST_V30(rxhlovfl)},
+	{"missbcn_dbg",		OFFSET_MCST_V30(missbcn_dbg)},
+	{"pmqovfl",		OFFSET_MCST_V30(pmqovfl)},
+	{"rxcgprqfrm",		OFFSET_MCST_V30(rxcgprqfrm)},
+	{"rxcgprsqovfl",	OFFSET_MCST_V30(rxcgprsqovfl)},
+	{"txcgprsfail",		OFFSET_MCST_V30(txcgprsfail)},
+	{"txcgprssuc",		OFFSET_MCST_V30(txcgprssuc)},
+	{"prs_timeout",		OFFSET_MCST_V30(prs_timeout)},
+	{"txrtsfail",		OFFSET_MCST_V30(txrtsfail)},
+	{"txucast",		OFFSET_MCST_V30(txucast)},
+	{"txinrtstxop",		OFFSET_MCST_V30(txinrtstxop)},
+	{"rxback",		OFFSET_MCST_V30(rxback)},
+	{"txback",		OFFSET_MCST_V30(txback)},
+	{"bphy_rxcrsglitch",	OFFSET_MCST_V30(bphy_rxcrsglitch)},
+	{"rxdrop20s",		OFFSET_MCST_V30(rxdrop20s)},
+	{"rxtoolate",		OFFSET_MCST_V30(rxtoolate)},
+	{"bphy_badplcp",	OFFSET_MCST_V30(bphy_badplcp)},
+	/* reinitreason counter */
+	{"reinitreason_counts[0]",	OFFSET_RIRNS_V30(rsn[0])},
+	{"reinitreason_counts[1]",	OFFSET_RIRNS_V30(rsn[1])},
+	{"reinitreason_counts[2]",	OFFSET_RIRNS_V30(rsn[2])},
+	{"reinitreason_counts[3]",	OFFSET_RIRNS_V30(rsn[3])},
+	{"reinitreason_counts[4]",	OFFSET_RIRNS_V30(rsn[4])},
+	{"reinitreason_counts[5]",	OFFSET_RIRNS_V30(rsn[5])},
+	{"reinitreason_counts[6]",	OFFSET_RIRNS_V30(rsn[6])},
+	{"reinitreason_counts[7]",	OFFSET_RIRNS_V30(rsn[7])},
+	{"reinitreason_counts[8]",	OFFSET_RIRNS_V30(rsn[8])},
+	{"reinitreason_counts[9]",	OFFSET_RIRNS_V30(rsn[9])},
+	{"reinitreason_counts[10]",	OFFSET_RIRNS_V30(rsn[10])},
+	{"reinitreason_counts[11]",	OFFSET_RIRNS_V30(rsn[11])},
+	{"reinitreason_counts[12]",	OFFSET_RIRNS_V30(rsn[12])},
+	{"reinitreason_counts[13]",	OFFSET_RIRNS_V30(rsn[13])},
+	{"reinitreason_counts[14]",	OFFSET_RIRNS_V30(rsn[14])},
+	{"reinitreason_counts[15]",	OFFSET_RIRNS_V30(rsn[15])},
+	{"reinitreason_counts[16]",	OFFSET_RIRNS_V30(rsn[16])},
+	{"reinitreason_counts[17]",	OFFSET_RIRNS_V30(rsn[17])},
+	{"reinitreason_counts[18]",	OFFSET_RIRNS_V30(rsn[18])},
+	{"reinitreason_counts[19]",	OFFSET_RIRNS_V30(rsn[19])},
+	{"reinitreason_counts[20]",	OFFSET_RIRNS_V30(rsn[20])},
+	{"reinitreason_counts[21]",	OFFSET_RIRNS_V30(rsn[21])},
+	{"reinitreason_counts[22]",	OFFSET_RIRNS_V30(rsn[22])},
+	{"reinitreason_counts[23]",	OFFSET_RIRNS_V30(rsn[23])},
+	{"reinitreason_counts[24]",	OFFSET_RIRNS_V30(rsn[24])},
+	{"reinitreason_counts[25]",	OFFSET_RIRNS_V30(rsn[25])},
+	{"reinitreason_counts[26]",	OFFSET_RIRNS_V30(rsn[26])},
+	{"reinitreason_counts[27]",	OFFSET_RIRNS_V30(rsn[27])},
+	{"reinitreason_counts[28]",	OFFSET_RIRNS_V30(rsn[28])},
+	{"reinitreason_counts[29]",	OFFSET_RIRNS_V30(rsn[29])},
+	{"reinitreason_counts[30]",	OFFSET_RIRNS_V30(rsn[30])},
+	{"reinitreason_counts[31]",	OFFSET_RIRNS_V30(rsn[31])},
+	{"reinitreason_counts[32]",	OFFSET_RIRNS_V30(rsn[32])},
+	{"reinitreason_counts[33]",	OFFSET_RIRNS_V30(rsn[33])},
+	{"reinitreason_counts[34]",	OFFSET_RIRNS_V30(rsn[34])},
+	{"reinitreason_counts[35]",	OFFSET_RIRNS_V30(rsn[35])},
+	{"reinitreason_counts[36]",	OFFSET_RIRNS_V30(rsn[36])},
+	{"reinitreason_counts[37]",	OFFSET_RIRNS_V30(rsn[37])},
+	{"reinitreason_counts[38]",	OFFSET_RIRNS_V30(rsn[38])},
+	{"reinitreason_counts[39]",	OFFSET_RIRNS_V30(rsn[39])},
+	{"reinitreason_counts[40]",	OFFSET_RIRNS_V30(rsn[40])},
+	{"reinitreason_counts[41]",	OFFSET_RIRNS_V30(rsn[41])},
+	{"reinitreason_counts[42]",	OFFSET_RIRNS_V30(rsn[42])},
+	{"reinitreason_counts[43]",	OFFSET_RIRNS_V30(rsn[43])},
+	{"reinitreason_counts[44]",	OFFSET_RIRNS_V30(rsn[44])},
+	{"reinitreason_counts[45]",	OFFSET_RIRNS_V30(rsn[45])},
+	{"reinitreason_counts[46]",	OFFSET_RIRNS_V30(rsn[46])},
+	{"reinitreason_counts[47]",	OFFSET_RIRNS_V30(rsn[47])},
+	{"reinitreason_counts[48]",	OFFSET_RIRNS_V30(rsn[48])},
+	{"reinitreason_counts[49]",	OFFSET_RIRNS_V30(rsn[49])},
+	{"reinitreason_counts[50]",	OFFSET_RIRNS_V30(rsn[50])},
+	{"reinitreason_counts[51]",	OFFSET_RIRNS_V30(rsn[51])},
+	{NULL, 0},
+};
+
+
+static ver_to_cntr_offset_info_t ver_to_cntr_offset_info_tbl[] = {
+	{&cntr_offset_info_v6[0],	6},
+	{&cntr_offset_info_v7[0],	7},
+	{&cntr_offset_info_v7[0],	7001},
+	{&cntr_offset_info_v11[0],	11},
+	{&cntr_offset_info_v30[0],	30},
+	{NULL,				0}
+};
+
+static const struct cnt_properties_s cnt_props[] = {
+	{"active_ant", 0},
+	{"ampdu_wds", CAT_AMPDU},
+	{"auto_en", 0},
+	{"avg_snr_per_ant0", 0},
+	{"avg_snr_per_ant1", 0},
+	{"avg_snr_per_ant2", 0},
+	{"bcntxcancl",       CAT_TX | CAT_ERR | CAT_MCAST | CAT_UCODE},
+	{"bphy_badplcp",     CAT_ERR | CAT_UCODE},
+	{"bphy_rxcrsglitch", CAT_RX | CAT_ERR | CAT_UCODE},
+	{"ccmpfmterr",       CAT_SEC | CAT_ERR},
+	{"ccmpreplay",       CAT_SEC | CAT_ERR},
+	{"ccmpundec",        CAT_SEC | CAT_ERR},
+	{"cell_policy",      0},
+	{"cfgrestore",       0},
+	{"chained",          0},
+	{"chainedsz1",       0},
+	{"cso_normal",       0},
+	{"cso_passthrough",  0},
+	{"currchainsz",      0},
+	{"dbgoff46", CAT_UCODE},
+	{"dbgoff47", CAT_UCODE},
+	{"dbgoff48", CAT_UCODE},
+	{"decsuccess",       0},
+	{"dma_hang",         CAT_ERR},
+	{"fourwayfail",      CAT_ERR | CAT_CTRL | CAT_SEC | CAT_ASSOC},
+	{"frmscons",         0},
+	{"m2vmsg",           0},
+	{"macxsusp",         0},
+	{"maxchainsz",       0},
+	{"mboxout",          0},
+	{"missbcn_dbg",      CAT_ERR | CAT_MCAST | CAT_UCODE | CAT_CTRL},
+	{"musnd",            CAT_CTRL},
+	{"mws_antsel_ovr_rx", CAT_RX},
+	{"mws_antsel_ovr_tx", CAT_TX},
+	{"p2p_tbtt",       0},
+	{"p2p_tbtt_miss",  CAT_ERR},
+	{"pciereset",      CAT_ERR},
+	{"phywatch",       CAT_UCODE},
+	{"pktengrxdmcast", CAT_RX | CAT_MCAST | CAT_UCODE},
+	{"pktengrxducast", CAT_RX | CAT_UCAST | CAT_UCODE},
+	{"pmqovfl",        CAT_ERR | CAT_UCODE},
+	{"prs_timeout",    CAT_ERR | CAT_UCODE},
+	{"reinit",     CAT_ERR},
+	{"reinitreason_counts",     CAT_ERR},
+	{"reset",      CAT_ERR},
+	{"rx11mbps",   CAT_RX},
+	{"rx12mbps",   CAT_RX},
+	{"rx18mbps",   CAT_RX},
+	{"rx1mbps",    CAT_RX},
+	{"rx24mbps",   CAT_RX},
+	{"rx2mbps",    CAT_RX},
+	{"rx36mbps",   CAT_RX},
+	{"rx48mbps",   CAT_RX},
+	{"rx54mbps",   CAT_RX},
+	{"rx5mbps5",   CAT_RX},
+	{"rx6mbps",    CAT_RX},
+	{"rx9mbps",    CAT_RX},
+	{"rx_policy",  CAT_RX},
+	{"rxackucast", CAT_RX | CAT_UCAST | CAT_UCODE},
+	{"rxaction",   CAT_RX | CAT_CTRL},
+	{"rxanyerr",   CAT_RX | CAT_UCODE},
+	{"rxassocreq", CAT_RX | CAT_CTRL | CAT_ASSOC},
+	{"rxassocrsp", CAT_RX | CAT_CTRL | CAT_ASSOC},
+	{"rxauth",  CAT_RX | CAT_CTRL | CAT_SEC | CAT_ASSOC},
+	{"rxback",  CAT_RX | CAT_UCODE},
+	{"rxbadcm", CAT_RX | CAT_ERR | CAT_SEC},
+	{"rxbadda", CAT_RX | CAT_CTRL},
+	{"rxbadds", CAT_RX | CAT_CTRL},
+	{"rxbadfcs",     CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxbadplcp",    CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxbadproto",   CAT_RX | CAT_ERR},
+	{"rxbadsrcmac",  CAT_RX | CAT_ERR},
+	{"rxbar",        CAT_RX | CAT_AMPDU | CAT_CTRL},
+	{"rxbeaconmbss", CAT_RX | CAT_UCODE | CAT_CTRL},
+	{"rxbeaconobss", CAT_RX | CAT_UCODE | CAT_CTRL},
+	{"rxbyte",       CAT_RX},
+	{"rxcfrmmcast",  CAT_RX | CAT_MCAST | CAT_CTRL},
+	{"rxcfrmocast",  CAT_RX | CAT_CTRL},
+	{"rxcfrmucast",  CAT_RX | CAT_UCAST | CAT_CTRL},
+	{"rxcgprqfrm",   CAT_RX | CAT_UCODE},
+	{"rxcgprsqovfl", CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxcount",      CAT_RX},
+	{"rxcrc",        CAT_RX},
+	{"rxcrsglitch",  CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxctl",        CAT_RX | CAT_CTRL},
+	{"rxctlmcast",   CAT_RX | CAT_MCAST | CAT_UCODE | CAT_CTRL},
+	{"rxctlocast",      CAT_RX | CAT_UCODE | CAT_CTRL},
+	{"rxctlucast",      CAT_RX | CAT_UCAST | CAT_UCODE | CAT_CTRL},
+	{"rxctsocast",      CAT_RX | CAT_UCODE | CAT_CTRL},
+	{"rxctsucast",      CAT_RX | CAT_UCAST | CAT_UCODE | CAT_CTRL},
+	{"rxdeauth",        CAT_RX | CAT_CTRL | CAT_SEC | CAT_ASSOC},
+	{"rxdfrmmcast",     CAT_RX | CAT_MCAST},
+	{"rxdfrmocast",     CAT_RX},
+	{"rxdfrmucastmbss", CAT_RX | CAT_UCAST},
+	{"rxdfrmucastobss", CAT_RX | CAT_UCAST},
+	{"rxdisassoc",      CAT_RX | CAT_ERR | CAT_ASSOC},
+	{"rxdrop20s",       CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxdtmcast",       CAT_RX | CAT_MCAST | CAT_UCODE},
+	{"rxdtocast",       CAT_RX | CAT_UCODE},
+	{"rxdtucastmbss",   CAT_RX | CAT_UCAST | CAT_UCODE},
+	{"rxdtucastobss",   CAT_RX | CAT_UCAST | CAT_UCODE},
+	{"rxdup",        CAT_RX | CAT_ERR},
+	{"rxerror",      CAT_RX | CAT_ERR},
+	{"rxf0ovfl",     CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxf1ovfl",     CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxf2ovfl",     CAT_RX | CAT_ERR},
+	{"rxfilter",     CAT_RX},
+	{"rxfrag",       CAT_RX},
+	{"rxfragerr",    CAT_RX | CAT_ERR},
+	{"rxframe",      CAT_RX},
+	{"rxfrmtoolong", CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxfrmtooshrt", CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxgiant",      CAT_RX},
+	{"rxhlovfl",     CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxinvmachdr",  CAT_RX},
+	{"rxmfrmmcast",  CAT_RX | CAT_MCAST},
+	{"rxmfrmocast",  CAT_RX},
+	{"rxmfrmucastmbss", CAT_RX | CAT_UCAST},
+	{"rxmgmcast",       CAT_RX | CAT_MCAST | CAT_UCODE | CAT_CTRL},
+	{"rxmgocast",       CAT_RX | CAT_UCODE | CAT_CTRL},
+	{"rxmgucastmbss",   CAT_RX| CAT_UCAST | CAT_UCODE | CAT_CTRL},
+	{"rxmpdu_mu",    CAT_RX},
+	{"rxmpdu_sgi",   CAT_RX},
+	{"rxmpdu_stbc",  CAT_RX},
+	{"rxmulti",      CAT_RX | CAT_MCAST},
+	{"rxnack",       CAT_RX | CAT_ERR},
+	{"rxnobuf",      CAT_RX | CAT_ERR},
+	{"rxnodelim",    CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxnondata",    CAT_RX | CAT_ERR | CAT_CTRL},
+	{"rxnoscb",      CAT_RX | CAT_ERR},
+	{"rxnull",       CAT_RX | CAT_ERR},
+	{"rxprobereq",   CAT_RX | CAT_CTRL},
+	{"rxprobersp",   CAT_RX | CAT_CTRL},
+	{"rxpspoll",     CAT_RX | CAT_CTRL},
+	{"rxqosnull",    CAT_RX},
+	{"rxreassocreq", CAT_RX | CAT_CTRL | CAT_ASSOC},
+	{"rxreassocrsp", CAT_RX | CAT_CTRL | CAT_ASSOC},
+	{"rxrsptmout",   CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxrtry",       CAT_RX | CAT_ERR},
+	{"rxrtsocast",   CAT_RX | CAT_UCODE | CAT_CTRL},
+	{"rxrtsucast",   CAT_RX | CAT_UCAST | CAT_UCODE | CAT_CTRL},
+	{"rxrunt",       CAT_RX | CAT_ERR},
+	{"rxstrt",       CAT_RX | CAT_UCODE},
+	{"rxtoolate",    CAT_RX | CAT_ERR | CAT_UCODE},
+	{"rxuflo",    CAT_RX | CAT_ERR},
+	{"rxundec",      CAT_RX | CAT_SEC},
+	{"sfb2v",        0},
+	{"swap_alivecheck0",   0},
+	{"swap_alivecheck1",   0},
+	{"swap_ge_rxcount0",   CAT_RX},
+	{"swap_ge_rxcount1",   CAT_RX},
+	{"swap_ge_snrthresh0", 0},
+	{"swap_ge_snrthresh1", 0},
+	{"swap_snrdrop0", 0},
+	{"swap_snrdrop1", 0},
+	{"swap_timer0", 0},
+	{"swap_timer1", 0},
+	{"swap_trig_event_id", 0},
+	{"swap_txfail0", CAT_TX | CAT_ERR},
+	{"swap_txfail1", CAT_TX | CAT_ERR},
+	{"tbtt", 0},
+	{"tkipcntrmsr", CAT_SEC},
+	{"tkipicverr", CAT_SEC},
+	{"tkipmicfaill", CAT_ERR | CAT_SEC},
+	{"tkipreplay", CAT_ERR | CAT_SEC},
+	{"tx_active_ant", CAT_TX},
+	{"tx_auto_en", CAT_TX},
+	{"tx_policy", CAT_TX},
+	{"txackfrm", CAT_TX | CAT_UCAST | CAT_UCODE},
+	{"txaction", CAT_TX | CAT_CTRL},
+	{"txallfrm", CAT_TX | CAT_UCODE},
+	{"txampdu", CAT_TX | CAT_AMPDU | CAT_UCODE},
+	{"txassocreq", CAT_TX | CAT_CTRL | CAT_ASSOC},
+	{"txassocrsp", CAT_TX | CAT_CTRL | CAT_ASSOC},
+	{"txauth", CAT_TX | CAT_CTRL | CAT_SEC | CAT_ASSOC},
+	{"txback", CAT_TX | CAT_UCODE},
+	{"txbar", CAT_TX | CAT_AMPDU},
+	{"txbcnfrm", CAT_TX | CAT_MCAST | CAT_UCODE | CAT_CTRL},
+	{"txbyte", CAT_TX},
+	{"txcgprsfail", CAT_TX | CAT_ERR | CAT_UCODE},
+	{"txcgprssuc", CAT_TX | CAT_UCODE},
+	{"txchanrej", CAT_TX | CAT_ERR},
+	{"txchit", CAT_TX},
+	{"txcmiss", CAT_TX | CAT_ERR},
+	{"txctsfrm", CAT_TX | CAT_UCODE | CAT_CTRL},
+	{"txdatabcast", CAT_TX | CAT_MCAST},
+	{"txdatamcast", CAT_TX | CAT_MCAST},
+	{"txdeauth", CAT_TX | CAT_ERR | CAT_CTRL | CAT_SEC | CAT_ASSOC},
+	{"txdisassoc", CAT_TX | CAT_ERR | CAT_CTRL | CAT_ASSOC},
+	{"txdmawar", CAT_TX | CAT_ERR},
+	{"txdnlfrm", CAT_TX | CAT_UCODE},
+	{"txerror", CAT_TX | CAT_ERR},
+	{"txfail", CAT_TX | CAT_ERR},
+	{"txfbw", CAT_TX},
+	{"txfrag", CAT_TX},
+	{"txfrag", CAT_TX},
+	{"txframe", CAT_TX},
+	{"txfrmsnt", CAT_TX},
+	{"txfunfl", CAT_TX | CAT_UCODE},
+	{"txinrtstxop", CAT_TX | CAT_UCODE},
+	{"txlost", CAT_TX | CAT_ERR},
+	{"txmpdu", CAT_TX | CAT_UCODE},
+	{"txmpdu_sgi", CAT_TX},
+	{"txmpdu_stbc", CAT_TX},
+	{"txmulti", CAT_TX | CAT_MCAST},
+	{"txnack", CAT_TX | CAT_ERR | CAT_UCAST},
+	{"txnoack", CAT_TX | CAT_ERR | CAT_UCAST},
+	{"txnoassoc", CAT_TX | CAT_ERR | CAT_ASSOC},
+	{"txnobuf", CAT_TX | CAT_ERR},
+	{"txnocts", CAT_TX},
+	{"txnull", CAT_TX},
+	{"txper_rts", CAT_TX | CAT_ERR | CAT_CTRL},
+	{"txper_ucastdt", CAT_TX | CAT_ERR | CAT_UCAST},
+	{"txphycrs", CAT_TX},
+	{"txphyerr", CAT_TX | CAT_ERR},
+	{"txphyerror", CAT_TX | CAT_ERR | CAT_UCODE},
+	{"txprobereq", CAT_TX | CAT_CTRL | CAT_ASSOC},
+	{"txprobersp", CAT_TX | CAT_CTRL | CAT_ASSOC},
+	{"txprshort", CAT_TX},
+	{"txpspoll", CAT_TX | CAT_CTRL},
+	{"txqosnull", CAT_TX | CAT_CTRL},
+	{"txreassocreq", CAT_TX | CAT_CTRL | CAT_ASSOC},
+	{"txreassocrsp", CAT_TX | CAT_CTRL | CAT_ASSOC},
+	{"txretrans", CAT_TX | CAT_ERR},
+	{"txretrie", CAT_TX | CAT_ERR | CAT_UCAST},
+	{"txretry", CAT_TX | CAT_ERR | CAT_UCAST},
+	{"txrts", CAT_TX | CAT_CTRL},
+	{"txrtsfail", CAT_TX | CAT_ERR | CAT_UCODE | CAT_CTRL},
+	{"txrtsfrm", CAT_TX | CAT_UCODE | CAT_CTRL},
+	{"txserr", CAT_TX | CAT_ERR},
+	{"txsfovfl", CAT_TX | CAT_ERR},
+	{"txtplunfl", CAT_TX | CAT_UCODE},
+	{"txucast", CAT_TX | CAT_UCAST | CAT_UCODE},
+	{"unchained", 0},
+	{"v2mmsg",    0},
+	{"wepicverr", CAT_ERR | CAT_SEC},
+	{"wepundec", CAT_SEC},
+	{NULL, 0}
+};
+
+static bool at_start_of_line; /**< prevents printing of empty lines */
+
+static int
+cntr_ver_to_tbl_info(uint8 counter_ver, counter_offset_info_t **cntr_offset_info_tbl)
+{
+	uint32 index = 0;
+
+	while (ver_to_cntr_offset_info_tbl[index].offset_info_tbl != NULL) {
+		if (ver_to_cntr_offset_info_tbl[index].cntr_ver == counter_ver) {
+			*cntr_offset_info_tbl = ver_to_cntr_offset_info_tbl[index].offset_info_tbl;
+			return BCME_OK;
+		}
+		index++;
+	}
+
+	*cntr_offset_info_tbl = NULL;
+	return BCME_ERROR;
+}
+
+/* Returns the offset of the counter in respective version of counters structure */
+/* Returns 0  - Found the offset of the counter */
+/* Returns -1 - Counter name passed do not match to any counter name */
+int
+get_counter_offset(char *name, uint32 *offset, uint8 counter_ver)
+{
+	uint32 index = 0;
+	counter_offset_info_t *offset_info_tbl = NULL;
+
+	if (cntr_ver_to_tbl_info(counter_ver, &offset_info_tbl) != BCME_OK) {
+		fprintf(stderr, "Unsupported counter ver %d\n", counter_ver);
+		return BCME_ERROR;
+	}
+
+	while (offset_info_tbl[index].name != NULL) {
+		if (!strcmp(offset_info_tbl[index].name, name)) {
+			*offset = htod32(offset_info_tbl[index].offset);
+			return BCME_OK;
+		}
+		index++;
+	}
+
+	fprintf(stderr, "Invalid counter name %s\n", name);
+	return BCME_ERROR;
+}
+
+int
+print_counter_help(uint8 counter_ver)
+{
+	uint32 index = 0;
+	counter_offset_info_t *offset_info_tbl = NULL;
+
+	if (cntr_ver_to_tbl_info(counter_ver, &offset_info_tbl) != BCME_OK) {
+		fprintf(stderr, "Unsupported counter ver %d\n", counter_ver);
+		return BCME_ERROR;
+	}
+
+	while (offset_info_tbl[index].name != NULL) {
+		if (index % 5 == 0) {
+			printf("\n");
+		}
+		printf("%s ", offset_info_tbl[index].name);
+		index++;
+	}
+	return BCME_OK;
+}
+
+int
+wl_subcounters(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	void *ptr;
+	char *endptr;
+	uint8 subcntdata[(MAX_SUBCOUNTER_SUPPORTED * sizeof(uint32)) +
+		OFFSETOF(wl_subcnt_info_t, data)];
+	int32 cntr_ver = -1;
+	uint32 cntr_num = 0;
+	uint32 req_len = 0;
+	uint32 arg_index = 1;	/* 0th arg is command_name */
+	wl_subcnt_info_t *subcntinfo;
+
+	memset(subcntdata, 0, sizeof(subcntdata));
+
+	if (argv[arg_index] != NULL) {
+		cntr_ver = strtoul(argv[arg_index], &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "Invalid cntr ver %s\n", argv[arg_index]);
+			return BCME_BADARG;
+		}
+		arg_index++;
+	}
+
+	subcntinfo = (wl_subcnt_info_t *)subcntdata;
+	while (argv[arg_index] != NULL)	{
+		if (cntr_num >= MAX_SUBCOUNTER_SUPPORTED) {
+			fprintf(stderr, "Max counters supported: %d\n", MAX_SUBCOUNTER_SUPPORTED);
+			return BCME_BADARG;
+		}
+
+		if (get_counter_offset(argv[arg_index],
+				&subcntinfo->data[cntr_num], cntr_ver)) {
+			return BCME_BADARG;
+		}
+		arg_index++;
+		cntr_num++;
+	}
+
+	if ((cntr_ver != -1) && (cntr_num == 0)) {
+		print_counter_help(cntr_ver);
+		return BCME_OK;
+	}
+
+	req_len = OFFSETOF(wl_subcnt_info_t, data) + (cntr_num * sizeof(subcntinfo->data[0]));
+	subcntinfo->version = htod16(WL_SUBCNTR_IOV_VER);
+	subcntinfo->counters_version = htod16(cntr_ver);
+	subcntinfo->num_subcounters = htod16(cntr_num);
+	subcntinfo->length = htod16(req_len);
+
+	if ((err = wlu_var_getbuf_minimal(wl, cmd->name, subcntdata, req_len, &ptr))) {
+		return (err);
+	}
+
+	subcntinfo = ptr;
+	subcntinfo->version = dtoh16(subcntinfo->version);
+	subcntinfo->counters_version = dtoh16(subcntinfo->counters_version);
+	subcntinfo->num_subcounters = dtoh16(subcntinfo->num_subcounters);
+	subcntinfo->length = dtoh16(subcntinfo->length);
+
+	if ((cntr_ver == -1) || (cntr_num == 0) || (subcntinfo->num_subcounters == 0)) {
+		printf("FW counter Version %d\n", subcntinfo->counters_version);
+		return BCME_OK;
+	}
+
+	if ((subcntinfo->num_subcounters > MAX_SUBCOUNTER_SUPPORTED) ||
+			(subcntinfo->length != req_len) ||
+			(subcntinfo->length != OFFSETOF(wl_subcnt_info_t, data) +
+			(subcntinfo->num_subcounters * sizeof(subcntinfo->data[0])))) {
+		fprintf(stderr,
+			"Mismatch App:FW cntr_ver %d:%d iov_ver %d:%d num_cntr %d:%d len %d:%d\n",
+			cntr_ver, subcntinfo->counters_version,
+			WL_SUBCNTR_IOV_VER, subcntinfo->version, cntr_num,
+			subcntinfo->num_subcounters, req_len, subcntinfo->length);
+		return BCME_BADARG;
+	}
+
+	for (cntr_num = 0; cntr_num < subcntinfo->num_subcounters; cntr_num++) {
+		/* Print max 5 counters value in a single row */
+		if (cntr_num % 5 == 0)
+			printf("\n");
+		printf("%s %d ", argv[cntr_num + 2],
+			dtoh32(subcntinfo->data[cntr_num]));
+	}
+	printf("\n");
+
+	return 0;
+}
+
+/***************************************************************************************************
+ * The prcnt_*() functions print counter values. The purpose of the functions is to facilitate
+ * filtering of the counter values, e.g. when the user only wants to see non-zero values.
+ */
+
+/** Must be called before any of the other prcnt_*() functions */
+void prcnt_init()
+{
+	at_start_of_line = TRUE;
+}
+
+/**
+ * Returns TRUE if a counter value is allowed by the filters to be printed.
+ * @param cnt_filters   Specifies the filters to be applied
+ * @param cntname        The name of the variable in the 'cnt' structure
+ */
+static bool prcnt_filter1(struct cnt_filters_s *cnt_filters, char *cntname)
+{
+	if (cnt_filters->filter != 0) {
+		const struct cnt_properties_s *cnt = &cnt_props[0];
+		while (cnt->name != NULL) {
+			if (!strcmp(cntname, cnt->name)) {
+				if ((cnt_filters->filter & cnt->categories) !=
+					cnt_filters->filter) {
+					// returns FALSE in non inverted case
+					return cnt_filters->invert_selection;
+				}
+				break;
+			}
+			cnt++;
+		}
+		if (cnt->name == NULL)
+			fprintf(stderr, "could not find this entry... %s\n", cntname);
+	}
+
+	return !cnt_filters->invert_selection;
+}
+
+/**
+ * Returns TRUE if a counter value is allowed by the filters to be printed.
+ * @param cnt_filters   Specifies the filters to be applied
+ * @param cntname       The name of the variable in the 'cnt' structure
+ * @param cntvalue      The value of the counter
+ */
+static bool prcnt_filter(struct cnt_filters_s *cnt_filters, char *cntname, uint32 cntvalue)
+{
+	if (cnt_filters->nonzero == TRUE && cntvalue == 0)
+		return FALSE;
+
+	return prcnt_filter1(cnt_filters, cntname);
+}
+
+/**
+ * For non-legacy mode (so user specified filter options): prevents empty lines when printing
+ * counter values. For legacy mode: empty lines are preserved for backwards compatibility of tools
+ * that interpret wl utility output.
+ * @param cnt_filters  User specified filters to apply
+ * @param ppbuf        Output buffer for the sprintf
+ */
+void prcnt_prnl1(struct cnt_filters_s *cnt_filters)
+{
+	if (at_start_of_line == FALSE || cnt_filters->filters_active == FALSE) {
+		printf("\n");
+		at_start_of_line = TRUE;
+	}
+}
+
+static int wl_counters_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
+{
+	int err = BCME_OK;
+	wl_cnt_cbfn_info_t *cbfn_info = ctx;
+	uint i;
+	struct cnt_filters_s *p_cnt_filters = &cbfn_info->cnt_filters;
+
+	PRINIT(); /* initializes printing of counter values */
+
+	switch (type) {
+		case WL_CNT_XTLV_WLC_RINIT_RSN: {
+			/* reinit reason counters */
+			reinit_rsns_t *cnt = (reinit_rsns_t *)data;
+			uint32 *val = cnt->rsn;
+			uint maxoffset = len/sizeof(uint32);
+
+			if (len > sizeof(reinit_rsns_t)) {
+				printf("type %d: cntbuf length too long! %d > %d\n"
+					"May need to use up-to-date wl utility.\n",
+					type, len, (int)sizeof(reinit_rsns_t));
+			}
+
+			if (cnt->rsn[0] != INVALID_CNT_VAL) {
+				PRSTR(reinitreason_counts, "reinitreason_counts: ");
+				for (i = 0; i < WL_REINIT_RC_LAST && i < maxoffset; i++) {
+					PRVAL_FMTSTR2(reinitreason_counts, "%d(%d) ", i, val[i]);
+				}
+				PRNL1();
+			}
+			break;
+		}
+		case WL_CNT_XTLV_WLC: {
+			/* WLC layer counters */
+			wl_cnt_wlc_t *cnt = (wl_cnt_wlc_t *)data;
+
+			if (len > sizeof(wl_cnt_wlc_t)) {
+				printf("type %d: cntbuf length too long! %d > %d\n"
+					"May need to use up-to-date wl utility.\n",
+					type, len, (int)sizeof(wl_cnt_wlc_t));
+			}
+			PRVALSF(reinit);
+
+			/* Display old reinitreason counts */
+			if (cnt->reinitreason[0] != INVALID_CNT_VAL) {
+				PRSTR(reinitreason_counts, "reinitreason_counts: ");
+				for (i = 0; i < NREINITREASONCOUNT; i++)
+					PRVAL_FMTSTR2(reinitreason_counts, "%d(%d) ",
+						i, cnt->reinitreason[i]);
+				PRNL1();
+			}
+
+			PRVALSF(reset); PRVALSF(pciereset); PRVALSF(cfgrestore);
+			PRVALSF(dma_hang); PRVALSF(ampdu_wds); PRNL1();
+
+			PRVALSF(txframe); PRVALSF(txbyte); PRVALSF(txretrans); PRVALSF(txlost);
+			PRVALSF(txfail); PRVALSF(txchanrej);
+			if (cbfn_info->cntr_ver ==  WL_CNT_VERSION_7001) PRVALSF_RENAME(phywatchdog,rxbcnlossmbss);
+			PRNL1();
+			PRVALSF(txdatamcast); PRVALSF(txdatabcast); PRNL1();
+			PRVALSF(tbtt); PRVALSF(p2p_tbtt); PRVALSF(p2p_tbtt_miss); PRNL1();
+			PRVALSF(rxframe); PRVALSF(rxbyte); PRVALSF(rxerror); PRNL1();
+			PRVALSF(txprshort); PRVALSF(txdmawar); PRVALSF(txnobuf); PRVALSF(txnoassoc);
+			PRVALSF(txchit); PRVALSF(txcmiss); PRNL1();
+			PRVALSF(txserr); PRVALSF(txphyerr); PRVALSF(txphycrs); PRVALSF(txerror);
+			PRNL1();
+			PRVALSF_RENAME(txfrag, d11_txfrag); PRVALSF_RENAME(txmulti, d11_txmulti);
+			PRVALSF_RENAME(txretry, d11_txretry);
+			PRVALSF_RENAME(txretrie, d11_txretrie); PRNL1();
+			PRVALSF_RENAME(txrts, d11_txrts); PRVALSF_RENAME(txnocts, d11_txnocts);
+			PRVALSF_RENAME(txnoack, d11_txnoack);
+			PRVALSF_RENAME(txfrmsnt, d11_txfrmsnt); PRNL1();
+
+			PRVALSF(rxcrc); PRVALSF(rxnobuf); PRVALSF(rxnondata); PRVALSF(rxbadds);
+			PRVALSF(rxbadcm); PRVALSF(rxdup); PRVALSF(rxfragerr); PRNL1();
+
+			PRVALSF(rxrunt); PRVALSF(rxgiant); PRVALSF(rxnoscb); PRVALSF(rxbadproto);
+			PRVALSF(rxbadsrcmac); PRVALSF(rxrtry); PRNL1();
+			PRVALSF_RENAME(rxfrag, d11_rxfrag); PRVALSF_RENAME(rxmulti, d11_rxmulti);
+			PRVALSF_RENAME(rxundec, d11_rxundec); PRNL1();
+			PRVALSF(rxctl); PRVALSF(rxbadda); PRVALSF(rxfilter);
+			if (cnt->rxuflo[0] != INVALID_CNT_VAL) {
+				PRSTR(rxuflo, "rxuflo: ");
+				for (i = 0; i < NFIFO; i++)
+					PRVAL_FMTSTR1(rxuflo, "%u ", cnt->rxuflo[i]);
+				PRNL1();
+			}
+
+			/* WPA2 counters */
+			PRNL1();
+			PRVALSF(tkipmicfaill); PRVALSF(tkipicverr); PRVALSF(tkipcntrmsr); PRNL1();
+			PRVALSF(tkipreplay); PRVALSF(ccmpfmterr); PRVALSF(ccmpreplay); PRNL1();
+			PRVALSF(ccmpundec); PRVALSF(fourwayfail); PRVALSF(wepundec); PRNL1();
+			PRVALSF(wepicverr); PRVALSF(decsuccess); PRVALSF(rxundec); PRNL1();
+			PRNL1();
+
+			/* per-rate receive counters */
+			PRVALSF(rx1mbps); PRVALSF(rx2mbps); PRVALSF(rx5mbps5);
+			PRVALSF(rx11mbps); PRNL1();
+			PRVALSF(rx6mbps); PRVALSF(rx9mbps); PRVALSF(rx12mbps);
+			PRVALSF(rx18mbps); PRNL1();
+			PRVALSF(rx24mbps); PRVALSF(rx36mbps); PRVALSF(rx48mbps);
+			PRVALSF(rx54mbps); PRNL1();
+
+			PRVALSF(txmpdu_sgi); PRVALSF(rxmpdu_sgi); PRVALSF(txmpdu_stbc);
+			PRVALSF(rxmpdu_stbc); PRVALSF(rxmpdu_mu); PRNL1();
+
+			PRVALSF(cso_normal); PRVALSF(cso_passthrough);
+			PRNL1();
+			PRVALSF(chained); PRVALSF(chainedsz1); PRVALSF(unchained);
+			PRVALSF(maxchainsz); PRVALSF(currchainsz); PRNL1();
+			PRNL1();
+
+			/* detailed amangement and control frame counters */
+			PRVALSF(txbar); PRVALSF(txpspoll); PRVALSF(rxbar);
+			PRVALSF(rxpspoll); PRNL1();
+			PRVALSF(txnull); PRVALSF(txqosnull); PRVALSF(rxnull);
+			PRVALSF(rxqosnull); PRNL1();
+			PRVALSF(txassocreq); PRVALSF(txreassocreq); PRVALSF(txdisassoc);
+			PRVALSF(txassocrsp); PRVALSF(txreassocrsp); PRNL1();
+			PRVALSF(txauth); PRVALSF(txdeauth); PRVALSF(txprobereq);
+			PRVALSF(txprobersp); PRVALSF(txaction); PRNL1();
+			PRVALSF(rxassocreq); PRVALSF(rxreassocreq); PRVALSF(rxdisassoc);
+			PRVALSF(rxassocrsp); PRVALSF(rxreassocrsp); PRNL1();
+			PRVALSF(rxauth); PRVALSF(rxdeauth); PRVALSF(rxprobereq);
+			PRVALSF(rxprobersp); PRVALSF(rxaction); PRNL1();
+			break;
+		}
+		case WL_CNT_XTLV_CNTV_LE10_UCODE: {
+			wl_cnt_v_le10_mcst_t *cnt = (wl_cnt_v_le10_mcst_t *)data;
+			if (len != sizeof(wl_cnt_v_le10_mcst_t)) {
+				printf("type %d: cnt struct length mismatch! %d != %d\n",
+					type, len, (int)sizeof(wl_cnt_v_le10_mcst_t));
+			}
+
+			/* UCODE SHM counters */
+			PRVAL(txallfrm); PRVAL(txbcnfrm); PRVAL(txrtsfrm);
+			PRVAL(txctsfrm); PRVAL(txackfrm); PRVAL(txback);
+			PRVAL(txdnlfrm); PRNL1();
+			PRSTR(txfunfl, "txfunfl: ");
+			for (i = 0; i < NFIFO; i++) {
+				PRVAL_FMTSTR1(txfunfl, "%u ", cnt->txfunfl[i]);
+			}
+			PRVAL(txtplunfl); PRVAL(txphyerror); PRNL1();
+			PRNL1();
+
+			PRVAL(rxstrt); PRVAL(rxbadplcp); PRVAL(rxcrsglitch);
+			PRVAL(rxtoolate); PRNL1();
+			PRVAL(rxdrop20s); PRVAL(rxrsptmout);  PRNL1();
+			PRVAL(rxbadfcs); PRVAL(rxfrmtoolong); PRVAL(rxfrmtooshrt);
+			PRVAL(rxinvmachdr); PRNL1();
+			PRVAL(rxf0ovfl); PRVAL(rxf1ovfl); PRVAL(rxf2ovfl);
+			PRVAL(txsfovfl); PRVAL(pmqovfl); PRNL1();
+			PRVAL(rxcfrmucast); PRVAL(rxrtsucast); PRVAL(rxctsucast);
+			PRVAL(rxackucast); PRVAL(rxback); PRNL1();
+			PRVAL(rxbeaconmbss); PRVAL(rxdfrmucastmbss);
+			PRVAL(rxmfrmucastmbss); PRNL1();
+			PRVAL(rxbeaconobss); PRVAL(rxdfrmucastobss);
+			PRVAL(rxdfrmocast); PRVAL(rxmfrmocast); PRNL1();
+			PRVAL(rxcfrmocast); PRVAL(rxrtsocast); PRVAL(rxctsocast); PRNL1();
+			PRVAL(rxcfrmmcast); PRVAL(rxdfrmmcast); PRVAL(rxmfrmmcast); PRNL1();
+			PRNL1();
+
+			PRVAL(rxcgprqfrm); PRVAL(rxcgprsqovfl);
+			PRVAL(txcgprsfail); PRVAL(txcgprssuc); PRVAL(prs_timeout); PRNL1();
+			PRVAL(pktengrxducast); PRVAL(pktengrxdmcast);
+			PRVAL(bcntxcancl); PRNL1();
+			PRVAL(txfbw); PRVAL(rxnack); PRVAL(frmscons);
+			PRVAL(txnack); PRNL1();
+			PRNL1();
+			break;
+		}
+		case WL_CNT_XTLV_LT40_UCODE_V1: {
+			wl_cnt_lt40mcst_v1_t *cnt = (wl_cnt_lt40mcst_v1_t *)data;
+			if (len != sizeof(wl_cnt_lt40mcst_v1_t)) {
+				printf("type %d: cnt struct length mismatch! %d != %d\n",
+					type, len, (int)sizeof(wl_cnt_lt40mcst_v1_t));
+			}
+			PRCNT_MACSTAT_TX_VER_GE11;
+			/* rx start and those that do not end well */
+			PRVAL(rxstrt); PRVAL(rxbadplcp); PRVAL(rxcrsglitch);
+			PRVAL(rxtoolate); PRVAL(rxnodelim); PRNL1();
+			PRVAL(bphy_badplcp); PRVAL(bphy_rxcrsglitch); PRNL1();
+			PRVAL(rxbadfcs); PRVAL(rxfrmtoolong); PRVAL(rxfrmtooshrt);
+			PRVAL(rxanyerr); PRNL1();
+			PRVAL(rxf0ovfl); PRVAL(pmqovfl); PRNL1();
+			PRCNT_MACSTAT_RX_VER_GE11;
+			PRNL1();
+			PRVAL(dbgoff46); PRVAL(dbgoff47);
+			PRVAL(dbgoff48); PRVAL(phywatch); PRNL1();
+			PRNL1();
+			break;
+		}
+		case WL_CNT_XTLV_GE40_UCODE_V1: {
+			wl_cnt_ge40mcst_v1_t *cnt = (wl_cnt_ge40mcst_v1_t *)data;
+			if (len != sizeof(wl_cnt_ge40mcst_v1_t)) {
+				printf("type %d: cnt struct length mismatch! %d != %d\n",
+					type, len, (int)sizeof(wl_cnt_ge40mcst_v1_t));
+			}
+			PRCNT_MACSTAT_TX_VER_GE11;
+			/* rx start and those that do not end well */
+			PRVAL(rxstrt); PRVAL(rxbadplcp); PRVAL(rxcrsglitch);
+			PRVAL(rxtoolate); PRVAL(rxnodelim); PRNL1();
+			PRVAL(rxdrop20s); PRVAL(bphy_badplcp); PRVAL(bphy_rxcrsglitch); PRNL1();
+			PRVAL(rxbadfcs); PRVAL(rxfrmtoolong); PRVAL(rxfrmtooshrt);
+			PRVAL(rxanyerr); PRNL1();
+			PRVAL(rxf0ovfl); PRVAL(rxf1ovfl); PRVAL(rxhlovfl); PRVAL(pmqovfl); PRNL1();
+			PRCNT_MACSTAT_RX_VER_GE11;
+			PRVAL(missbcn_dbg); PRNL1();
+			PRNL1();
+			break;
+		}
+		case WL_CNT_XTLV_GE64_UCODEX_V1: {
+			wl_cnt_ge64mcxst_v1_t *cnt = (wl_cnt_ge64mcxst_v1_t *)data;
+			if (len != sizeof(wl_cnt_ge64mcxst_v1_t)) {
+				printf("type %d: cnt struct length mismatch! %d != %d\n",
+					type, len, (int)sizeof(wl_cnt_ge64mcxst_v1_t));
+			}
+			PRVAL(macxsusp); PRVAL(m2vmsg); PRVAL(v2mmsg); PRNL1();
+			PRVAL(mboxout); PRVAL(musnd); PRVAL(sfb2v);
+			PRNL1();
+			break;
+		}
+		default:
+			printf("Unknown counters type %d!! You may try updating wl utility.\n",
+				type);
+			break;
+	}
+
+	return err;
+}
+
+int
+wl_counters(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_cnt_info_t *cntinfo;
+	int err;
+	void *ptr;
+	uint16 ver;
+	uint8 *cntdata;
+	uint32 corerev = 0;
+	wl_cnt_cbfn_info_t cbfn_info;
+#ifdef WL_NAN
+	wl_nan_ioc_t*nanioc;
+	uint16 iocsz = sizeof(wl_nan_ioc_t) + WL_NAN_IOC_BUFSZ;
+#endif /* WL_NAN */
+
+	memset(&cbfn_info, 0, sizeof(cbfn_info));
+	while (*++argv != NULL) {
+		cbfn_info.cnt_filters.filters_active = TRUE;
+		if (!strcmp(*argv, "--nz"))
+			cbfn_info.cnt_filters.nonzero = TRUE;
+		else if (!strcmp(*argv, "--invert")) /* inverts entire selection */
+			cbfn_info.cnt_filters.invert_selection = TRUE;
+		else if (!strcmp(*argv, "--rx"))
+			cbfn_info.cnt_filters.filter |= CAT_RX;
+		else if (!strcmp(*argv, "--tx"))
+			cbfn_info.cnt_filters.filter |= CAT_TX;
+		else if (!strcmp(*argv, "--err"))
+			cbfn_info.cnt_filters.filter |= CAT_ERR;
+		else if (!strcmp(*argv, "--ucast"))
+			cbfn_info.cnt_filters.filter |= CAT_UCAST;
+		else if (!strcmp(*argv, "--mcast")) /* includes broadcast frames */
+			cbfn_info.cnt_filters.filter |= CAT_MCAST;
+		else if (!strcmp(*argv, "--ampdu"))
+			cbfn_info.cnt_filters.filter |= CAT_AMPDU;
+		else if (!strcmp(*argv, "--ucode"))
+			cbfn_info.cnt_filters.filter |= CAT_UCODE;
+		else if (!strcmp(*argv, "--ctrl"))
+			cbfn_info.cnt_filters.filter |= CAT_CTRL;
+		else if (!strcmp(*argv, "--sec"))
+			cbfn_info.cnt_filters.filter |= CAT_SEC;
+		else if (!strcmp(*argv, "--assoc"))
+			cbfn_info.cnt_filters.filter |= CAT_ASSOC;
+		else {
+			fprintf(stderr, "unrecognized option %s\n", *argv);
+			err = BCME_ERROR;
+			goto exit;
+		}
+	}
+
+	if ((err = wlu_var_getbuf_med (wl, cmd->name, NULL, 0, &ptr))) {
+		goto exit;
+	}
+
+	cntinfo = ptr;
+	cntinfo->version = dtoh16(cntinfo->version);
+	cntinfo->datalen = dtoh16(cntinfo->datalen);
+	CHK_CNTBUF_DATALEN(cntinfo, WLC_IOCTL_MEDLEN);
+	ver = cntinfo->version;
+	if (ver > WL_CNT_T_VERSION && ver != WL_CNT_VERSION_7001) {
+		printf("\tIncorrect version of counters struct: expected %d; got %d\n",
+		       WL_CNT_T_VERSION, ver);
+		err = BCME_ERROR;
+		goto exit;
+	}
+
+	printf("counters_version %d\n", ver);
+
+
+	if (ver == WL_CNT_VERSION_11) {
+		wlc_rev_info_t revinfo;
+		memset(&revinfo, 0, sizeof(revinfo));
+		err = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+		if (err) {
+			printf("%s: WLC_GET_REVINFO failed %d\n", __FUNCTION__, err);
+			goto exit;
+		}
+		corerev = dtoh32(revinfo.corerev);
+	}
+	err = wl_cntbuf_to_xtlv_format(NULL, cntinfo, WLC_IOCTL_MEDLEN, corerev);
+
+	if (err) {
+		printf("%s: wl_cntbuf_to_xtlv_format failed %d\n", __FUNCTION__, err);
+		goto exit;
+	}
+
+	/* Now counter buffer of all versions is translated to xtlv format */
+	printf("datalen %d\n", cntinfo->datalen);
+
+	cntdata = (uint8 *)malloc(cntinfo->datalen);
+	if (cntdata == NULL) {
+		err = BCME_NOMEM;
+		printf("malloc fail!\n");
+		goto exit;
+	};
+
+	memcpy(cntdata, cntinfo->data, cntinfo->datalen);
+
+	cbfn_info.cntr_ver = ver;
+	if ((err = bcm_unpack_xtlv_buf(&cbfn_info, cntdata, cntinfo->datalen,
+		BCM_XTLV_OPTION_ALIGN32, wl_counters_cbfn))) {
+		printf("error %d\n", err);
+	}
+	free(cntdata);
+
+exit:
+#ifdef WL_NAN
+	/*	alloc mem for ioctl headr +  tlv data  */
+	nanioc = calloc(1, iocsz);
+	if (nanioc == NULL)
+		return BCME_NOMEM;
+
+	/* make up nan cmd ioctl header */
+	nanioc->version = htod16(WL_NAN_IOCTL_VERSION);
+	nanioc->id = WL_NAN_CMD_CFG_COUNT;
+	nanioc->len = WL_NAN_IOC_BUFSZ;
+
+	wl_nan_do_get_ioctl(wl, nanioc, iocsz);
+	free(nanioc);
+#endif /* WL_NAN */
+
+	return err;
+}
+
+int
+wl_if_counters(void *wl, cmd_t *cmd, char **argv)
+{
+	char *statsbuf;
+	wl_if_stats_t *cnt;
+	int err;
+	void *ptr;
+	struct cnt_filters_s cnt_filters;
+	struct cnt_filters_s *p_cnt_filters = &cnt_filters;
+	UNUSED_PARAMETER(argv);
+
+	memset(&cnt_filters, 0, sizeof(cnt_filters));
+	if ((err = wlu_var_getbuf_med (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	statsbuf = (char *)ptr;
+	cnt = (wl_if_stats_t*)malloc(sizeof(wl_if_stats_t));
+	if (cnt == NULL) {
+		printf("\tCan not allocate %d bytes for counters struct\n",
+		       (int)sizeof(wl_if_stats_t));
+		return BCME_NOMEM;
+	} else
+		memcpy(cnt, statsbuf, sizeof(wl_if_stats_t));
+	/* summary stat counter line */
+	PRINIT();
+	PRVAL(txframe); PRVAL(txbyte); PRVAL(txerror);
+	PRVAL(rxframe); PRVAL(rxbyte); PRVAL(rxerror); PRNL1();
+
+	PRVAL(txnobuf); PRVAL(txfail); PRNL1();
+	PRVALSF_RENAME(txfrag, d11_txfrag);
+	PRVALSF_RENAME(txmulti, d11_txmulti);
+	PRVALSF_RENAME(txretry, d11_txretry);
+	PRVALSF_RENAME(txretrie, d11_txretrie);
+	PRNL1();
+	PRVALSF_RENAME(txfrmsnt, d11_txfrmsnt);
+	PRNL1();
+
+	PRVAL(rxnobuf);	PRVAL(rxfragerr); PRNL1();
+	PRVAL(rxrunt); PRNL1();
+	PRVALSF_RENAME(rxmulti, d11_rxmulti);
+	PRNL1();
+	if (dtoh16(cnt->length) > OFFSETOF(wl_if_stats_t, txexptime)) {
+		PRVAL(txexptime);
+		PRVAL(txrts); PRVAL(txnocts);
+	}
+	PRNL1();
+
+	if (cnt)
+		free(cnt);
+
+	return (0);
+}
+
+int
+wl_delta_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	char *statsbuf;
+	wl_delta_stats_t *cnt;
+	int err;
+	void *ptr;
+	struct cnt_filters_s cnt_filters;
+	struct cnt_filters_s *p_cnt_filters = &cnt_filters;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	memset(&cnt_filters, 0, sizeof(cnt_filters));
+
+	if ((err = wlu_var_getbuf_med (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	statsbuf = (char *)ptr;
+
+	cnt = (wl_delta_stats_t*)malloc(sizeof(wl_delta_stats_t));
+	if (cnt == NULL) {
+		printf("\tCan not allocate %d bytes for wl delta stats struct\n",
+		       (int)sizeof(wl_delta_stats_t));
+		return BCME_NOMEM;
+	}
+	memcpy(cnt, statsbuf, sizeof(wl_delta_stats_t));
+	cnt->version = dtoh16(cnt->version);
+	cnt->length = dtoh16(cnt->length);
+
+	if (cnt->version != WL_DELTA_STATS_T_VERSION) {
+		printf("\tIncorrect version of delta stats struct: expected %d; got %d\n",
+			WL_DELTA_STATS_T_VERSION, cnt->version);
+		free(cnt);
+		return -1;
+	}
+
+	PRINIT();
+	PRVAL(txframe); PRVAL(txbyte); PRVAL(txretrans); PRVAL(txfail); PRNL1();
+	PRVAL(rxframe); PRVAL(rxbyte); PRNL1();
+	PRVAL(rx1mbps); PRVAL(rx2mbps); PRVAL(rx5mbps5); PRVAL(rx6mbps); PRNL1();
+	PRVAL(rx9mbps); PRVAL(rx11mbps); PRVAL(rx12mbps); PRVAL(rx18mbps); PRNL1();
+	PRVAL(rx24mbps); PRVAL(rx36mbps); PRVAL(rx48mbps); PRVAL(rx54mbps); PRNL1();
+	PRNL1();
+
+	PRVAL(rxbadplcp); PRVAL(rxcrsglitch); PRVAL(bphy_rxcrsglitch); PRVAL(bphy_badplcp);
+	PRNL1();
+
+	if (cnt != NULL)
+		free(cnt);
+
+	return (0);
+}
+
+int
+wl_swdiv_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	char *statsbuf;
+	struct wlc_swdiv_stats_v1 *cnt_v1;
+	struct wlc_swdiv_stats_v2 *cnt;
+	int err = BCME_OK;
+	void *ptr;
+	struct cnt_filters_s cnt_filters;
+	struct cnt_filters_s *p_cnt_filters = &cnt_filters;
+
+	memset(&cnt_filters, 0, sizeof(cnt_filters));
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf_med (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	statsbuf = (char *)ptr;
+
+	/* Check for the firmware version and process accordingly */
+	if (wlc_ver_major(wl) <= 5) {
+		cnt_v1 = (struct wlc_swdiv_stats_v1*)malloc(sizeof(struct wlc_swdiv_stats_v1));
+		if (cnt_v1 == NULL) {
+			printf("\tCan not allocate %d bytes for wl swdiv stats struct\n",
+				(int)sizeof(struct wlc_swdiv_stats_v2));
+			return (-1);
+		}
+		memcpy(cnt_v1, statsbuf, sizeof(struct wlc_swdiv_stats_v1));
+		PRINIT();
+		PRVALV1(mws_antsel_ovr_tx); PRVALV1(mws_antsel_ovr_rx); PRNL1();
+		PRVALV1(rx_policy); PRVALV1(tx_policy); PRVALV1(cell_policy); PRNL1();
+		PRVALV1(auto_en); PRVALV1(active_ant); PRVALV1(rxcount); PRNL1();
+		PRVALV1(tx_auto_en); PRVALV1(tx_active_ant); PRNL1();
+		PRVALV1(avg_snr_per_ant0); PRVALV1(avg_snr_per_ant1);
+		PRVALV1(avg_snr_per_ant2); PRNL1();
+		PRVALV1(swap_ge_rxcount0); PRVALV1(swap_ge_rxcount1); PRNL1();
+		PRVALV1(swap_ge_snrthresh0); PRVALV1(swap_ge_snrthresh1); PRNL1();
+		PRVALV1(swap_txfail0); PRVALV1(swap_txfail1); PRNL1();
+		PRVALV1(swap_timer0); PRVALV1(swap_timer1); PRNL1();
+		PRVALV1(swap_alivecheck0); PRVALV1(swap_alivecheck1); PRNL1();
+		PRVALV1(swap_snrdrop0); PRVALV1(swap_snrdrop1); PRNL1();
+		PRVALV1(swap_trig_event_id); PRNL1();
+		PRNL1();
+
+	} else {
+		cnt = (struct wlc_swdiv_stats_v2*)malloc(sizeof(struct wlc_swdiv_stats_v2));
+		if (cnt == NULL) {
+			printf("\tCan not allocate %d bytes for wl swdiv stats struct\n",
+					(int)sizeof(struct wlc_swdiv_stats_v2));
+			return (-1);
+		}
+		memcpy(cnt, statsbuf, sizeof(struct wlc_swdiv_stats_v2));
+		if (cnt->version != 0) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		PRINIT();
+		PRVAL(mws_antsel_ovr_tx); PRVAL(mws_antsel_ovr_rx); PRNL1();
+		PRVAL(rx_policy); PRVAL(tx_policy); PRVAL(cell_policy); PRNL1();
+		PRVAL(auto_en); PRVAL(active_ant); PRVAL(rxcount); PRNL1();
+		PRVAL(tx_auto_en); PRVAL(tx_active_ant); PRNL1();
+		PRVAL(avg_snr_per_ant0); PRVAL(avg_snr_per_ant1);
+		PRVAL(avg_snr_per_ant2); PRNL1();
+		PRVAL(swap_ge_rxcount0); PRVAL(swap_ge_rxcount1); PRNL1();
+		PRVAL(swap_ge_snrthresh0); PRVAL(swap_ge_snrthresh1); PRNL1();
+		PRVAL(swap_txfail0); PRVAL(swap_txfail1); PRNL1();
+		PRVAL(swap_timer0); PRVAL(swap_timer1); PRNL1();
+		PRVAL(swap_alivecheck0); PRVAL(swap_alivecheck1); PRNL1();
+		PRVAL(swap_snrdrop0); PRVAL(swap_snrdrop1); PRNL1();
+		PRVAL(swap_trig_event_id); PRNL1();
+		PRNL1();
+	}
+
+exit :
+	if (wlc_ver_major(wl) <= 5) {
+		if (cnt_v1 != NULL)
+			free(cnt_v1);
+	} else {
+		if (cnt)
+			free(cnt);
+	}
+
+	return err;
+}
+
+int
+wl_clear_counters(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int val;
+#ifdef WL_NAN
+	wl_nan_ioc_t*nanioc;
+	uint16 iocsz = sizeof(wl_nan_ioc_t) + WL_NAN_IOC_BUFSZ;
+#endif /* WL_NAN */
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_iovar_getint(wl, cmd->name, &val)))
+		return (err);
+
+#ifdef WL_NAN
+	/*	alloc mem for ioctl headr +  tlv data  */
+	nanioc = calloc(1, iocsz);
+	if (nanioc == NULL)
+		return BCME_NOMEM;
+
+	/* make up nan cmd ioctl header */
+	nanioc->version = htod16(WL_NAN_IOCTL_VERSION);
+	nanioc->id = WL_NAN_CMD_CFG_CLEARCOUNT;
+	nanioc->len = WL_NAN_IOC_BUFSZ;
+
+	wl_nan_do_get_ioctl(wl, nanioc, iocsz);
+	free(nanioc);
+#endif /* WL_NAN */
+
+	return (0);
+}
diff --git a/wl/src/wl/exe/wlu_subcounters.h b/wl/src/wl/exe/wlu_subcounters.h
new file mode 100644
index 0000000..509af4a
--- /dev/null
+++ b/wl/src/wl/exe/wlu_subcounters.h
@@ -0,0 +1,25 @@
+/*
+ * Availability support functions
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: $
+ */
+
+#ifndef _WLU_SUBCOUNTERS_H_
+#define _WLU_SUBCOUNTERS_H_
+#define MAX_SUBCOUNTER_SUPPORTED	64 /* Max subcounters supported. */
+
+cmd_func_t wl_subcounters;
+cmd_func_t wl_counters, wl_if_counters, wl_swdiv_stats, wl_delta_stats;
+cmd_func_t wl_clear_counters;
+
+#endif /* _WLU_SUBCOUNTERS_H_ */
diff --git a/wl/src/wl/exe/wluc_ampdu.c b/wl/src/wl/exe/wluc_ampdu.c
new file mode 100644
index 0000000..afc4da9
--- /dev/null
+++ b/wl/src/wl/exe/wluc_ampdu.c
@@ -0,0 +1,320 @@
+/*
+ * wl ampdu command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_ampdu.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_ampdu_tid;
+static cmd_func_t wl_ampdu_aggr;
+static cmd_func_t wl_ampdu_retry_limit_tid;
+static cmd_func_t wl_ampdu_rr_retry_limit_tid;
+static cmd_func_t wl_ampdu_send_addba;
+static cmd_func_t wl_ampdu_send_delba;
+
+static cmd_t wl_ampdu_cmds[] = {
+	{ "ampdu_tid", wl_ampdu_tid, WLC_GET_VAR, WLC_SET_VAR,
+	"enable/disable per-tid ampdu; usage: wl ampdu_tid <tid> [0/1]" },
+	{ "ampdu_txaggr", wl_ampdu_aggr, WLC_GET_VAR, WLC_SET_VAR,
+	"enable/disable tx aggregation per tid or all tid for specific interface;\n"
+	"\tget current status: wl ampdu_txaggr\n"
+	"\tenable/disable all category(tid): wl ampdu_txaggr <0/1>\n"
+	"\tenable/disable per category(tid): wl ampdu_txaggr [<tid> <0/1>]"},
+	{ "ampdu_rxaggr", wl_ampdu_aggr, WLC_GET_VAR, WLC_SET_VAR,
+	"enable/disable rx aggregation per tid or all tid for specific interface;\n"
+	"\tget current status: wl ampdu_rxaggr\n"
+	"\tenable/disable all category(tid): wl ampdu_rxaggr <0/1>\n"
+	"\tenable/disable per category(tid): wl ampdu_rxaggr [<tid> <0/1>]"},
+	{ "ampdu_retry_limit_tid", wl_ampdu_retry_limit_tid, WLC_GET_VAR, WLC_SET_VAR,
+	"Set per-tid ampdu retry limit; usage: wl ampdu_retry_limit_tid <tid> [0~31]" },
+	{ "ampdu_rr_retry_limit_tid", wl_ampdu_rr_retry_limit_tid, WLC_GET_VAR, WLC_SET_VAR,
+	"Set per-tid ampdu regular rate retry limit; usage: "
+	"wl ampdu_rr_retry_limit_tid <tid> [0~31]" },
+	{ "ampdu_send_addba", wl_ampdu_send_addba, WLC_GET_VAR, WLC_SET_VAR,
+	"send addba to specified ea-tid; usage: wl ampdu_send_addba <tid> <ea>" },
+	{ "ampdu_send_delba", wl_ampdu_send_delba, WLC_GET_VAR, WLC_SET_VAR,
+	"send delba to specified ea-tid; usage: wl ampdu_send_delba <tid> <ea> [initiator]" },
+	{ "ampdu_txq_prof_start", wl_var_void, -1, WLC_SET_VAR,
+	"start sample txq profiling data"},
+	{ "ampdu_txq_prof_dump", wl_var_void, -1, WLC_SET_VAR,
+	"show txq histogram"},
+	{ "ampdu_txq_ss", wl_var_void, -1, WLC_SET_VAR,
+	"take txq snapshot"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_ampdu_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register ampdu commands */
+	wl_module_cmds_register(wl_ampdu_cmds);
+}
+
+static int
+wl_ampdu_tid(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_tid";
+	struct ampdu_tid_control atc, *reply;
+	uint8 tid;
+	int err;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	tid = atoi(param);
+	if (tid > MAXPRIO)
+		return BCME_USAGE_ERROR;
+	atc.tid = tid;
+
+	if ((param = *++argv)) {
+		atc.enable = atoi(param);
+		err = wlu_var_setbuf(wl, cmdname, &atc, sizeof(atc));
+	} else {
+		if ((err = wlu_var_getbuf_sm(wl, cmdname, &atc, sizeof(atc), &ptr) < 0))
+			return err;
+		reply = (struct ampdu_tid_control *)ptr;
+		printf("AMPDU for tid %d: %d\n", tid, reply->enable);
+	}
+	return err;
+}
+
+static int
+wl_ampdu_aggr(void *wl, cmd_t *cmd, char **argv)
+{
+	struct ampdu_aggr aggr, *reply;
+	int err;
+	int idx;
+	void *ptr = NULL;
+
+	if (argv[1] == NULL) {
+		/* get current status of aggregation */
+		if ((err = wlu_var_getbuf_sm(wl, cmd->name, &aggr, sizeof(aggr), &ptr) < 0)) {
+			return err;
+		}
+		reply = ptr;
+		printf("%s_override: %s\n", cmd->name, (reply->aggr_override == AUTO) ? "AUTO" :
+			((reply->aggr_override == ON) ? "ON" : "OFF"));
+		for (idx = 0; idx < NUMPRIO; idx++) {
+			printf("tid:%d status:%d\n", idx, isbitset(reply->enab_TID_bmap, idx));
+		}
+		return err;
+	}
+	memset(&aggr, 0, sizeof(aggr));
+	if (argv[2] == NULL) {
+		/* Set for all TID */
+		bool enab = atoi(*++argv);
+		aggr.enab_TID_bmap = enab ? NBITMASK(NUMPRIO) : 0;
+		aggr.conf_TID_bmap = NBITMASK(NUMPRIO);
+	} else {
+		char *param;
+		/* Set for specific TIDs */
+		while ((param = *++argv) != NULL) {
+			uint8 tid;
+			bool enab;
+			tid = atoi(param);
+			if (tid > MAXPRIO) {
+				return BCME_USAGE_ERROR;
+			}
+			if ((param = *++argv) == NULL) {
+				return BCME_USAGE_ERROR;
+			}
+			enab = atoi(param);
+			setbit(&aggr.conf_TID_bmap, tid);
+			if (enab) {
+				setbit(&aggr.enab_TID_bmap, tid);
+			}
+		}
+	}
+	err = wlu_var_setbuf(wl, cmd->name, &aggr, sizeof(aggr));
+	return err;
+}
+
+static int
+wl_ampdu_retry_limit_tid(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_retry_limit_tid";
+	struct ampdu_retry_tid retry_limit, *reply;
+	uint8 tid;
+	int err;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	tid = atoi(param);
+	if (tid > MAXPRIO)
+		return BCME_USAGE_ERROR;
+	retry_limit.tid = tid;
+
+	if ((param = *++argv)) {
+		retry_limit.retry = atoi(param);
+		err = wlu_var_setbuf(wl, cmdname, &retry_limit, sizeof(retry_limit));
+	} else {
+		if ((err = wlu_var_getbuf(wl, cmdname, &retry_limit,
+			sizeof(retry_limit), &ptr)) < 0)
+			return err;
+		reply = (struct ampdu_retry_tid *)ptr;
+		printf("AMPDU retry limit for tid %d: %d\n", tid, reply->retry);
+	}
+	return err;
+}
+
+static int
+wl_ampdu_rr_retry_limit_tid(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_rr_retry_limit_tid";
+	struct ampdu_retry_tid retry_limit, *reply;
+	uint8 tid;
+	int err;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	tid = atoi(param);
+	if (tid > MAXPRIO)
+		return BCME_USAGE_ERROR;
+	retry_limit.tid = tid;
+
+	if ((param = *++argv)) {
+		retry_limit.retry = atoi(param);
+		err = wlu_var_setbuf(wl, cmdname, &retry_limit, sizeof(retry_limit));
+	} else {
+		if ((err = wlu_var_getbuf(wl, cmdname, &retry_limit,
+			sizeof(retry_limit), &ptr)) < 0)
+			return err;
+		reply = (struct ampdu_retry_tid *)ptr;
+		printf("AMPDU regular rate retry limit for tid %d: %d\n", tid, reply->retry);
+	}
+	return err;
+}
+
+
+static int
+wl_ampdu_send_addba(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_send_addba";
+	struct ampdu_ea_tid aet;
+	uint8 tid;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	tid = atoi(param);
+	if (tid > MAXPRIO)
+		return BCME_USAGE_ERROR;
+	aet.tid = tid;
+
+	argv++;
+	if (!*argv) {
+		printf("error: missing address\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!wl_ether_atoe(*argv, &aet.ea)) {
+		printf("error: could not parse MAC address %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	return wlu_var_setbuf(wl, cmdname, &aet, sizeof(aet));
+}
+
+static int
+wl_ampdu_send_delba(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_send_delba";
+	struct ampdu_ea_tid aet;
+	uint8 tid;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	tid = atoi(param);
+	if (tid > MAXPRIO)
+		return BCME_USAGE_ERROR;
+	aet.tid = tid;
+
+	argv++;
+	if (!*argv) {
+		printf("error: missing address\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!wl_ether_atoe(*argv, &aet.ea)) {
+		printf("error: could not parse MAC address %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* initiator (optional argument), 0 is recipient, 1 is originator */
+	argv++;
+	if (*argv) {
+		aet.initiator = atoi(*argv);
+	}
+	else {
+		/* default is originator */
+		aet.initiator = TRUE;
+	}
+
+	return wlu_var_setbuf(wl, cmdname, &aet, sizeof(aet));
+}
diff --git a/wl/src/wl/exe/wluc_ampdu_cmn.c b/wl/src/wl/exe/wluc_ampdu_cmn.c
new file mode 100644
index 0000000..3d7f016
--- /dev/null
+++ b/wl/src/wl/exe/wluc_ampdu_cmn.c
@@ -0,0 +1,93 @@
+/*
+ * wl ampdu_cmn command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_ampdu_cmn.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_ampdu_activate_test;
+
+static cmd_t wl_ampdu_cmn_cmds[] = {
+	{ "ampdu_activate_test", wl_ampdu_activate_test, -1, WLC_SET_VAR,
+	"actiate" },
+	{ "ampdu_clear_dump", wl_var_void, -1, WLC_SET_VAR,
+	"clear ampdu counters"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_ampdu_cmn_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register ampdu_cmn commands */
+	wl_module_cmds_register(wl_ampdu_cmn_cmds);
+}
+
+static int
+wl_ampdu_activate_test(void *wl, cmd_t *cmd, char **argv)
+{
+	char *param;
+	const char *cmdname = "ampdu_activate_test";
+	struct agg {
+		bool val1;
+		bool val2;
+	} x;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	if ((param = *++argv) == NULL)
+		return BCME_USAGE_ERROR;
+
+	x.val1 = atoi(param);
+	if ((param = *++argv)) {
+		x.val2 = atoi(param);
+		printf("%d %d\n", x.val1, x.val2);
+		err = wlu_var_setbuf(wl, cmdname, &x, sizeof(x));
+	}
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_anqpo.c b/wl/src/wl/exe/wluc_anqpo.c
new file mode 100644
index 0000000..5a11f17
--- /dev/null
+++ b/wl/src/wl/exe/wluc_anqpo.c
@@ -0,0 +1,596 @@
+/*
+ * wl anqpo command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_anqpo.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifdef LINUX
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* LINUX */
+
+static cmd_func_t wl_anqpo_set;
+static cmd_func_t wl_anqpo_stop_query;
+static cmd_func_t wl_anqpo_start_query;
+static cmd_func_t wl_anqpo_ignore_ssid_list;
+static cmd_func_t wl_anqpo_ignore_bssid_list;
+#if defined(linux)
+static cmd_func_t wl_anqpo_results;
+#endif	/* linux */
+
+static cmd_t wl_anqpo_cmds[] = {
+	{ "anqpo_set", wl_anqpo_set, -1, -1,
+	"set ANQP offload parameters\n"
+	"\tusage: anqpo_set [max_retransmit <number>]\n"
+	"\t\t[response_timeout <msec>] [max_comeback_delay <msec>]\n"
+	"\t\t[max_retries <number>] [query \"encoded ANQP query\"]"
+	},
+	{ "anqpo_stop_query", wl_anqpo_stop_query, -1, WLC_SET_VAR,
+	"stop ANQP query\n"
+	"\tusage: anqpo_stop_query"
+	},
+	{ "anqpo_start_query", wl_anqpo_start_query, -1, WLC_SET_VAR,
+	"start ANQP query to peer(s)\n"
+	"\tusage: anqpo_start_query <channel> <xx:xx:xx:xx:xx:xx>\n"
+	"\t\t[<channel> <xx:xx:xx:xx:xx:xx>]>"
+	},
+	{ "anqpo_auto_hotspot", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"automatic ANQP query to maximum number of hotspot APs, default 0 (disabled)\n"
+	"\tusage: anqpo_auto_hotspot [max]"
+	},
+	{ "anqpo_ignore_mode", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"ignore duplicate SSIDs or BSSIDs, default 0 (SSID)\n"
+	"\tusage: anqpo_ignore_mode [0 (SSID) | 1 (BSSID)]"
+	},
+	{ "anqpo_ignore_ssid_list", wl_anqpo_ignore_ssid_list, WLC_GET_VAR, WLC_SET_VAR,
+	"get, clear, set, or append to ANQP offload ignore SSID list\n"
+	"\tusage: wl anqpo_ignore_ssid_list [clear |\n"
+	"\t\tset <ssid1> [ssid2] |\n"
+	"\t\tappend <ssid3> [ssid4]>"
+	},
+	{ "anqpo_ignore_bssid_list", wl_anqpo_ignore_bssid_list, WLC_GET_VAR, WLC_SET_VAR,
+	"get, clear, set, or append to ANQP offload ignore BSSID list\n"
+	"\tusage: wl anqpo_ignore_bssid_list [clear |\n"
+	"\t\tset <xx:xx:xx:xx:xx:xx> [xx:xx:xx:xx:xx:xx] |\n"
+	"\t\tappend <xx:xx:xx:xx:xx:xx> [xx:xx:xx:xx:xx:xx]]>"
+	},
+#if defined(linux)
+	{ "anqpo_results", wl_anqpo_results, -1, WLC_SET_VAR,
+	"Listens and displays ANQP results."
+	},
+#endif	/* linux */
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_anqpo_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register anqpo commands */
+	wl_module_cmds_register(wl_anqpo_cmds);
+}
+
+#define ANQPO_EVENTS_BUFFER_SIZE	2048
+
+static int
+wl_anqpo_set(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_USAGE_ERROR, malloc_size;
+	char *buffer;
+	wl_anqpo_set_t *set;
+	int length;
+
+	UNUSED_PARAMETER(cmd);
+
+	malloc_size = OFFSETOF(wl_anqpo_set_t, query_data) +
+		(ANQPO_MAX_QUERY_SIZE * sizeof(uint8));
+	buffer = malloc(malloc_size);
+	if (buffer == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+	memset(buffer, 0, malloc_size);
+	set = (wl_anqpo_set_t *)buffer;
+	/* parameters not configured by default */
+	set->max_retransmit = -1;
+	set->response_timeout = -1;
+	set->max_comeback_delay = -1;
+	set->max_retries = -1;
+
+	while (*++argv) {
+		if (!stricmp(*argv, "max_retransmit")) {
+			if (*++argv)
+				set->max_retransmit = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing max retransmit\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+		}
+		else if (!stricmp(*argv, "response_timeout")) {
+			if (*++argv)
+				set->response_timeout = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing response timeout\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+		}
+		else if (!stricmp(*argv, "max_comeback_delay")) {
+			if (*++argv)
+				set->max_comeback_delay = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing max comeback delay\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+		}
+		else if (!stricmp(*argv, "max_retries")) {
+			if (*++argv)
+				set->max_retries = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing retries\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+		}
+		else if (!stricmp(*argv, "query")) {
+			if (*++argv) {
+				if ((set->query_len = hexstr2hex(*argv)) == 0) {
+					fprintf(stderr, "Invalid ANQP query\n");
+					err = BCME_USAGE_ERROR;
+					goto done;
+				}
+				if (set->query_len > ANQPO_MAX_QUERY_SIZE) {
+					fprintf(stderr, "ANQP query size %d exceeds %d\n",
+						set->query_len, ANQPO_MAX_QUERY_SIZE);
+					err = BCME_USAGE_ERROR;
+					goto done;
+				}
+				memcpy(set->query_data, *argv, set->query_len);
+			}
+			else {
+				fprintf(stderr, "Missing ANQP query\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+		}
+		else {
+			fprintf(stderr, "Invalid parameter %s\n", *argv);
+			err = BCME_USAGE_ERROR;
+			goto done;
+		}
+
+	}
+
+	length = OFFSETOF(wl_anqpo_set_t, query_data) + set->query_len;
+	set->max_retransmit = htod16(set->max_retransmit);
+	set->response_timeout = htod16(set->response_timeout);
+	set->max_comeback_delay = htod16(set->max_comeback_delay);
+	set->max_retries = htod16(set->max_retries);
+	set->query_len = htod16(set->query_len);
+
+	err = wlu_iovar_set(wl, cmd->name, set, length);
+
+done:
+	free(buffer);
+	return err;
+}
+
+static int
+wl_anqpo_stop_query(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	return wlu_iovar_set(wl, cmd->name, 0, 0);
+}
+
+static int
+wl_anqpo_start_query(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_USAGE_ERROR, malloc_size;
+	char *buffer;
+	wl_anqpo_peer_list_t *list;
+	wl_anqpo_peer_t *peer;
+	int c;
+	int length;
+
+	UNUSED_PARAMETER(cmd);
+
+	malloc_size = OFFSETOF(wl_anqpo_peer_list_t, peer) +
+		(ANQPO_MAX_PEER_LIST * sizeof(wl_anqpo_peer_t));
+	buffer = malloc(malloc_size);
+	if (buffer == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+	memset(buffer, 0, malloc_size);
+	list = (wl_anqpo_peer_list_t *)buffer;
+	peer = &list->peer[0];
+
+	c = 1;
+	while (argv[c] && argv[c + 1]) {
+		if ((peer->channel = htod16(atoi(argv[c]))) == 0) {
+			fprintf(stderr, "Invalid channel\n");
+			err = BCME_USAGE_ERROR;
+			goto done;
+		}
+		if (!wl_ether_atoe(argv[c + 1], &peer->addr)) {
+			fprintf(stderr, "Invalid address\n");
+			err = BCME_USAGE_ERROR;
+			goto done;
+		}
+		list->count++;
+		c += 2;
+		peer++;
+	}
+
+	length = OFFSETOF(wl_anqpo_peer_list_t, peer) +
+		(list->count * sizeof(wl_anqpo_peer_t));
+	list->count = htod16(list->count);
+
+	err = wlu_iovar_set(wl, cmd->name, list, length);
+
+done:
+	free(buffer);
+	return err;
+}
+
+static int
+wl_anqpo_ignore_ssid_list(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_USAGE_ERROR, malloc_size;
+	char *buffer;
+	wl_anqpo_ignore_ssid_list_t *list;
+	int length;
+
+	UNUSED_PARAMETER(cmd);
+
+	malloc_size = OFFSETOF(wl_anqpo_ignore_ssid_list_t, ssid) +
+		(ANQPO_MAX_IGNORE_SSID * (sizeof(wl_anqpo_ignore_ssid_list_t) -
+		OFFSETOF(wl_anqpo_ignore_ssid_list_t, ssid)));
+	buffer = malloc(malloc_size);
+	if (buffer == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+	memset(buffer, 0, malloc_size);
+	list = (wl_anqpo_ignore_ssid_list_t *)buffer;
+
+	/* get */
+	if (!argv[1]) {
+		int i;
+
+		if ((err = wlu_iovar_get(wl, cmd->name, list, malloc_size)) < 0)
+			goto done;
+		list->count = dtoh16(list->count);
+		for (i = 0; i < list->count; i++) {
+			char ssidbuf[SSID_FMT_BUF_LEN];
+
+			wl_format_ssid(ssidbuf, list->ssid[i].SSID, list->ssid[i].SSID_len);
+			printf("%s\n", ssidbuf);
+		}
+		goto done;
+	}
+
+	/* set */
+	argv++;
+	if (!stricmp(*argv, "clear")) {
+		list->is_clear = TRUE;
+	}
+	else if (!stricmp(*argv, "set")) {
+		list->is_clear = TRUE;
+		while (*++argv) {
+			int len = strlen(*argv);
+			if (list->count > ANQPO_MAX_IGNORE_SSID) {
+				fprintf(stderr, "Too many BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			if (len > 32) {
+				fprintf(stderr, "SSID too long\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			list->ssid[list->count].SSID_len = len;
+			memcpy(list->ssid[list->count].SSID, *argv, len);
+			list->count++;
+		}
+	}
+	else if (!stricmp(*argv, "append")) {
+		while (*++argv) {
+			int len = strlen(*argv);
+			if (list->count > ANQPO_MAX_IGNORE_SSID) {
+				fprintf(stderr, "Too many BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			if (len > 32) {
+				fprintf(stderr, "SSID too long\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			list->ssid[list->count].SSID_len = len;
+			memcpy(list->ssid[list->count].SSID, *argv, len);
+			list->count++;
+		}
+	}
+	else {
+		fprintf(stderr, "Invalid parameter %s\n", *argv);
+		err = BCME_USAGE_ERROR;
+		goto done;
+	}
+
+	length = OFFSETOF(wl_anqpo_ignore_ssid_list_t, ssid) +
+		(list->count * (sizeof(wl_anqpo_ignore_ssid_list_t) -
+		OFFSETOF(wl_anqpo_ignore_ssid_list_t, ssid)));
+	list->count = htod16(list->count);
+
+	err = wlu_iovar_set(wl, cmd->name, list, length);
+
+done:
+	free(buffer);
+	return err;
+}
+
+static int
+wl_anqpo_ignore_bssid_list(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_USAGE_ERROR, malloc_size;
+	char *buffer;
+	wl_anqpo_ignore_bssid_list_t *list;
+	int length;
+
+	UNUSED_PARAMETER(cmd);
+
+	malloc_size = OFFSETOF(wl_anqpo_ignore_bssid_list_t, bssid) +
+		(ANQPO_MAX_IGNORE_BSSID * (sizeof(wl_anqpo_ignore_bssid_list_t) -
+		OFFSETOF(wl_anqpo_ignore_bssid_list_t, bssid)));
+	buffer = malloc(malloc_size);
+	if (buffer == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+	memset(buffer, 0, malloc_size);
+	list = (wl_anqpo_ignore_bssid_list_t *)buffer;
+
+	/* get */
+	if (!argv[1]) {
+		int i;
+
+		if ((err = wlu_iovar_get(wl, cmd->name, list, malloc_size)) < 0)
+			goto done;
+		list->count = dtoh16(list->count);
+		for (i = 0; i < list->count; i++) {
+			printf("%s\n", wl_ether_etoa(&list->bssid[i]));
+		}
+		goto done;
+	}
+
+	/* set */
+	argv++;
+	if (!stricmp(*argv, "clear")) {
+		list->is_clear = TRUE;
+	}
+	else if (!stricmp(*argv, "set")) {
+		list->is_clear = TRUE;
+		while (*++argv) {
+			if (list->count > ANQPO_MAX_IGNORE_BSSID) {
+				fprintf(stderr, "Too many BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			if (!wl_ether_atoe(*argv, &list->bssid[list->count])) {
+				fprintf(stderr, "Invalid BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			list->count++;
+		}
+	}
+	else if (!stricmp(*argv, "append")) {
+		while (*++argv) {
+			if (list->count > ANQPO_MAX_IGNORE_BSSID) {
+				fprintf(stderr, "Too many BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			if (!wl_ether_atoe(*argv, &list->bssid[list->count])) {
+				fprintf(stderr, "Invalid BSSID\n");
+				err = BCME_USAGE_ERROR;
+				goto done;
+			}
+			list->count++;
+		}
+	}
+	else {
+		fprintf(stderr, "Invalid parameter %s\n", *argv);
+		err = BCME_USAGE_ERROR;
+		goto done;
+	}
+
+	length = OFFSETOF(wl_anqpo_ignore_bssid_list_t, bssid) +
+		(list->count * (sizeof(wl_anqpo_ignore_bssid_list_t) -
+		OFFSETOF(wl_anqpo_ignore_bssid_list_t, bssid)));
+	list->count = htod16(list->count);
+
+	err = wlu_iovar_set(wl, cmd->name, list, length);
+
+done:
+	free(buffer);
+	return err;
+}
+
+#if defined(linux)
+static int
+wl_anqpo_results(void *wl, cmd_t *cmd, char **argv)
+{
+	int fd, err, octets;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	char *data;
+	uint8 event_inds_mask[WL_EVENTING_MASK_LEN];	/* event bit mask */
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+
+	memset(event_inds_mask, '\0', WL_EVENTING_MASK_LEN);
+	event_inds_mask[WLC_E_GAS_FRAGMENT_RX / 8] |= 1 << (WLC_E_GAS_FRAGMENT_RX % 8);
+	event_inds_mask[WLC_E_GAS_COMPLETE / 8] |= 1 << (WLC_E_GAS_COMPLETE % 8);
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		goto exit2;
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		err = -1;
+		goto exit2;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		goto exit1;
+	}
+
+	/* bind the socket first before starting so we won't miss any event */
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		goto exit1;
+	}
+
+	data = (char*)malloc(ANQPO_EVENTS_BUFFER_SIZE);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			ANQPO_EVENTS_BUFFER_SIZE);
+		err = BCME_NOMEM;
+		goto exit1;
+	}
+
+	/* receive result */
+	while (1) {
+		bcm_event_t *bcm_event;
+		int event_type;
+
+		octets = recv(fd, data, ANQPO_EVENTS_BUFFER_SIZE, 0);
+		bcm_event = (bcm_event_t *)data;
+		event_type = ntoh32(bcm_event->event.event_type);
+
+		if (octets >= (int)sizeof(bcm_event_t)) {
+			uint32 status = ntoh32(bcm_event->event.status);
+
+			if (event_type == WLC_E_GAS_FRAGMENT_RX) {
+				wl_event_gas_t *gas_data =
+					(wl_event_gas_t *)&data[sizeof(bcm_event_t)];
+
+				gas_data->channel = dtoh16(gas_data->channel);
+				gas_data->status_code = dtoh16(gas_data->status_code);
+				gas_data->data_len = dtoh16(gas_data->data_len);
+
+				printf("WLC_E_GAS_FRAGMENT_RX: %s\n",
+					status == WLC_E_STATUS_PARTIAL ? "WLC_E_STATUS_PARTIAL" :
+					status == WLC_E_STATUS_SUCCESS ? "WLC_E_STATUS_SUCCESS" :
+					status == WLC_E_STATUS_FAIL ? "WLC_E_STATUS_FAIL" :
+					"unknown");
+				printf("   channel         = %d\n", gas_data->channel);
+				printf("   peer            = %s\n",
+					wl_ether_etoa(&bcm_event->event.addr));
+				printf("   dialog token    = 0x%02x (%d)\n",
+					gas_data->dialog_token, gas_data->dialog_token);
+				printf("   fragment id     = 0x%02x\n", gas_data->fragment_id);
+				printf("   GAS status      = %s\n",
+					gas_data->status_code == DOT11_SC_SUCCESS ? "SUCCESS" :
+					gas_data->status_code == DOT11_SC_FAILURE ? "UNSPECIFIED" :
+					gas_data->status_code == DOT11_SC_ADV_PROTO_NOT_SUPPORTED ?
+						"ADVERTISEMENT_PROTOCOL_NOT_SUPPORTED" :
+					gas_data->status_code == DOT11_SC_NO_OUTSTAND_REQ ?
+						"NO_OUTSTANDING_REQUEST" :
+					gas_data->status_code == DOT11_SC_RSP_NOT_RX_FROM_SERVER ?
+						"RESPONSE_NOT_RECEIVED_FROM_SERVER" :
+					gas_data->status_code == DOT11_SC_TIMEOUT ?
+						"TIMEOUT" :
+					gas_data->status_code == DOT11_SC_QUERY_RSP_TOO_LARGE ?
+						"QUERY_RESPONSE_TOO_LARGE" :
+					gas_data->status_code == DOT11_SC_SERVER_UNREACHABLE ?
+						"SERVER_UNREACHABLE" :
+					gas_data->status_code == DOT11_SC_TRANSMIT_FAILURE ?
+						"TRANSMISSION_FAILURE" : "unknown");
+				printf("   GAS data length = %d\n", gas_data->data_len);
+				if (gas_data->data_len) {
+					wl_hexdump(gas_data->data, gas_data->data_len);
+				}
+			}
+			else if (event_type == WLC_E_GAS_COMPLETE) {
+				printf("WLC_E_GAS_COMPLETE: %s\n",
+					status == WLC_E_STATUS_SUCCESS ? "WLC_E_STATUS_SUCCESS" :
+					"unknown");
+			}
+		}
+	}
+
+	free(data);
+exit1:
+	close(fd);
+exit2:
+	return err;
+}
+#endif	/* linux */
diff --git a/wl/src/wl/exe/wluc_ap.c b/wl/src/wl/exe/wluc_ap.c
new file mode 100644
index 0000000..11f5016
--- /dev/null
+++ b/wl/src/wl/exe/wluc_ap.c
@@ -0,0 +1,606 @@
+/*
+ * wl ap command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_ap.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_maclist_1;
+static cmd_func_t wl_management_info;
+static cmd_func_t wl_bsscfg_enable;
+static cmd_func_t wl_radar;
+
+static cmd_t wl_ap_cmds[] = {
+	{ "ap", wl_int, WLC_GET_AP, WLC_SET_AP,
+	"Set AP mode: 0 (STA) or 1 (AP)" },
+	{ "tkip_countermeasures", wl_int, -1, WLC_TKIP_COUNTERMEASURES,
+	"Enable or disable TKIP countermeasures (TKIP-enabled AP only)\n"
+	"\t0 - disable\n"
+	"\t1 - enable" },
+	{ "shortslot_restrict", wl_int, WLC_GET_SHORTSLOT_RESTRICT, WLC_SET_SHORTSLOT_RESTRICT,
+	"Get/Set AP Restriction on associations for 11g Short Slot Timing capable STAs.\n"
+	"\t0 - Do not restrict association based on ShortSlot capability\n"
+	"\t1 - Restrict association to STAs with ShortSlot capability" },
+	{ "ignore_bcns", wl_int, WLC_GET_IGNORE_BCNS, WLC_SET_IGNORE_BCNS,
+	"AP only (G mode): Check for beacons without NONERP element"
+	"(0=Examine beacons, 1=Ignore beacons)" },
+	{ "scb_timeout", wl_int, WLC_GET_SCB_TIMEOUT, WLC_SET_SCB_TIMEOUT,
+	"AP only: inactivity timeout value for authenticated stas" },
+	{ "assoclist", wl_maclist, WLC_GET_ASSOCLIST, -1,
+	"AP only: Get the list of associated MAC addresses."},
+	{ "radar", wl_radar, WLC_GET_RADAR, WLC_SET_RADAR,
+	"Enable/Disable radar. One-shot Radar simulation with optional sub-band"},
+	{ "authe_sta_list", wl_maclist_1, WLC_GET_VAR, -1,
+	"Get authenticated sta mac address list"},
+	{ "autho_sta_list", wl_maclist_1, WLC_GET_VAR, -1,
+	"Get authorized sta mac address list"},
+	{ "beacon_info", wl_management_info, WLC_GET_VAR, -1,
+	"Returns the 802.11 management frame beacon information\n"
+	"Usage: wl beacon_info [-f file] [-r]\n"
+	"\t-f Write beacon data to file\n"
+	"\t-r Raw hex dump of beacon data" },
+	{ "probe_resp_info", wl_management_info, WLC_GET_VAR, -1,
+	"Returns the 802.11 management frame probe response information\n"
+	"Usage: wl probe_resp_info [-f file] [-r]\n"
+	"\t-f Write probe response data to file\n"
+	"\t-r Raw hex dump of probe response data" },
+	{ "bss", wl_bsscfg_enable, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get BSS enabled status: up/down"},
+	{ "closednet", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get BSS closed network attribute"},
+	{ "ap_isolate", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get AP isolation"},
+	{ "mode_reqd", wl_bsscfg_int, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get operational capabilities required for STA to associate to the BSS "
+	"supported by the interface.\n"
+	"\tUsage: wl [-i ifname] mode_reqd [value]\n"
+	"\t       wl mode_reqd [-C bss_idx ] [value]\n"
+	"\t\t     <ifname> is the name of the interface corresponding to the BSS.\n"
+	"\t\t\t   If the <ifname> is not given, the primary BSS is assumed.\n"
+	"\t\t     <bss_idx> is the the BSS configuration index.\n"
+	"\t\t\t   If the <bss_idx> is not given, configuraion #0 is assumed\n"
+	"\t\t     <value> is the numeric values in the range [0..3]\n"
+	"\t\t     0 - no requirements on joining devices.\n"
+	"\t\t     1 - devices must advertise ERP (11g) capabilities to be allowed to associate\n"
+	"\t\t\t   to a 2.4 GHz BSS.\n"
+	"\t\t     2 - devices must advertise HT (11n) capabilities to be allowed to associate\n"
+	"\t\t\t   to a BSS.\n"
+	"\t\t     3 - devices must advertise VHT (11ac) capabilities to be allowed to associate\n"
+	"\t\t\t   to a BSS.\n"
+	"\tThe command returns an error if the BSS interface is up.\n"
+	"\tThis configuration can only be changed while the BSS interface is down.\n"
+	"\tNote that support for HT implies support for ERP,\n"
+	"\tand support for VHT implies support for HT."},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_ap_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register ap commands */
+	wl_module_cmds_register(wl_ap_cmds);
+}
+
+/*
+ * Get Radar Enable/Disable status
+ * Set one-shot radar simulation with optional subband
+ */
+int
+wl_radar(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char *endptr = NULL;
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv) {
+		if ((ret = wlu_get(wl, WLC_GET_RADAR, &val, sizeof(int))) < 0) {
+			return ret;
+		}
+
+		val = dtoh32(val);
+		wl_printint(val);
+	} else {
+		struct {
+			int val;
+			uint sub;
+		} radar;
+		radar.val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			/* not all the value string was parsed by strtol */
+			return BCME_USAGE_ERROR;
+		}
+
+		radar.val = htod32(radar.val);
+		radar.sub = 0;
+		if (!*++argv) {
+			ret = wlu_set(wl, WLC_SET_RADAR, &radar.val, sizeof(radar.val));
+		} else {
+			radar.sub = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+			radar.sub = htod32(radar.sub);
+			ret = wlu_set(wl, WLC_SET_RADAR, &radar, sizeof(radar));
+		}
+	}
+
+	return ret;
+}
+
+static int
+wl_bsscfg_enable(void *wl, cmd_t *cmd, char **argv)
+{
+	char *endptr;
+	const char *val_name = "bss";
+	int bsscfg_idx = 0;
+	int val;
+	int consumed;
+	int ret;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* skip the command name */
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv, val_name, &bsscfg_idx, &consumed)) != 0)
+		return ret;
+
+	argv += consumed;
+	if (consumed == 0) { /* Use the -i parameter if that was present */
+		bsscfg_idx = -1;
+	}
+
+	if (!*argv) {
+		bsscfg_idx = htod32(bsscfg_idx);
+		ret = wlu_iovar_getbuf(wl, val_name, &bsscfg_idx, sizeof(bsscfg_idx),
+		                      buf, WLC_IOCTL_MAXLEN);
+		if (ret < 0)
+			return ret;
+		val = *(int*)buf;
+		val = dtoh32(val);
+		if (val)
+			printf("up\n");
+		else
+			printf("down\n");
+		return 0;
+	} else {
+		struct {
+			int cfg;
+			int val;
+		} bss_setbuf;
+		if (!stricmp(*argv, "move"))
+			val = WLC_AP_IOV_OP_MOVE;
+		else if (!stricmp(*argv, "ap"))
+			val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
+		else if (!stricmp(*argv, "sta"))
+			val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
+		else if (!stricmp(*argv, "up"))
+			val = WLC_AP_IOV_OP_ENABLE;
+		else if (!stricmp(*argv, "down"))
+			val = WLC_AP_IOV_OP_DISABLE;
+		else if (!stricmp(*argv, "del"))
+			val = WLC_AP_IOV_OP_DELETE;
+		else {
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+		}
+		bss_setbuf.cfg = htod32(bsscfg_idx);
+		bss_setbuf.val = htod32(val);
+
+		return wlu_iovar_set(wl, val_name, &bss_setbuf, sizeof(bss_setbuf));
+	}
+}
+
+static void dump_management_fields(uint8 *data, int len)
+{
+	int i, tag_len;
+	uint8 tag;
+	char temp[64];
+	uint8 *p;
+
+	while (len > 0) {
+		/* Get the tag */
+		tag = *data;
+		data++; len--;
+
+		/* Get the tag length */
+		tag_len = (int) *data;
+		data++; len--;
+
+		printf("Tag:%d Len:%d - ", tag, tag_len);
+
+		switch (tag) {
+		case DOT11_MNG_SSID_ID:
+			for (i = 0; i < tag_len; i++) {
+				temp[i] = data[i];
+			}
+			if (i < 64) {
+				temp[i] = '\0';
+			}
+			printf("SSID: '%s'\n", temp);
+			break;
+		case DOT11_MNG_FH_PARMS_ID:
+			printf("FH Parameter Set\n");
+			break;
+		case DOT11_MNG_DS_PARMS_ID:
+			printf("DS Parameter Set\n");
+			break;
+		case DOT11_MNG_CF_PARMS_ID:
+			printf("CF Parameter Set\n");
+			break;
+		case DOT11_MNG_RATES_ID:
+			printf("Supported Rates\n");
+			break;
+		case DOT11_MNG_TIM_ID:
+			printf("Traffic Indication Map (TIM)\n");
+			break;
+		case DOT11_MNG_IBSS_PARMS_ID:
+			printf("IBSS Parameter Set\n");
+			break;
+		case DOT11_MNG_COUNTRY_ID:
+			p = data;
+			printf("Country '%c%c%c'\n",
+			       data[0], data[1], data[2]);
+			p += DOT11_MNG_COUNTRY_ID_LEN;
+			while (((data+tag_len) - p) >= DOT11_MNG_COUNTRY_ID_LEN) {
+				printf("Start Channel: %d, Channels: %d, "
+				       "Max TX Power: %d dBm\n",
+				       p[0], p[1], p[2]);
+				p += DOT11_MNG_COUNTRY_ID_LEN;
+			}
+			break;
+		case DOT11_MNG_HOPPING_PARMS_ID:
+			printf("Hopping Pattern Parameters\n");
+			break;
+		case DOT11_MNG_HOPPING_TABLE_ID:
+			printf("Hopping Pattern Table\n");
+			break;
+		case DOT11_MNG_REQUEST_ID:
+			printf("Request\n");
+			break;
+		case DOT11_MNG_QBSS_LOAD_ID:
+			printf("QBSS Load\n");
+			break;
+		case DOT11_MNG_EDCA_PARAM_ID:
+			printf("EDCA Parameter\n");
+			break;
+		case DOT11_MNG_CHALLENGE_ID:
+			printf("Challenge text\n");
+			break;
+		case DOT11_MNG_PWR_CONSTRAINT_ID:
+			printf("Power Constraint\n");
+			break;
+		case DOT11_MNG_PWR_CAP_ID:
+			printf("Power Capability\n");
+			break;
+		case DOT11_MNG_TPC_REQUEST_ID:
+			printf("Transmit Power Control (TPC) Request\n");
+			break;
+		case DOT11_MNG_TPC_REPORT_ID:
+			printf("Transmit Power Control (TPC) Report\n");
+			break;
+		case DOT11_MNG_SUPP_CHANNELS_ID:
+			printf("Supported Channels\n");
+			break;
+		case DOT11_MNG_CHANNEL_SWITCH_ID:
+			printf("Channel Switch Announcement\n");
+			break;
+		case DOT11_MNG_MEASURE_REQUEST_ID:
+			printf("Measurement Request\n");
+			break;
+		case DOT11_MNG_MEASURE_REPORT_ID:
+			printf("Measurement Report\n");
+			break;
+		case DOT11_MNG_QUIET_ID:
+			printf("Quiet\n");
+			break;
+		case DOT11_MNG_IBSS_DFS_ID:
+			printf("IBSS DFS\n");
+			break;
+		case DOT11_MNG_ERP_ID:
+			printf("ERP Information\n");
+			break;
+		case DOT11_MNG_TS_DELAY_ID:
+			printf("TS Delay\n");
+			break;
+		case DOT11_MNG_HT_CAP:
+			printf("HT Capabilities\n");
+			break;
+		case DOT11_MNG_QOS_CAP_ID:
+			printf("QoS Capability\n");
+			break;
+		case DOT11_MNG_NONERP_ID:
+			printf("NON-ERP\n");
+			break;
+		case DOT11_MNG_RSN_ID:
+			printf("RSN\n");
+			break;
+		case DOT11_MNG_EXT_RATES_ID:
+			printf("Extended Supported Rates\n");
+			break;
+		case DOT11_MNG_AP_CHREP_ID:
+			printf("AP Channel Report\n");
+			break;
+		case DOT11_MNG_NEIGHBOR_REP_ID:
+			printf("Neighbor Report\n");
+			break;
+		case DOT11_MNG_MDIE_ID:
+			printf("Mobility Domain\n");
+			break;
+		case DOT11_MNG_FTIE_ID:
+			printf("Fast BSS Transition\n");
+			break;
+		case DOT11_MNG_FT_TI_ID:
+			printf("802.11R Timeout Interval\n");
+			break;
+		case DOT11_MNG_REGCLASS_ID:
+			printf("Regulatory Class\n");
+			break;
+		case DOT11_MNG_EXT_CSA_ID:
+			printf("Extended CSA\n");
+			break;
+		case DOT11_MNG_HT_ADD:
+			printf("HT Information\n");
+			break;
+		case DOT11_MNG_EXT_CHANNEL_OFFSET:
+			printf("Ext Channel\n");
+			break;
+#ifdef BCMWAPI_WAI
+		case DOT11_MNG_WAPI_ID:
+			printf("WAPI\n");
+			break;
+#endif
+		case DOT11_MNG_RRM_CAP_ID:
+			printf("Radio Measurement\n");
+			break;
+		case DOT11_MNG_HT_BSS_COEXINFO_ID:
+			printf("OBSS Coexistence INFO\n");
+			break;
+		case DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID:
+			printf("OBSS Intolerant Channel List\n");
+			break;
+		case DOT11_MNG_HT_OBSS_ID:
+			printf("OBSS HT Info\n");
+			break;
+#ifdef DOT11_MNG_CHANNEL_USAGE
+		case DOT11_MNG_CHANNEL_USAGE:
+			printf("Channel Usage\n");
+			break;
+#endif
+		case DOT11_MNG_LINK_IDENTIFIER_ID:
+			printf("TDLS Link Identifier\n");
+			break;
+		case DOT11_MNG_WAKEUP_SCHEDULE_ID:
+			printf("TDLS Wakeup Schedule\n");
+			break;
+		case DOT11_MNG_CHANNEL_SWITCH_TIMING_ID:
+			printf("TDLS Channel Switch Timing\n");
+			break;
+		case DOT11_MNG_PTI_CONTROL_ID:
+			printf("TDLS PTI Control\n");
+			break;
+		case DOT11_MNG_PU_BUFFER_STATUS_ID:
+			printf("TDLS PU Buffer Status\n");
+			break;
+		case DOT11_MNG_EXT_CAP_ID:
+			printf("Management Ext Capability\n");
+			break;
+		case DOT11_MNG_PROPR_ID:
+			printf("Proprietary\n");
+			break;
+		default:
+			if (tag_len <= len) {
+				printf("Unsupported tag\n");
+			} else {
+				/* Just dump the remaining data */
+				printf("Unsupported tag error/malformed\n");
+				tag_len = len;
+			}
+			break;
+		} /* switch */
+
+		wl_hexdump(data, tag_len);
+
+		data += tag_len;
+		len -= tag_len;
+	} /* while */
+}
+
+static void dump_management_info(uint8 *data, int len)
+{
+	struct dot11_management_header hdr;
+	struct dot11_bcn_prb parms;
+
+	if (len <= (int) (sizeof(hdr)+sizeof(parms))) {
+		/* Management packet invalid */
+		return;
+	}
+
+	memcpy(&hdr, data, sizeof(hdr));
+	data += sizeof(hdr);
+	len -= sizeof(hdr);
+
+	memcpy(&parms, data, sizeof(parms));
+	data += sizeof(parms);
+	len -= sizeof(parms);
+
+	/* 802.11 MAC header */
+	printf("Frame Ctl: 0x%04x\n", ltoh16(hdr.fc));
+	printf("Duration : 0x%04x\n", ltoh16(hdr.durid));
+	printf("Dest addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       hdr.da.octet[0],
+	       hdr.da.octet[1],
+	       hdr.da.octet[2],
+	       hdr.da.octet[3],
+	       hdr.da.octet[4],
+	       hdr.da.octet[5]);
+	printf("Src addr : %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       hdr.sa.octet[0],
+	       hdr.sa.octet[1],
+	       hdr.sa.octet[2],
+	       hdr.sa.octet[3],
+	       hdr.sa.octet[4],
+	       hdr.sa.octet[5]);
+	printf("BSSID    : %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       hdr.bssid.octet[0],
+	       hdr.bssid.octet[1],
+	       hdr.bssid.octet[2],
+	       hdr.bssid.octet[3],
+	       hdr.bssid.octet[4],
+	       hdr.bssid.octet[5]);
+	printf("Seq ctl  : 0x%04x\n", hdr.seq);
+
+	/* 802.11 management frame */
+	printf("Timestamp: 0x%08x%08x\n",
+	       ltoh32(parms.timestamp[0]), ltoh32(parms.timestamp[1]));
+	printf("Beacon Interval: 0x%04x\n", ltoh16(parms.beacon_interval));
+	printf("Capabilities: 0x%04x\n", ltoh32(parms.capability));
+
+	dump_management_fields(data, len);
+}
+
+static int
+wl_management_info(void *wl, cmd_t *cmd, char**argv)
+{
+	int ret = 0;
+	int len;
+	uint8 *data;
+	FILE *fp = NULL;
+	char *fname = NULL;
+	int raw = 0;
+
+	/* Skip the command name */
+	argv++;
+
+	while (*argv) {
+		char *s = *argv;
+
+		if (!strcmp(s, "-f") && argv[1] != NULL) {
+			/* Write packet to a file */
+			fname = argv[1];
+			argv += 2;
+		} else if (!strcmp(s, "-r")) {
+			/* Do a hex dump to console */
+			raw = 1;
+			argv++;
+		} else
+			return BCME_USAGE_ERROR;
+	}
+
+	/* Get the beacon information */
+	strcpy(buf, cmd->name);
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	/*
+	 * Dump out the beacon data. The first word (4 bytes) is the
+	 * length of the management packet followed by the data itself.
+	 */
+	len = dtoh32(*(int *)buf);
+
+	if (len <= 0) {
+		/* Nothing to do */
+		return ret;
+	}
+
+	data = (uint8 *) (buf + sizeof(int));
+	printf("Data: %p Len: %d bytes\n", data, len);
+
+	if (fname != NULL) {
+		/* Write the packet to a file */
+		if ((fp = fopen(fname, "wb")) == NULL) {
+			fprintf(stderr, "Failed to open file %s\n",
+			        fname);
+			ret = BCME_BADARG;
+		} else {
+			ret = fwrite(data, 1, len, fp);
+
+			if (ret != len) {
+				fprintf(stderr,
+				        "Error write %d bytes to file %s, rc %d!\n",
+				        len, fname, ret);
+				ret = -1;
+			}
+		}
+	} else if (raw) {
+		/* Hex dump */
+		wl_hexdump(data, len);
+	} else {
+		/* Print management (w/some decode) */
+		dump_management_info(data, len);
+	}
+
+	if (fp)
+		fclose(fp);
+
+	return ret;
+}
+
+static int
+wl_maclist_1(void *wl, cmd_t *cmd, char **argv)
+{
+	struct maclist *maclist;
+	struct ether_addr *ea;
+	uint i;
+	int ret;
+
+	strcpy(buf, argv[0]);
+
+	if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	maclist = (struct maclist *)buf;
+
+	for (i = 0, ea = maclist->ea; i < dtoh32(maclist->count); i++, ea++)
+		printf("%s %s\n", cmd->name, wl_ether_etoa(ea));
+	return 0;
+}
diff --git a/wl/src/wl/exe/wluc_arpoe.c b/wl/src/wl/exe/wluc_arpoe.c
new file mode 100644
index 0000000..8c4440b
--- /dev/null
+++ b/wl/src/wl/exe/wluc_arpoe.c
@@ -0,0 +1,108 @@
+/*
+ * wl arpoe command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_arpoe.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_arp_stats;
+
+static cmd_t wl_arpoe_cmds[] = {
+	{ "arp_ol", wl_offload_cmpnt, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set arp offload components"},
+	{ "arp_peerage", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set age of the arp entry in minutes"},
+	{ "arp_table_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear arp cache"},
+	{ "arp_hostip", wl_hostip, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a host-ip address or display them"},
+	{ "arp_hostip_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear all host-ip addresses"},
+	{ "arp_stats", wl_arp_stats, WLC_GET_VAR, -1,
+	"Display ARP offload statistics"},
+	{ "arp_stats_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear ARP offload statistics"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_arpoe_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register arpoe commands */
+	wl_module_cmds_register(wl_arpoe_cmds);
+}
+
+static int
+wl_arp_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct arp_ol_stats_t *arpstats;
+
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+		arpstats = (struct arp_ol_stats_t *)ptr;
+		printf("host_ip_entries = %d\n", dtoh32(arpstats->host_ip_entries));
+		printf("host_ip_overflow = %d\n", dtoh32(arpstats->host_ip_overflow));
+		printf("arp_table_entries = %d\n", dtoh32(arpstats->arp_table_entries));
+		printf("arp_table_overflow = %d\n", dtoh32(arpstats->arp_table_overflow));
+		printf("host_request = %d\n", dtoh32(arpstats->host_request));
+		printf("host_reply = %d\n", dtoh32(arpstats->host_reply));
+		printf("host_service = %d\n", dtoh32(arpstats->host_service));
+		printf("peer_request = %d\n", dtoh32(arpstats->peer_request));
+		printf("peer_request_drop = %d\n", dtoh32(arpstats->peer_request_drop));
+		printf("peer_reply = %d\n", dtoh32(arpstats->peer_reply));
+		printf("peer_reply_drop = %d\n", dtoh32(arpstats->peer_reply_drop));
+		printf("peer_service = %d\n", dtoh32(arpstats->peer_service));
+		printf("host_ip_entries = %d\n", dtoh32(arpstats->host_ip_entries));
+	} else
+		printf("Cannot set arp stats, use 'wl arp_stats_clear' to clear the counters\n");
+
+	return 0;
+}
diff --git a/wl/src/wl/exe/wluc_bdo.c b/wl/src/wl/exe/wluc_bdo.c
new file mode 100644
index 0000000..1ae5bd0
--- /dev/null
+++ b/wl/src/wl/exe/wluc_bdo.c
@@ -0,0 +1,351 @@
+/*
+ * wl bdo command module - Bonjour Dongle Offload
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id:$
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+#include <sys/stat.h>
+#include <errno.h>
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_bdo;
+
+static cmd_t wl_bdo_cmds[] = {
+	{ "bdo", wl_bdo, WLC_GET_VAR, WLC_SET_VAR,
+	"Bonjour dongle offload subcommands:\n"
+	"\tbdo download <dbase_filename>\n"
+	"\tbdo enable <0|1>\n"
+	"\tbdo max_download"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_bdo_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register bdo commands */
+	wl_module_cmds_register(wl_bdo_cmds);
+}
+
+/* download database from buffer */
+static int
+wl_bdo_download_database(void *wl, uint8 *database, uint16 len)
+{
+	int err = BCME_OK;
+	uint16 total_size = len;
+	uint16 current_size = 0;
+	uint16 frag_num = 0;
+
+	while (current_size < total_size) {
+		uint8 buffer[OFFSETOF(wl_bdo_t, data) + sizeof(wl_bdo_download_t)];
+		wl_bdo_t *bdo = (wl_bdo_t *)buffer;
+		int length;
+		wl_bdo_download_t *bdo_download = (wl_bdo_download_t *)bdo->data;
+
+		/* update size and fragment */
+		bdo_download->total_size = total_size;
+		bdo_download->frag_num = frag_num;
+		bdo_download->frag_size = MIN(total_size - current_size, BDO_MAX_FRAGMENT_SIZE);
+		memcpy(bdo_download->fragment, &database[current_size], bdo_download->frag_size);
+
+		bdo->subcmd_id = WL_BDO_SUBCMD_DOWNLOAD;
+		bdo->len = OFFSETOF(wl_bdo_download_t, fragment) + bdo_download->frag_size;
+
+		/* update before dongle byte order */
+		current_size += bdo_download->frag_size;
+		frag_num++;
+
+		/* dongle byte order */
+		bdo_download->total_size = htod16(bdo_download->total_size);
+		bdo_download->frag_num = htod16(bdo_download->frag_num);
+		bdo_download->frag_size = htod16(bdo_download->frag_size);
+
+		/* invoke iovar */
+		length = OFFSETOF(wl_bdo_t, data) + bdo->len;
+		bdo->subcmd_id = htod16(bdo->subcmd_id);
+		bdo->len = htod16(bdo->len);
+		if (wlu_iovar_setbuf(wl, "bdo", bdo, length, buf, WLC_IOCTL_MAXLEN) != 0) {
+			err = BCME_ERROR;
+			break;
+		}
+	}
+	return err;
+}
+
+/* reads file into buffer and returns bytes read and malloc'ed buffer with file contents */
+static int
+read_file(char *filename, unsigned char **buffer)
+{
+	FILE *fp = NULL;
+	int ifd;
+	struct stat filest;
+	unsigned int filesize = 0;
+	unsigned long status = 0;
+	unsigned char *buf = NULL;
+
+	/* open the file */
+	if (!(fp = fopen(filename, "rb"))) {
+		fprintf(stderr, "unable to open input file %s\n", filename);
+		goto error;
+	}
+
+	/* get fstat */
+	ifd = fileno(fp);
+	if (fstat(ifd, &filest)) {
+		fprintf(stderr, "fstat on input file %s return error %s\n",
+			filename, strerror(errno));
+		goto error;
+	}
+
+	/* get filesize */
+	filesize = filest.st_size;
+	if (filesize == 0) {
+		fprintf(stderr, "input file %s is empty (i.e. zero length)\n", filename);
+		goto error;
+	}
+
+	/* get buffer */
+	if ((buf = malloc(filesize)) == NULL) {
+		fprintf(stderr, "unable to allocate %u bytes based on input file size!\n",
+			filesize);
+		goto error;
+	}
+
+	/* read from file to buffer and check length */
+	status = fread(buf, 1, filesize, fp);
+	if (status != filesize) {
+		fprintf(stderr, "read of input file %s wasn't good based on fstat size %u\n",
+			filename, filesize);
+		goto error;
+	}
+
+	/* return buffer and filesize */
+	*buffer = buf;
+	fclose(fp);
+	return filesize;
+
+error:
+	if (buf) {
+		free(buf);
+	}
+	if (fp) {
+		fclose(fp);
+	}
+	return 0;
+}
+
+/* converts input hex buffer to binary and returns bytes converted and malloc'ed buffer */
+static int
+hex2bin(char *input, int len, unsigned char **buffer)
+{
+	unsigned char *buf = NULL;
+	int num_converted = 0;
+	char *p;
+
+	/* get buffer */
+	if ((buf = malloc(len)) == NULL) {
+		fprintf(stderr, "unable to allocate %u bytes\n", len);
+		return 0;
+	}
+
+	p = input;
+	while (p < input + len) {
+		char hex[3];
+
+		/* ignore unknown leading/trailing characters */
+		if (!isprint(*p)) {
+			p++;
+			continue;
+		}
+
+		hex[0] = *p++;
+		hex[1] = *p++;
+		hex[2] = 0;
+		/* convert hex to binary */
+		buf[num_converted++] = strtoul(hex, NULL, 16);
+	}
+
+	/* return buffer and number converted */
+	*buffer = buf;
+	return num_converted;
+}
+
+/* read database from file and download buffer */
+static int
+wl_bdo_download_file(void *wl, char *filename)
+{
+	int err;
+	int file_len;
+	unsigned char *file_buf;
+	unsigned char *conv_buf = NULL;
+	int dload_len;
+	unsigned char *dload_buf;
+
+	if ((file_len = read_file(filename, &file_buf)) == 0) {
+		return BCME_BADARG;
+	}
+
+	/* conversion to binary is needed if first char is printable */
+	if (isprint(file_buf[0])) {
+		dload_len = hex2bin((char *)file_buf, file_len, &conv_buf);
+		dload_buf = conv_buf;
+	} else {
+		dload_len = file_len;
+		dload_buf = file_buf;
+	}
+
+	err = wl_bdo_download_database(wl, dload_buf, dload_len);
+	if (err) {
+		printf("Failed to download. Error code: %d\n", err);
+	}
+	else {
+		printf("%s: %d bytes\n", filename, dload_len);
+	}
+
+	free(file_buf);
+	if (conv_buf) {
+		free(conv_buf);
+	}
+
+	return err;
+}
+
+static int
+wl_bdo(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	char *subcmd;
+	int subcmd_len;
+
+	/* skip iovar */
+	argv++;
+
+	/* must have subcommand */
+	subcmd = *argv++;
+	if (!subcmd) {
+		return BCME_USAGE_ERROR;
+	}
+	subcmd_len = strlen(subcmd);
+
+	if (!*argv) {
+		/* get */
+		uint8 buffer[OFFSETOF(wl_bdo_t, data)];
+		wl_bdo_t *bdo = (wl_bdo_t *)buffer;
+		int len = OFFSETOF(wl_bdo_t, data);
+
+		memset(bdo, 0, len);
+		if (!strncmp(subcmd, "enable", subcmd_len)) {
+			bdo->subcmd_id = WL_BDO_SUBCMD_ENABLE;
+		} else if (!strncmp(subcmd, "max_download", subcmd_len)) {
+			bdo->subcmd_id = WL_BDO_SUBCMD_MAX_DOWNLOAD;
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+		/* invoke GET iovar */
+		bdo->subcmd_id = htod16(bdo->subcmd_id);
+		bdo->len = htod16(bdo->len);
+		if ((err = wlu_iovar_getbuf(wl, cmd->name, bdo, len, buf, WLC_IOCTL_SMLEN)) < 0) {
+			return err;
+		}
+
+		/* process and print GET results */
+		bdo = (wl_bdo_t *)buf;
+		bdo->subcmd_id = dtoh16(bdo->subcmd_id);
+		bdo->len = dtoh16(bdo->len);
+
+		switch (bdo->subcmd_id) {
+		case WL_BDO_SUBCMD_ENABLE:
+		{
+			wl_bdo_enable_t *bdo_enable = (wl_bdo_enable_t *)bdo->data;
+			if (bdo->len >= sizeof(*bdo_enable)) {
+				printf("%d\n", bdo_enable->enable);
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		case WL_BDO_SUBCMD_MAX_DOWNLOAD:
+		{
+			wl_bdo_max_download_t *max_download = (wl_bdo_max_download_t *)bdo->data;
+			if (bdo->len >= sizeof(*max_download)) {
+				printf("%d\n", dtoh16(max_download->size));
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		default:
+			break;
+		}
+	} else if (!strncmp(subcmd, "download", subcmd_len) && argv[0]) {
+		/* download */
+		err = wl_bdo_download_file(wl, argv[0]);
+	}
+	else {
+		/* set */
+		uint8 buffer[OFFSETOF(wl_bdo_t, data) +	sizeof(wl_bdo_enable_t)];
+		wl_bdo_t *bdo = (wl_bdo_t *)buffer;
+		int len;
+
+		if (!strncmp(subcmd, "enable", subcmd_len) &&
+			(!strcmp(argv[0], "0") || !strcmp(argv[0], "1"))) {
+			wl_bdo_enable_t *bdo_enable = (wl_bdo_enable_t *)bdo->data;
+			bdo->subcmd_id = WL_BDO_SUBCMD_ENABLE;
+			bdo->len = sizeof(*bdo_enable);
+			bdo_enable->enable = atoi(argv[0]);
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+		/* invoke SET iovar */
+		len = OFFSETOF(wl_bdo_t, data) + bdo->len;
+		bdo->subcmd_id = htod16(bdo->subcmd_id);
+		bdo->len = htod16(bdo->len);
+		err = wlu_iovar_set(wl, cmd->name, bdo, len);
+	}
+
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_bmac.c b/wl/src/wl/exe/wluc_bmac.c
new file mode 100644
index 0000000..df36f28
--- /dev/null
+++ b/wl/src/wl/exe/wluc_bmac.c
@@ -0,0 +1,742 @@
+/*
+ * wl bmac command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_bmac.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+#include <bcmsrom_fmt.h>
+#include <bcmsrom_tbl.h>
+
+/* For backwards compatibility, the absense of the define 'NO_FILESYSTEM_SUPPORT'
+ * implies that a filesystem is supported.
+ */
+#if !defined(BWL_NO_FILESYSTEM_SUPPORT)
+#define BWL_FILESYSTEM_SUPPORT
+#endif
+
+static cmd_func_t wl_gpioout;
+static cmd_func_t wl_nvsource;
+static cmd_func_t wl_var_getinthex;
+static cmd_func_t wl_otpw, wl_otpraw;
+static cmd_func_t wl_devpath;
+static cmd_func_t wl_diag;
+static cmd_func_t wl_var_setintandprintstr;
+static cmd_func_t wl_otpdump_iter;
+static cmd_func_t wlu_srwrite_data;
+
+static cmd_t wl_bmac_cmds[] = {
+	{ "srcrc", wlu_srwrite, WLC_GET_SROM, -1,
+	"Get the CRC for input binary file" },
+	{ "cis_source", wl_varint, WLC_GET_VAR, -1,
+	"Display which source is used for the SDIO CIS"},
+	{ "nvram_source", wl_nvsource, WLC_GET_VAR, -1,
+	"Display which source is used for nvram"},
+	{ "customvar1", wl_var_getinthex, -1, -1,
+	"print the value of customvar1 in hex format" },
+	{ "gpioout", wl_gpioout, -1, -1,
+	"Set any GPIO pins to any value. Use with caution as GPIOs would be "
+	"assigned to chipcommon\n"
+	"\tUsage: gpiomask gpioval"},
+	{ "devpath", wl_devpath, WLC_GET_VAR, -1,
+	"print device path" },
+	{ "otpraw", wl_otpraw, WLC_GET_VAR, WLC_SET_VAR,
+	"Read/Write raw data to on-chip otp\n"
+	"Usage: wl otpraw <offset> <bits> [<data>]"},
+	{ "otpw", wl_otpw, -1, WLC_OTPW,
+	"Write an srom image to on-chip otp\n"
+	"Usage: wl otpw file"},
+	{ "nvotpw", wl_otpw, -1, WLC_NVOTPW,
+	"Write nvram to on-chip otp\n"
+	"Usage: wl nvotpw file"},
+	{ "diag", wl_diag, WLC_GET_VAR, -1,
+	"diag testindex(1-interrupt, 2-loopback, 3-memory, 4-led);"
+	" precede by 'wl down' and follow by 'wl up'" },
+	{ "otpdump", wl_otpdump_iter, WLC_GET_VAR, -1,
+	"Dump raw otp"},
+	{ "otpstat", wl_var_setintandprintstr, WLC_GET_VAR, -1,
+	"Dump OTP status"},
+	{ "srwrite_data", wlu_srwrite_data, WLC_GET_SROM, WLC_SET_SROM,
+	"Write caldata to srom: srwrite_data -t type filename\n"
+	"\t Supported types: calblob"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_bmac_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register bmac commands */
+	wl_module_cmds_register(wl_bmac_cmds);
+}
+
+static int
+wl_gpioout(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 mask;
+	uint32 val;
+	char *endptr = NULL;
+	uint argc;
+	uint32 *int_ptr;
+
+	UNUSED_PARAMETER(cmd);
+
+	val = 0;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* Get and print the values */
+	if (argc == 0) {
+		uint32 gpio_cntrl;
+		uint32 gpio_out;
+		uint32 gpio_outen;
+		int ret;
+
+		if ((ret = wlu_iovar_get(wl, "gpioout", buf, sizeof(uint32) *3)) < 0)
+			return ret;
+		gpio_cntrl = dtoh32(((uint32 *)buf)[0]);
+		gpio_out = dtoh32(((uint32 *)buf)[1]);
+		gpio_outen = dtoh32(((uint32 *)buf)[2]);
+
+		printf("gpiocontrol 0x%x gpioout 0x%x gpioouten 0x%x\n", gpio_cntrl,
+		       gpio_out, gpio_outen);
+
+		return 0;
+	}
+
+	/* required arg: mask value */
+	if (argc < 2)
+		return BCME_USAGE_ERROR;
+
+	mask = strtoul(argv[0], &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	val = strtoul(argv[1], &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	if ((~mask & val) != 0)
+		return BCME_BADARG;
+
+	int_ptr = (uint32 *)buf;
+	mask = htod32(mask);
+	memcpy(int_ptr, (const void *)&mask, sizeof(mask));
+	int_ptr++;
+	val = htod32(val);
+	memcpy(int_ptr, (const void *)&val, sizeof(val));
+
+	return wlu_iovar_set(wl, "gpioout", buf, sizeof(uint32) *2);
+}
+
+static int
+wl_nvsource(void *wl, cmd_t *cmd, char **argv)
+{
+	int32 val, err;
+
+	if ((err = wl_var_get(wl, cmd, argv)))
+		return (err);
+
+	val = dtoh32(*(int32*)buf);
+
+	switch (val) {
+	case 0:
+		printf("SROM\n");
+		break;
+	case 1:
+		printf("OTP\n");
+		break;
+	case 2:
+		printf("NVRAM\n");
+		break;
+	default:
+		printf("Unrecognized source %d\n", val);
+		break;
+	}
+
+	return 0;
+}
+
+#include <bcmnvram.h>
+
+static int
+wl_otpraw(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[392];
+	uint32 offset;
+	uint32 bits;
+	uint32 len;
+	bool get = TRUE;
+	void *ptr = NULL;
+	char *endptr;
+	uint32 i;
+
+	if (argv[1]) {
+		offset = htod32(strtoul(argv[1], &endptr, 0));
+		memcpy(var, (char *)&offset, sizeof(offset));
+		len = sizeof(offset);
+	}
+	else
+		return BCME_USAGE_ERROR;
+
+	if (argv[2]) {
+		bits = htod32(strtoul(argv[2], &endptr, 0));
+		if (bits > 3072)
+		{
+			printf("bit size (%d) too long or negative!!\n", bits);
+			return BCME_BADARG;
+		}
+	}
+	else
+		bits = 1;
+
+	memcpy(&var[len], (char *)&bits, sizeof(bits));
+	len += sizeof(bits);
+
+	if (argv[3]) {
+		unsigned char data[768];
+		uint32  patlen;
+		char *inptr = argv[3];
+
+		get = FALSE;
+
+		if (*inptr == '0' && toupper((int)(*(inptr + 1))) == 'X')
+			inptr += 2;
+
+		patlen = strlen(inptr);
+		if (patlen > 768 || (patlen * 4) < bits)
+		{
+			printf("data length (%d) too long or small!!\n", patlen);
+			return BCME_USAGE_ERROR;
+		}
+
+		for (i = 1; i <= patlen; i++)
+		{
+			int n = (int)((unsigned char)*inptr++);
+			if (!isxdigit(n)) {
+				fprintf(stderr, "invalid hex digit %c\n", n);
+				return BCME_USAGE_ERROR;
+			}
+			data[patlen - i] = (unsigned char)(isdigit(n) ? (n - '0')
+				        : ((islower(n) ? (toupper(n)) : n) - 'A' + 10));
+		}
+
+		for (i = 0; i < patlen; i += 2)
+		{
+			unsigned char v;
+			v = data[i];
+			if (i + 1 < patlen)
+				v += (data[i+1] * 16);
+			memcpy(&var[len], (char *)&v, sizeof(v));
+			len += sizeof(v);
+		}
+
+		printf("OTP RAM Write:");
+		for (i = 0; i < bits; i += 8)
+		{
+			unsigned char v;
+			v = var[2*sizeof(uint32) + (i/8)];
+
+			if ((i % 64) == 0)
+				printf("\nbit %4d:", offset + i);
+			printf(" 0x%x", v);
+		}
+		printf("\n");
+
+	}
+
+	if (get) {
+		int ret;
+		unsigned char v, *cptr;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, var, sizeof(var), &ptr)) < 0) {
+			printf("Error reading from OTP data\n");
+			return ret;
+		}
+
+		cptr = (unsigned char *)ptr;
+
+		printf("OTP RAM Read:");
+		for (i = 0; i < bits; i += 8)
+		{
+			v = *cptr++;
+
+			if ((i % 64) == 0)
+				printf("\nbit %4d:", offset + i);
+			printf(" 0x%02x", v);
+		}
+		printf("\n");
+		return 0;
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, &var, sizeof(var));
+}
+
+static int
+wl_otpw(void *wl, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return (-1);
+#elif	defined(DONGLEBUILD)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return 0;
+#else
+	FILE *fp;
+	int ret = 0;
+	struct nvram_header *nvr;
+	char *p, otpw_buf[1024 - 128];
+	const char *msg;
+	int len;
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	if (!(fp = fopen(*argv, "rb"))) {
+		fprintf(stderr, "%s: No such file or directory\n", *argv);
+		return BCME_BADARG;
+	}
+
+	len = fread(otpw_buf, 1, sizeof(otpw_buf) - 1, fp);
+	if ((ret = ferror(fp))) {
+		printf("\nerror %d reading %s\n", ret, *argv);
+		ret = BCME_ERROR;
+		goto out;
+	}
+	if (!feof(fp)) {
+		printf("\nFile %s too large\n", *argv);
+		ret = BCME_ERROR;
+		goto out;
+	}
+
+	/* Got the bits, do they look like the output of nvserial? */
+	nvr = (struct nvram_header *)otpw_buf;
+	if (nvr->magic == NVRAM_MAGIC) {
+		if (cmd->set == WLC_OTPW) {
+			printf("File %s looks like an nvserial file, use nvotpw\n", *argv);
+			fflush(stdout);
+			ret = BCME_ERROR;
+			goto out;
+		}
+		len  = nvr->len - sizeof(struct nvram_header);
+		if (len <= 0) {
+			printf("Invalid length (%d)\n", len);
+			ret = BCME_ERROR;
+			goto out;
+		}
+		if (len & 1) {
+			otpw_buf[len++] = '\0';
+		}
+		p = (char *)(nvr + 1);
+		msg = "nvserial";
+	} else {
+		if (cmd->set == WLC_NVOTPW) {
+			printf("File %s is not an nvserial file\n", *argv);
+			ret = BCME_ERROR;
+			goto out;
+		}
+		if (len & 1) {
+			printf("File %s has an odd length (%d)\n", *argv, len);
+			ret = BCME_ERROR;
+			goto out;
+		}
+		p = otpw_buf;
+		msg = "raw";
+	}
+
+	printf("Writing %d bytes from %s file %s to otp ...\n", len, msg, *argv);
+	fflush(stdout);
+
+	if ((ret = wlu_set(wl, cmd->set, p, len)) < 0) {
+		printf("\nError %d writing %s to otp\n", ret, *argv);
+	}
+
+out:
+	fclose(fp);
+	return ret;
+#endif /* BWL_FILESYSTEM_SUPPORT */
+}
+
+int wlu_srwrite_data(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, len, nw;
+	uint16 *words = (uint16 *)&buf[8];
+	uint16 caldata_offset;
+	FILE *fp = NULL;
+	srom_rw_t   *srt =  (srom_rw_t *)buf;
+	char *arg;
+	char *cal_buf;
+	int argc;
+
+	for (argc = 0; argv[argc]; argc++);
+
+	if (argc != 4)
+		return BCME_USAGE_ERROR;
+
+	/* We need at least one arg */
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	arg = *argv++;
+	if (!strcmp(arg, "-t") && !strcmp(*argv++, "calblob")) {
+		arg = *argv++;
+	/*
+	 * Avoid wl utility to driver compatibility issues by reading a 'safe' amount of words from
+	 * SPROM to determine the SPROM version that the driver supports, once the version is known
+	 * the full SPROM contents can be read. At the moment sromrev12 is the largest.
+	 */
+		nw = MAX(MAX(SROM10_SIGN, SROM11_SIGN), SROM11_SIGN)  + 1;
+		srt->byteoff = htod32(0);
+		srt->nbytes = htod32(2 * nw);
+
+		if (cmd->get < 0)
+			return BCME_ERROR;
+
+		if ((ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+		caldata_offset = words[SROM15_CAL_OFFSET_LOC] & 0xff;
+		if (words[SROM11_SIGN] == SROM15_SIGNATURE) {
+			nw = SROM15_WORDS;
+		} else if (words[SROM16_SIGN] == SROM16_SIGNATURE) {
+			nw = SROM16_WORDS;
+			caldata_offset = SROM16_CAL_DATA_OFFSET;
+			printf("Srom16, byte offset: %d\n", caldata_offset);
+		} else {
+			printf("Unsupported for SROM revs other than rev15\n");
+			return BCME_ERROR;
+		}
+
+
+		/* Reading caldata from msf file */
+		if (!(fp = fopen(arg, "rb"))) {
+				fprintf(stderr, "%s: No such file or directory\n", arg);
+				return BCME_BADARG;
+		}
+
+		cal_buf = malloc(SROM_MAX);
+		if (cal_buf == NULL) {
+			ret = BCME_NOMEM;
+			goto out;
+		}
+		len = fread(cal_buf, 1, SROM_MAX + 1, fp);
+		len = (len + 1) & ~1;
+		if (len > SROM15_MAX_CAL_SIZE) {
+			ret = BCME_BUFTOOLONG;
+			goto out;
+		}
+
+		if ((ret = ferror(fp))) {
+			printf("\nerror %d reading %s\n", ret, arg);
+			ret = BCME_ERROR;
+			goto out;
+		}
+
+		if (!feof(fp)) {
+			printf("\nFile %s is too large\n", arg);
+			ret = BCME_ERROR;
+			goto out;
+		}
+		if ((len - MAX_IOCTL_TXCHUNK_SIZE) > 0) {
+			memcpy(srt->buf, cal_buf, MAX_IOCTL_TXCHUNK_SIZE);
+			srt->byteoff = htod32(caldata_offset);
+			srt->nbytes = htod32(MAX_IOCTL_TXCHUNK_SIZE);
+			ret = wlu_set(wl, cmd->set, buf, MAX_IOCTL_TXCHUNK_SIZE + 8);
+			memcpy(srt->buf, cal_buf + MAX_IOCTL_TXCHUNK_SIZE,
+				len - MAX_IOCTL_TXCHUNK_SIZE);
+			srt->byteoff = htod32(caldata_offset + MAX_IOCTL_TXCHUNK_SIZE);
+			srt->nbytes = htod32(len - MAX_IOCTL_TXCHUNK_SIZE);
+			ret = wlu_set(wl, cmd->set, buf, len - MAX_IOCTL_TXCHUNK_SIZE + 8);
+		}
+		else {
+			memcpy(srt->buf, cal_buf, len);
+			srt->byteoff = htod32(caldata_offset);
+			srt->nbytes = htod32(len);
+			ret = wlu_set(wl, cmd->set, buf, len + 8);
+		}
+	}
+	else {
+		printf("Invalid arguments for srwrite_data\n");
+		return BCME_BADARG;
+	}
+out:
+	fflush(stdout);
+	if (fp)
+		fclose(fp);
+	free(cal_buf);
+	return ret;
+}
+
+
+
+/*
+ * wlu_reg3args is a generic function that is used for setting/getting
+ * WL_IOVAR variables that require address + offset for read, and
+ * address + offset + data for write.
+ */
+int
+wlu_reg3args(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	uint32 int_val;
+	bool get = TRUE;
+	uint32 len, i;
+	void *ptr = NULL;
+	char *endptr;
+	uint numargs;
+	int ret = 0;
+
+	len = 0;
+
+	if (!argv[1] || !argv[2]) {
+		printf("Wrong syntax => dev offset [val]\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (argv[3]) {
+		numargs = 3;
+		get = FALSE;
+	} else
+		numargs = 2;
+
+	for (i = 1; i <= numargs; i++) {
+		int_val = htod32(strtoul(argv[i], &endptr, 0));
+		memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+		len += sizeof(int_val);
+	}
+
+	if (get) {
+		if ((ret = wlu_var_getbuf(wl, cmd->name, var, sizeof(var), &ptr)) < 0)
+			return ret;
+
+		printf("0x%x\n", dtoh32(*(int *)ptr));
+	}
+	else
+		ret = wlu_var_setbuf(wl, cmd->name, &var, sizeof(var));
+	return ret;
+}
+
+
+static int
+wl_var_getinthex(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int32 val;
+
+	if ((err = wl_var_get(wl, cmd, argv)))
+		return (err);
+
+	val = dtoh32(*(int32*)buf);
+
+	printf("0x%08x\n", val);
+
+	return 0;
+}
+
+/* Variation: Like getandprint, but allow an int arg to be passed */
+static int
+wl_var_setintandprintstr(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int32 val;
+	char *varname;
+	char *endptr = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*argv) {
+		printf("set: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	varname = *argv++;
+
+	if (!*argv) {
+		val = 0;
+	} else {
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			/* not all the value string was parsed by strtol */
+			printf("set: error parsing value \"%s\" as an integer for set of \"%s\"\n",
+			       *argv, varname);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	val = htod32(val);
+	err = wlu_iovar_getbuf(wl, varname, &val, sizeof(int), buf, WLC_IOCTL_MAXLEN);
+
+	if (err)
+		return (err);
+
+	printf("%s\n", buf);
+	return (0);
+}
+
+#if WL_OTPREAD_VER != 1
+#error "Update this code to handle the new version of wl_otpread_cmd_t !"
+#endif
+
+static int
+wl_otpdump_iter(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int otpsize, readsize, offset = 0;
+	uint i;
+	uint16 *outbuf = (uint16 *)buf;
+	wl_otpread_cmd_t read_cmd;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*argv) {
+		printf("set: missing arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((ret = wlu_iovar_getint(wl, "otpsize", &otpsize)) < 0) {
+		return wl_var_setintandprintstr(wl, cmd, argv);
+	}
+
+	readsize = otpsize = dtoh32(otpsize);
+	printf("otpsize: %d\n", otpsize);
+
+	read_cmd.version = WL_OTPREAD_VER;
+	read_cmd.cmd_len = sizeof(read_cmd);
+	read_cmd.rdmode = 0;
+
+	while (readsize) {
+		read_cmd.rdsize = (readsize <= WLC_IOCTL_MAXLEN) ? readsize : WLC_IOCTL_MAXLEN;
+		read_cmd.rdoffset = offset;
+
+		memset(buf, 0, WLC_IOCTL_MAXLEN);
+
+		ret = wlu_iovar_getbuf(wl, "otpread", &read_cmd, sizeof(read_cmd),
+				buf, WLC_IOCTL_MAXLEN);
+
+		if (ret < 0)
+			return ret;
+
+		for (i = 0; i < (read_cmd.rdsize / 2); i++) {
+			if ((i % 4) == 0) {
+				printf("\n0x%04x:", 2 * i + offset);
+			}
+			printf(" 0x%04x", outbuf[i]);
+		}
+
+		readsize -= read_cmd.rdsize;
+		offset += read_cmd.rdsize;
+	}
+	printf("\n\n");
+
+	return (0);
+}
+
+void
+wl_printlasterror(void *wl)
+{
+	char error_str[128];
+
+	if (wlu_iovar_get(wl, "bcmerrorstr", error_str, sizeof(error_str)) != 0) {
+		fprintf(stderr, "%s: \nError getting the last error\n", wlu_av0);
+	} else {
+		fprintf(stderr, "%s: %s\n", wlu_av0, error_str);
+	}
+}
+
+static int
+wl_devpath(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	void *ptr;
+	char *pbuf = buf;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf_sm (wl, cmd->name, NULL, 0, &ptr)))
+		return (err);
+
+	pbuf += strlen(buf);
+	sprintf(pbuf, "\n");
+	fputs(buf, stdout);
+	return (0);
+}
+
+static int
+wl_diag(void *wl, cmd_t *cmd, char **argv)
+{
+	uint testindex;
+	int buflen, err;
+	char *param;
+	uint32 testresult;
+
+	if (!*++argv) {
+		printf(" Usage: %s testindex[1-4]\n", cmd->name);
+		return BCME_USAGE_ERROR;
+	}
+
+	testindex = atoi(*argv);
+
+	strcpy(buf, "diag");
+	buflen = strlen(buf) + 1;
+	param = (char *)(buf + buflen);
+	testindex = htod32(testindex);
+	memcpy(param, (char*)&testindex, sizeof(testindex));
+
+	if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	testresult = *(uint32 *)buf;
+	testindex = dtoh32(testindex);
+	testresult = dtoh32(testresult);
+	if (testresult != 0) {
+		printf("\ndiag test %d failed(error code %d)\n", testindex, testresult);
+	} else
+		printf("\ndiag test %d passed\n", testindex);
+
+	return (0);
+}
diff --git a/wl/src/wl/exe/wluc_bssload.c b/wl/src/wl/exe/wluc_bssload.c
new file mode 100644
index 0000000..35396d7
--- /dev/null
+++ b/wl/src/wl/exe/wluc_bssload.c
@@ -0,0 +1,270 @@
+/*
+ * wl bssload command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_bssload.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifdef LINUX
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* LINUX */
+
+static int wl_bssload_static(void *wl, cmd_t *cmd, char **argv);
+#if defined(WLBSSLOAD_REPORT)
+static int wl_bssload_report(void *wl, cmd_t *cmd, char **argv);
+static int wl_bssload_report_event(void *wl, cmd_t *cmd, char **argv);
+#if defined(linux)
+static cmd_func_t wl_bssload_event_check;
+#endif   /* linux */
+#endif   /* WLBSSLOAD_REPORT */
+
+static cmd_t wl_bssload_cmds[] = {
+	{ "bssload_static", wl_bssload_static, WLC_GET_VAR, WLC_SET_VAR,
+	"get or set static BSS load\n"
+	"\tusage: wl bssload_static [off | <sta_count> <chan_util> <acc>]"},
+#if defined(WLBSSLOAD_REPORT)
+	{ "bssload_report", wl_bssload_report, WLC_GET_VAR, -1,
+	"Get the latest BSS Load IE data from the associated AP's beacon\n"
+	"\tUsage: bssload_report"
+	},
+	{ "bssload_report_event", wl_bssload_report_event, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set BSS load threshold for sending WLC_E_BSS_LOAD event\n"
+	"\tUsage: wl bssload_report_event [rate_limit_msec] [level] [level] ...\n"
+	"\t\t[level] is a 0...255 channel utilization value.\n"
+	"\t\tUp to 8 levels in increasing order may be specified."
+	},
+#if defined(linux)
+	{ "bssload_event_check", wl_bssload_event_check, -1, -1,
+	"Listens forever for BSS Load events and prints them.\n"
+	"\tUsage: wl bssload_event_check"
+	},
+#endif	/* linux */
+#endif   /* WLBSSLOAD_REPORT */
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_bssload_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register bssload commands */
+	wl_module_cmds_register(wl_bssload_cmds);
+}
+
+static int
+wl_bssload_static(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	wl_bssload_static_t bssload;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* get */
+	if (!argv[1]) {
+		if ((err = wlu_iovar_get(wl, cmd->name, &bssload, sizeof(bssload))) < 0)
+			return err;
+		if (bssload.is_static) {
+			printf("station count: %d\n", dtoh16(bssload.sta_count));
+			printf("channel utilization: %d\n", bssload.chan_util);
+			printf("avail admission capacity: %d\n", dtoh16(bssload.aac));
+		}
+	}
+	else {
+		/* set */
+		argv++;
+		memset(&bssload, 0, sizeof(bssload));
+		if (!stricmp(*argv, "off")) {
+			bssload.is_static = FALSE;
+		}
+		else {
+			bssload.sta_count = htod16(strtoul(*argv, NULL, 0));
+
+			if (*++argv == NULL) {
+				printf("wl_bssload_static: "
+					"channel utilization not provided\n");
+				return -1;
+			}
+			bssload.chan_util = strtoul(*argv, NULL, 0);
+
+			if (*++argv == NULL) {
+				printf("wl_bssload_static: "
+					"avail admission capacity not provided\n");
+				return -1;
+			}
+			bssload.aac = htod16(strtoul(*argv, NULL, 0));
+
+			bssload.is_static = TRUE;
+		}
+
+		err = wlu_iovar_set(wl, cmd->name, &bssload, sizeof(bssload));
+	}
+
+	return err;
+}
+
+#if defined(WLBSSLOAD_REPORT)
+static int
+wl_bssload_report(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	wl_bssload_t *bssload = NULL;
+
+	/* If any arguments are given, print help */
+	if (ARGCNT(argv) > 1)
+		goto usage;
+
+	/* Get and print the current BSS Load values */
+	if ((ret = wlu_var_getbuf_sm(wl, cmd->name, NULL, 0, (void*)&bssload)))
+		return ret;
+	if (bssload == NULL)
+		return BCME_ERROR;
+	printf("BSS Load from associated AP beacon:\n");
+	printf("station count               : %u\n", dtoh16(bssload->sta_count));
+	printf("channel utilization         : %u\n", bssload->chan_util);
+	printf("available admission capacity: %u\n", dtoh16(bssload->aac));
+	return 0;
+
+usage:
+	return -1;
+}
+
+static int
+wl_bssload_report_event(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	wl_bssload_cfg_t blcfg;
+
+	(void) wl;
+	if (!*++argv) {
+		/* get */
+		void *ptr = NULL;
+		uint i;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		memcpy(&blcfg, ptr, sizeof(blcfg));
+		blcfg.rate_limit_msec = dtoh32(blcfg.rate_limit_msec);
+
+		printf("rate_limit_msec: %d\n", blcfg.rate_limit_msec);
+		printf("%d channel utilization levels:", blcfg.num_util_levels);
+		for (i = 0; i < blcfg.num_util_levels; i++) {
+			printf(" %d", blcfg.util_levels[i]);
+		}
+		printf("\n");
+	} else {
+		/* set */
+		memset(&blcfg, 0, sizeof(wl_bssload_cfg_t));
+		blcfg.rate_limit_msec = atoi(*argv);
+
+		while (*++argv && blcfg.num_util_levels < MAX_BSSLOAD_LEVELS) {
+			blcfg.util_levels[blcfg.num_util_levels++] = atoi(*argv);
+			if (blcfg.num_util_levels > 1 &&
+				blcfg.util_levels[blcfg.num_util_levels - 1] <=
+				blcfg.util_levels[blcfg.num_util_levels - 2]) {
+				printf("Channel utilization level %u was <= level %u.\n",
+					blcfg.util_levels[blcfg.num_util_levels - 1],
+					blcfg.util_levels[blcfg.num_util_levels - 2]);
+				goto usage;
+			}
+		}
+
+		if (*argv) {
+			printf("Too many parameters.\n");
+			goto usage;
+		}
+
+		blcfg.rate_limit_msec = htod32(blcfg.rate_limit_msec);
+		ret = wlu_var_setbuf(wl, cmd->name, &blcfg, sizeof(blcfg));
+	}
+	return ret;
+
+usage:
+	return -1;
+}
+
+#if defined(linux)
+static void
+wl_bssload_event_cb(int event_type, bcm_event_t *bcm_event)
+{
+	struct timeval tv;
+	uint32 sec, msec;
+	int ret;
+	wl_bssload_t *data = (wl_bssload_t *) (bcm_event + 1);
+
+	if (event_type == WLC_E_BSS_LOAD) {
+		/* Print a timestamp */
+		ret = gettimeofday(&tv, NULL);
+		if (ret == 0) {
+			sec = (uint32) (tv.tv_sec % 10000);
+			msec = (uint32) tv.tv_usec / 1000;
+			printf("%04d.%03d\n", sec, msec);
+		}
+
+		printf("WLC_E_BSS_LOAD: chan_util = %u\n", data->chan_util);
+		printf("                sta_count = %u\n", dtoh16(data->sta_count));
+		printf("                aac       = %u\n", dtoh16(data->aac));
+	}
+}
+
+static int
+wl_bssload_event_check(void *wl, cmd_t *cmd, char **argv)
+{
+	if (argv[1] && argv[1][0] == '-') {
+		wl_cmd_usage(stderr, cmd);
+		return -1;
+	}
+	return wl_wait_for_event(wl, argv, WLC_E_BSS_LOAD, 2048, wl_bssload_event_cb);
+}
+#endif	/* linux */
+#endif   /* WLBSSLOAD_REPORT */
diff --git a/wl/src/wl/exe/wluc_btcdyn.c b/wl/src/wl/exe/wluc_btcdyn.c
new file mode 100644
index 0000000..1b82e03
--- /dev/null
+++ b/wl/src/wl/exe/wluc_btcdyn.c
@@ -0,0 +1,509 @@
+
+/*
+ * wl dynamic btcoex command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_btcdyn.c $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifdef WIN32
+#define bzero(b, len)	memset((b), 0, (len))
+#endif
+
+#ifdef LINUX
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* LINUX */
+
+#include <miniopt.h>
+
+static cmd_func_t wl_btcoex_dynctl;
+static cmd_func_t wl_btcoex_dynctl_status;
+static cmd_func_t wl_btcoex_dynctl_sim;
+
+#define WL_BTCDYNCTL_USAGE \
+"Usage:\n" \
+"\t [-d dflt_dsns_level] [-l low_dsns_level] [-m mid_dsns_level] [-h high_dsns_level]\n" \
+"\t [-c default_btc_mode\n" \
+"\t [-s mode_switching_btrssi_hysteresis in dBm\n\n" \
+"\t [-f dynctl_flags] : bit0: Dynctl on/off, bit1-desense on/off," \
+" bit2-m_switch on/off, bit7-dryrun on/off\n" \
+"\t [-j row_idx:btcmode,bt_pwr,wl_rssi_high,wl_rssi_low] : set one row in mode table\n" \
+"\t [-k row_idx:btcmode,bt_pwr,wl_rssi_high,wl_rssi_low] : set one row in desense table\n" \
+"\t [-n number of active rows in mode switching table\n" \
+"\t [-o number of active rows in desense switching table\n\n"
+
+#define WL_BTCDYNCTL_STATUS_USAGE \
+"Usage: command doeesn't take any arguments]\n"
+
+#define WL_BTCDYNCTL_SIM_USAGE \
+"Usage: wl btc_dynctl_sim [1|0] [-b bt_sim_pwr] [-r bt_sim_rssi] [-w wl_sim_rssi] \n" \
+
+/* bycdyn wl commands  */
+static cmd_t wl_btcdyn_cmds[] = {
+	{ "btc_dynctl", wl_btcoex_dynctl, WLC_GET_VAR, WLC_SET_VAR, WL_BTCDYNCTL_USAGE},
+	{ "btc_dynctl_status", wl_btcoex_dynctl_status, WLC_GET_VAR, -1, WL_BTCDYNCTL_STATUS_USAGE},
+	{ "btc_dynctl_sim", wl_btcoex_dynctl_sim, WLC_GET_VAR, WLC_SET_VAR, WL_BTCDYNCTL_SIM_USAGE},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_btcdyn_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register btcdyn commands */
+	wl_module_cmds_register(wl_btcdyn_cmds);
+}
+
+
+static int fill_thd_row(btc_thr_data_t *thd, char *str)
+{
+	char delim[] = ":,\0";
+	int err = BCME_OK;
+	int idx = atoi(strtok(str, delim));
+	char *s_mode, *s_bt_pwr, *s_bt_rssi, *s_wl_rssi_high, *s_wl_rssi_low;
+
+	if (idx >= DCTL_TROWS_MAX) {
+		fprintf(stderr, " invalid index:%d the data:%s\n", idx, str);
+		err = BCME_BADARG;
+		return err;
+	}
+
+	s_mode = strtok(NULL, delim);
+	s_bt_pwr = strtok(NULL, delim);
+	s_bt_rssi = strtok(NULL, delim);
+	s_wl_rssi_high = strtok(NULL, delim);
+	s_wl_rssi_low = strtok(NULL, delim);
+	if (!s_mode || !s_bt_pwr || !s_bt_rssi || !s_wl_rssi_high ||
+		!s_wl_rssi_low) {
+		fprintf(stderr, " invalid row data format or number of parameters\n");
+		err = BCME_BADARG;
+		return err;
+	}
+	/* all present, convert them to int */
+	thd[idx].mode = atoi(s_mode);
+	thd[idx].bt_pwr = atoi(s_bt_pwr);
+	thd[idx].bt_rssi = atoi(s_bt_rssi);
+	thd[idx].wl_rssi_high = atoi(s_wl_rssi_high);
+	thd[idx].wl_rssi_low = atoi(s_wl_rssi_low);
+
+	printf("written table entry:%d: mode:%d, bt_pwr:%d, bt_rssi:%d,"
+		" wl_rssi_high:%d, wl_rssi_low:%d\n",
+		idx, thd[idx].mode, thd[idx].bt_pwr, thd[idx].bt_rssi,
+		thd[idx].wl_rssi_high, thd[idx].wl_rssi_low);
+	return err;
+}
+
+/*
+*  get/set dynamic BTCOEX profile (desense, modesw etc)
+*/
+static int
+wl_btcoex_dynctl(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0, opt_err;
+	miniopt_t to;
+	void *ptr;
+	dctl_prof_t *profile = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* get current profile */
+	if ((err = wlu_var_getbuf(wl,
+			"btc_dynctl", NULL, 0, &ptr) < 0)) {
+		fprintf(stderr, "btc_dynctl: getbuf ioctl failed\n");
+		return err;
+	}
+
+	if (*++argv) {
+		/* some arguments are present, do set or help  */
+
+		if (argv[0][0] == 'h' ||
+			argv[0][0] == '?') {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		profile = calloc(1, sizeof(dctl_prof_t) + sizeof(dynctl_status_t));
+		if (profile == NULL)
+			return BCME_NOMEM;
+
+		/* copy current profile values into buf allocated for set ioctl */
+		bcopy(ptr, profile, sizeof(dctl_prof_t));
+
+		miniopt_init(&to, __FUNCTION__, NULL, FALSE);
+
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+				if (opt_err == 1) {
+					err = BCME_USAGE_ERROR;
+					goto exit;
+				}
+				argv += to.consumed;
+
+				if (to.opt == 'c') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" default_btc_mode\n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					profile->default_btc_mode = to.val;
+				}
+
+				if (to.opt == 'd') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" dflt_dsns_level\n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					profile->dflt_dsns_level = to.val;
+				}
+
+				if (to.opt == 'l') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" low_dsns_level\n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					profile->low_dsns_level = to.val;
+				}
+				if (to.opt == 'm') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" mid_dsns_level\n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					profile->mid_dsns_level = to.val;
+				}
+				if (to.opt == 'h') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" high_dsns_level\n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					profile->high_dsns_level = to.val;
+				}
+
+				if (to.opt == 'f') {
+					/*   set dynctl flags  */
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" flags \n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					profile->flags = to.val;
+				}
+
+				/*   modify mode switching table  */
+				if (to.opt == 'j') {
+					if (fill_thd_row(profile->msw_data, to.valstr) != BCME_OK)
+							goto exit;
+				}
+
+				/*   modify desense level table */
+				if (to.opt == 'k') {
+					if (fill_thd_row(profile->dsns_data, to.valstr) != BCME_OK)
+							goto exit;
+				}
+
+				/*  set number of active rows in msw table  */
+				if (to.opt == 'n') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" msw_rows\n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+						/* check for array bounds  */
+					if (to.val > DCTL_TROWS_MAX) {
+						fprintf(stderr, "array index:%d >= MAX:%d !\n",
+							to.val, DCTL_TROWS_MAX);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					profile->msw_rows = to.val;
+				}
+				/*  set number of active rows in desense table  */
+				if (to.opt == 'o') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" dsns_rows\n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					/* check for array bounds  */
+					if (to.val > DCTL_TROWS_MAX) {
+						fprintf(stderr, "array index;%d >= MAX:%d !\n",
+							to.val, DCTL_TROWS_MAX);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					profile->dsns_rows = to.val;
+				}
+				if (to.opt == 's') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" btrssi_hysteresis \n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					profile->msw_btrssi_hyster = to.val;
+				}
+		} /* end of miniopt while loop */
+
+		/* write back modified dctl_prof_t structure */
+		if ((err = wlu_var_setbuf(wl, "btc_dynctl", profile,
+			sizeof(dctl_prof_t)) < 0)) {
+			printf("btc_dynctl: fail to set %d\n", err);
+		}
+
+	} else { /* display current dynctl profile */
+		int i;
+		profile = ptr;
+
+		/* get:  just display the current profile values  */
+		printf(" === btc dynctl: ===\n");
+		printf("DYNCTL(0x%x): %s, Desense:%s, Mode:%s\n",
+			profile->flags,
+			IS_DYNCTL_ON(profile)?"On":"Off",
+			IS_DESENSE_ON(profile)?"On":"Off",
+			IS_MSWITCH_ON(profile)?"On":"Off");
+			printf("dflt_dsns_level:%d\n", profile->dflt_dsns_level);
+		printf("low_dsns_level:%d\n", profile->low_dsns_level);
+		printf("mid_dsns_level:%d\n", profile->mid_dsns_level);
+		printf("high_dsns_level:%d\n", profile->high_dsns_level);
+		printf("btrssi msw hysteresis %d dBm\n", profile->msw_btrssi_hyster);
+		printf("default_btc_mode:%d\n", profile->default_btc_mode);
+
+		printf("--- coex mode switch data table "
+			"msw_rows:%d ---\n", profile->msw_rows);
+
+		for (i = 0; i < MIN(DCTL_TROWS_MAX, profile->msw_rows); i++) {
+			printf("row:%d: btcmode:%d, bt_pwr:%d, bt_rssi:%d,"
+				" wl_rssi_high:%d, wl_rssi_low:%d\n",
+				i,
+				profile->msw_data[i].mode,
+				profile->msw_data[i].bt_pwr,
+				profile->msw_data[i].bt_rssi,
+				profile->msw_data[i].wl_rssi_high,
+				profile->msw_data[i].wl_rssi_low);
+		}
+		printf("--- wl desense data table "
+			"dsns_rows:%d ---\n", profile->dsns_rows);
+		for (i = 0; i < MIN(DCTL_TROWS_MAX, profile->dsns_rows); i++) {
+			printf("row:%d: btcmode:%d, bt_pwr:%d, bt_rssi:%d,"
+				" wl_rssi_high:%d, wl_rssi_low:%d\n",
+				i,
+				profile->dsns_data[i].mode,
+				profile->dsns_data[i].bt_pwr,
+				profile->dsns_data[i].bt_rssi,
+				profile->dsns_data[i].wl_rssi_high,
+				profile->dsns_data[i].wl_rssi_low);
+		}
+		profile = NULL;
+	}
+
+exit:
+	if (profile)
+		free(profile);
+	return err;
+}
+
+/*
+*  get dynamic BTCOEX status
+*/
+static int
+wl_btcoex_dynctl_status(void *wl, cmd_t *cmd, char **argv)
+{
+	dynctl_status_t	status;
+	void *ptr;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv != NULL) {
+		fprintf(stderr, "command doesn't accept any params\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* get current profile */
+	if ((err = wlu_var_getbuf(wl,
+			"btc_dynctl_status", NULL, 0, &ptr) < 0)) {
+		printf("btc_dynctl: getbuf ioctl failed\n");
+			return err;
+	}
+	/* copy the status from ioctl buffer */
+	bcopy(ptr, &status, sizeof(dynctl_status_t));
+
+	printf("--- btc dynctl status ---:\n");
+	printf("simulation mode:%s\n", status.sim_on?"On":"Off");
+	printf("bt_pwr_shm %x\n", dtoh16(status.bt_pwr_shm));
+	printf("bt_pwr:%d dBm\n", status.bt_pwr);
+	printf("bt_rssi:%d dBm\n", status.bt_rssi);
+	printf("wl_rssi:%d dBm\n", status.wl_rssi);
+	printf("dsns_level:%d\n", status.dsns_level);
+	printf("btc_mode:%d\n", status.btc_mode);
+
+	return err;
+}
+
+/*
+*  get/set dynamic BTCOEX simulation mode
+*/
+static int
+wl_btcoex_dynctl_sim(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0, opt_err;
+	miniopt_t to;
+	void *ptr;
+	dynctl_sim_t *sim = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* get current profile */
+	if ((err = wlu_var_getbuf(wl,
+			"btc_dynctl_sim", NULL, 0, &ptr) < 0)) {
+		printf("btc_dynctl: getbuf ioctl failed\n");
+			return err;
+	}
+
+	if (*++argv) {
+		/* some arguments are present, do set or help  */
+
+		if (argv[0][0] == 'h' ||
+			argv[0][0] == '?') {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		sim = calloc(1, sizeof(dynctl_sim_t));
+		if (sim == NULL)
+			return BCME_NOMEM;
+
+		/* copy current ioctl buf into local var */
+		bcopy(ptr, sim, sizeof(dynctl_sim_t));
+
+		/* 1st parameter is on/off ( 0 | 1)  */
+		if (*argv[0] == '1') {
+			/* sim enabled */
+			sim->sim_on = TRUE;
+		}
+		else  if (*argv[0] == '0') {
+			/* sim disabled */
+			sim->sim_on = FALSE;
+		}
+
+		++argv;
+
+		miniopt_init(&to, __FUNCTION__, NULL, FALSE);
+
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+				if (opt_err == 1) {
+					err = BCME_USAGE_ERROR;
+					goto exit;
+				}
+				argv += to.consumed;
+			if (to.opt == 'b') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" sim_btpwr\n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					sim->btpwr = to.val;
+				}
+
+				if (to.opt == 'r') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" sim_btrssi\n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					sim->btrssi = to.val;
+				}
+
+				if (to.opt == 'w') {
+					if (!to.good_int) {
+						fprintf(stderr, "could not parse %s as an int for"
+							" sim_wlrssi\n", to.valstr);
+						err = BCME_BADARG;
+						goto exit;
+					}
+					sim->wlrssi = to.val;
+				}
+		}
+
+			/* write back modified structure */
+		if ((err = wlu_var_setbuf(wl, "btc_dynctl_sim", sim,
+			sizeof(dynctl_sim_t)) < 0)) {
+			printf("%s: failed to set %d\n", cmd->name, err);
+		}
+	} else {
+		/* get */
+		sim = ptr;
+		printf("btc dynctl simulation mode:%s\n BT pwr:%ddBm\n"
+			" BT rssi:%ddBm\n WL ssi:%ddBm\n",
+			sim->sim_on?"On":"Off",
+			sim->btpwr, sim->btrssi, sim->wlrssi);
+		sim = NULL;
+	}
+
+exit:
+	if (sim)
+		free(sim);
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_btcx.c b/wl/src/wl/exe/wluc_btcx.c
new file mode 100644
index 0000000..bb30beb
--- /dev/null
+++ b/wl/src/wl/exe/wluc_btcx.c
@@ -0,0 +1,444 @@
+/*
+ * wl btcx command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_btcx.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <miniopt.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_btc_profile;
+
+#define WL_BTCPROFILE_USAGE \
+"Usage:\n" \
+"\t -p profile_index [-e mode_strong_wl_bt_rssi] [-f mode_weak_wl_rssi]" \
+" [-g  mode_weak_bt_rssi] [-h mode_weak_wl_bt_rssi]\n" \
+"\t [-W mode_wl_hi_lo_rssi_thresh] [-w mode_wl_lo_hi_rssi_thresh]" \
+" [-B mode_bt_hi_lo_rssi_thresh] [-b mode_bt_lo_hi_rssi_thresh]\n" \
+"\t [-D desense_wl_hi_lo_rssi_thresh] [-d desense_wl_lo_hi_rssi_thresh]\n" \
+"\t [-A ack_pwr_wl_hi_lo_rssi_thresh] [-a ack_pwr_wl_lo_hi_rssi_thresh]\n" \
+"\t [-T tx_pwr_wl_hi_lo_rssi_thresh] [-t tx_pwr_wl_lo_hi_rssi_thresh]\n" \
+"\t [-l desense_level[0] desense_level[1] desense_level[2]] : desense level per chain\n" \
+"\t [-X ack_pwr_strong_wl[0] ack_pwr_strong_wl[1] ack_pwr_strong_wl[2]] :" \
+" ACK power per chain at strong RSSI\n" \
+"\t [-x ack_pwr_weak_wl[0] ack_pwr_weak_wl[1] ack_pwr_weak_wl[2]] :" \
+" ACK power per chain at weak RSSI\n" \
+"\t [-Y tx_pwr_strong_wl[0] tx_pwr_strong_wl[1] tx_pwr_strong_wl[2]] :" \
+" Tx power per chain at strong RSSI\n" \
+"\t [-y tx_pwr_weak_wl[0] tx_pwr_weak_wl[1] tx_pwr_weak_wl[2]] :" \
+" Tx power per chain at weak RSSI\n\n"
+
+static cmd_t wl_btcx_cmds[] = {
+	{ "btc_params", wlu_reg2args, WLC_GET_VAR, WLC_SET_VAR, "g/set BT Coex parameters"},
+	{ "btc_flags", wlu_reg2args, WLC_GET_VAR, WLC_SET_VAR, "g/set BT Coex flags"},
+	{ "btc_profile", wl_btc_profile, WLC_GET_VAR, WLC_SET_VAR, WL_BTCPROFILE_USAGE},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_btcx_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register btcx commands */
+	wl_module_cmds_register(wl_btcx_cmds);
+}
+
+static void
+wl_btc_print_profile(wlc_btcx_profile_v1_t *pbtcx_profile)
+{
+	int i;
+	uint8 chain_attr_count = pbtcx_profile->chain_attr_count;
+	/* Basic profile information */
+	printf("Profile Version: %u\n"
+			"Profile Size: %u\n"
+			"Profile Initialized: %s\n"
+			"Number of Tx chains: %u\n"
+			"Profile Index: %u\n"
+			"BTC mode under strong WLAN and BT RSSI: %u\n"
+			"BTC mode under weak WLAN RSSI: %u\n"
+			"BTC mode under weak BT RSSI: %u\n"
+			"BTC mode under weak WLAN and BT RSSI: %u\n",
+			pbtcx_profile->version,
+			pbtcx_profile->length,
+			pbtcx_profile->init ? "Yes" : "No",
+			pbtcx_profile->chain_attr_count,
+			pbtcx_profile->profile_index,
+			pbtcx_profile->mode_strong_wl_bt,
+			pbtcx_profile->mode_weak_wl,
+			pbtcx_profile->mode_weak_bt,
+			pbtcx_profile->mode_weak_wl_bt);
+	/* Threshold information */
+	printf("WLAN strong to weak RSSI threshold for mode change: %d\n"
+			"WLAN weak to strong RSSI threshold for mode change: %d\n"
+			"BT strong to weak RSSI threshold for mode change: %d\n"
+			"BT weak to strong RSSI threshold for mode change: %d\n"
+			"WLAN strong to weak RSSI threshold for desense: %d\n"
+			"WLAN weak to strong RSSI threshold for desense: %d\n"
+			"WLAN strong to weak RSSI threshold for ACK power: %d\n"
+			"WLAN weak to strong RSSI threshold for ACK power: %d\n"
+			"WLAN strong to weak RSSI threshold for Tx power: %d\n"
+			"WLAN weak to strong RSSI threshold for Tx power: %d\n",
+			pbtcx_profile->mode_wl_hi_lo_rssi_thresh,
+			pbtcx_profile->mode_wl_lo_hi_rssi_thresh,
+			pbtcx_profile->mode_bt_hi_lo_rssi_thresh,
+			pbtcx_profile->mode_bt_lo_hi_rssi_thresh,
+			pbtcx_profile->desense_wl_hi_lo_rssi_thresh,
+			pbtcx_profile->desense_wl_lo_hi_rssi_thresh,
+			pbtcx_profile->ack_pwr_wl_hi_lo_rssi_thresh,
+			pbtcx_profile->ack_pwr_wl_lo_hi_rssi_thresh,
+			pbtcx_profile->tx_pwr_wl_hi_lo_rssi_thresh,
+			pbtcx_profile->tx_pwr_wl_lo_hi_rssi_thresh);
+	/* Desense and Power values per core */
+	printf("--- Desense and power limits per core ---\n");
+	for (i = 0; i < chain_attr_count; i++) {
+		printf("Core %u:\t desense level:%d\t"
+				"ACK power strong RSSI:%d\t"
+				"ACK power weak RSSI:%d\t"
+				"Tx power strong RSSI:%d\t"
+				"Tx power weak RSSI:%d\n", i,
+				pbtcx_profile->chain_attr[i].desense_level,
+				pbtcx_profile->chain_attr[i].ack_pwr_strong_rssi,
+				pbtcx_profile->chain_attr[i].ack_pwr_weak_rssi,
+				pbtcx_profile->chain_attr[i].tx_pwr_strong_rssi,
+				pbtcx_profile->chain_attr[i].tx_pwr_weak_rssi);
+	}
+}
+
+/* This IOVAR does a read-modify-write of the user specified profile */
+/* Since the utility does not know about the number of Tx chains on the device */
+/* We use the MAX_UCM_CHAINS to size the variable length array to pull the IO buffer */
+/* Once the buffer is modified by the user, the wlu layer passes the buffer back to driver */
+/* This buffer is sized by the number of TX chains (chain_attr_count) on the device */
+static int
+wl_btc_profile(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr = NULL;
+	wlc_btcx_profile_v1_t *pbtcx_profile = NULL;
+	wlc_btcx_chain_attr_t *chain_attr;
+	uint8 chain_attr_count;
+	int8 val;
+	int err, idx, opt_err, ncon;
+	char *endptr = NULL;
+	miniopt_t to;
+	size_t ucm_prof_sz = sizeof(*pbtcx_profile)
+		+ MAX_UCM_CHAINS*sizeof(pbtcx_profile->chain_attr[1]);
+
+	/* discard the command name */
+	++argv;
+	miniopt_init(&to, __FUNCTION__, NULL, FALSE);
+
+	/* First extract the profile index */
+	opt_err = miniopt(&to, argv);
+	if (opt_err == 0) {
+		if (to.opt == 'p') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for"
+					" the profile index\n", __FUNCTION__, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (to.uval >= MAX_UCM_PROFILES) {
+				fprintf(stderr, "Profile selected is out of range.\n");
+				err = BCME_RANGE;
+				goto exit;
+			} else {
+				idx = to.uval;
+			}
+		} else {
+			fprintf(stderr, "Invalid first option. "
+				"Please select a profile first.\n");
+			err = BCME_BADOPTION;
+			goto exit;
+		}
+	} else {
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	/* Get the relevant btc profile */
+	if (ucm_prof_sz > WLC_IOCTL_SMLEN) {
+		err = BCME_BUFTOOSHORT;
+		goto exit;
+	}
+
+	if ((err = wlu_var_getbuf_sm(wl, cmd->name, &idx, sizeof(idx), &ptr)) < 0) {
+		fprintf(stderr, "%s: getbuf ioctl failed\n", __FUNCTION__);
+		err = BCME_ERROR;
+		goto exit;
+	}
+
+	/* WL utility will pull MAX_UCM_CHAINS size variable array */
+	/* however the FW mallocs only chain_attr_count size variable array */
+	pbtcx_profile = calloc(1, ucm_prof_sz);
+	if (pbtcx_profile == NULL) {
+		err = BCME_NOMEM;
+		goto exit;
+	}
+	memcpy(pbtcx_profile, ptr, ucm_prof_sz);
+
+	if (pbtcx_profile->version != UCM_PROFILE_VERSION_1) {
+		err = BCME_VERSION;
+		goto exit;
+	}
+
+	chain_attr_count = pbtcx_profile->chain_attr_count;
+	if (chain_attr_count > MAX_UCM_CHAINS) {
+		fprintf(stderr, "number of Tx chains (%u) on the device exceeds"
+			" the maximum supported chains (%u)\n", chain_attr_count,
+			MAX_UCM_CHAINS);
+		err = BCME_ERROR;
+		goto exit;
+	}
+
+	argv += to.consumed;
+	chain_attr = pbtcx_profile->chain_attr;
+
+	/* Get: no more arguments */
+	if (*argv == NULL) {
+		wl_btc_print_profile(pbtcx_profile);
+	} else {
+	/* Set: more arguments to be parsed */
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+
+			if (!to.good_int) {
+				fprintf(stderr, "could not parse %s as an int for"
+					" option -%c\n", to.valstr, to.opt);
+				err = BCME_BADARG;
+				goto exit;
+			}
+
+			switch (to.opt) {
+				case 'e' :
+					pbtcx_profile->mode_strong_wl_bt = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'f' :
+					pbtcx_profile->mode_weak_wl = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'g' :
+					pbtcx_profile->mode_weak_bt = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'h' :
+					pbtcx_profile->mode_weak_wl_bt = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'W' :
+					pbtcx_profile->mode_wl_hi_lo_rssi_thresh = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'w' :
+					pbtcx_profile->mode_wl_lo_hi_rssi_thresh = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'B' :
+					pbtcx_profile->mode_bt_hi_lo_rssi_thresh = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'b' :
+					pbtcx_profile->mode_bt_lo_hi_rssi_thresh = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'D' :
+					pbtcx_profile->desense_wl_hi_lo_rssi_thresh = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'd' :
+					pbtcx_profile->desense_wl_lo_hi_rssi_thresh = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'A' :
+					pbtcx_profile->ack_pwr_wl_hi_lo_rssi_thresh = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'a' :
+					pbtcx_profile->ack_pwr_wl_lo_hi_rssi_thresh = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'T' :
+					pbtcx_profile->tx_pwr_wl_hi_lo_rssi_thresh = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 't' :
+					pbtcx_profile->tx_pwr_wl_lo_hi_rssi_thresh = to.val;
+					ncon  = to.consumed;
+					break;
+
+				case 'l' :
+					argv++;
+					for (idx = 0; idx < chain_attr_count; idx++) {
+						if (*(argv+idx) != NULL) {
+							val = (int8)strtoul(*(argv+idx),
+								&endptr, 0);
+							if (*endptr != '\0') {
+								err = BCME_BADOPTION;
+								goto exit;
+							}
+							chain_attr[idx].desense_level = val;
+						} else {
+							err = BCME_BADLEN;
+							goto exit;
+						}
+					}
+					ncon = idx;
+					break;
+
+				case 'X' :
+					argv++;
+					for (idx = 0; idx < chain_attr_count; idx++) {
+						if (*(argv+idx) != NULL) {
+							val = (int8)strtoul(*(argv+idx),
+								&endptr, 0);
+							if (*endptr != '\0') {
+								err = BCME_BADOPTION;
+								goto exit;
+							}
+							chain_attr[idx].ack_pwr_strong_rssi = val;
+						} else {
+							err = BCME_BADLEN;
+							goto exit;
+						}
+					}
+					ncon = idx;
+					break;
+
+				case 'x' :
+					argv++;
+					for (idx = 0; idx < chain_attr_count; idx++) {
+						if (*(argv+idx) != NULL) {
+							val = (int8)strtoul(*(argv+idx),
+								&endptr, 0);
+							if (*endptr != '\0') {
+								err = BCME_BADOPTION;
+								goto exit;
+							}
+							chain_attr[idx].ack_pwr_weak_rssi = val;
+						} else {
+							err = BCME_BADLEN;
+							goto exit;
+						}
+					}
+					ncon = idx;
+					break;
+
+				case 'Y' :
+					argv++;
+					for (idx = 0; idx < chain_attr_count; idx++) {
+						if (*(argv+idx) != NULL) {
+							val = (int8)strtoul(*(argv+idx),
+								&endptr, 0);
+							if (*endptr != '\0') {
+								err = BCME_BADOPTION;
+								goto exit;
+							}
+							chain_attr[idx].tx_pwr_strong_rssi = val;
+						} else {
+							err = BCME_BADLEN;
+							goto exit;
+						}
+					}
+					ncon = idx;
+					break;
+
+				case 'y' :
+					argv++;
+					for (idx = 0; idx < chain_attr_count; idx++) {
+						if (*(argv+idx) != NULL) {
+							val = (int8)strtoul(*(argv+idx),
+								&endptr, 0);
+							if (*endptr != '\0') {
+								err = BCME_BADOPTION;
+								goto exit;
+							}
+							chain_attr[idx].tx_pwr_weak_rssi = val;
+						} else {
+							err = BCME_BADLEN;
+							goto exit;
+						}
+					}
+					ncon = idx;
+					break;
+
+				default :
+					fprintf(stderr, "Invalid option %c\n", to.opt);
+			}
+			argv += ncon;
+		}
+
+		/* write back using var length array size of pbtcx_profile->chain_attr_count */
+		if ((err = wlu_var_setbuf(wl, cmd->name, pbtcx_profile, sizeof(*pbtcx_profile)
+			+ chain_attr_count*sizeof(pbtcx_profile->chain_attr[1])) < 0)) {
+			fprintf(stderr, "%s: fail to set %d\n", __FUNCTION__, err);
+			err = BCME_ERROR;
+			goto exit;
+		}
+	}
+	err = BCME_OK;
+
+exit:
+	if (pbtcx_profile != NULL)
+		free(pbtcx_profile);
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_cac.c b/wl/src/wl/exe/wluc_cac.c
new file mode 100644
index 0000000..96425c3
--- /dev/null
+++ b/wl/src/wl/exe/wluc_cac.c
@@ -0,0 +1,775 @@
+/*
+ * wl cac command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_cac.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <proto/802.11e.h>
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_cac, wl_tslist, wl_tspec, wl_tslist_ea, wl_tspec_ea, wl_cac_delts_ea;
+static void wl_cac_addts_usage(void);
+static void wl_cac_delts_usage(void);
+static void wl_print_tspec(tspec_arg_t *ts);
+
+static cmd_t wl_cac_cmds[] = {
+	{ "cac_addts", wl_cac, -1, WLC_SET_VAR,
+	"add TSPEC, error if STA is not associated or WME is not enabled\n"
+	"\targ: TSPEC parameter input list"},
+	{ "cac_delts", wl_cac, -1, WLC_SET_VAR,
+	"delete TSPEC, error if STA is not associated or WME is not enabled\n"
+	"\targ: TSINFO for the target tspec"},
+	{ "cac_delts_ea", wl_cac_delts_ea, -1, WLC_SET_VAR,
+	"delete TSPEC, error if STA is not associated or WME is not enabled\n"
+	"\targ1: Desired TSINFO for the target tspec\n"
+	"\targ2: Desired MAC address"},
+	{ "cac_tslist", wl_tslist, WLC_GET_VAR, -1,
+	"Get the list of TSINFO in driver\n"
+	"\teg. 'wl cac_tslist' get a list of TSINFO"},
+	{ "cac_tslist_ea", wl_tslist_ea, WLC_GET_VAR, -1,
+	"Get the list of TSINFO for given STA in driver\n"
+	"\teg. 'wl cac_tslist_ea ea' get a list of TSINFO"},
+	{ "cac_tspec", wl_tspec, WLC_GET_VAR, -1,
+	"Get specific TSPEC with matching TSINFO\n"
+	"\teg. 'wl cac_tspec 0xaa 0xbb 0xcc' where 0xaa 0xbb & 0xcc are TSINFO octets"},
+	{ "cac_tspec_ea", wl_tspec_ea, WLC_GET_VAR, -1,
+	"Get specific TSPEC for given STA with matching TSINFO\n"
+	"\teg. 'wl cac_tspec 0xaa 0xbb 0xcc xx:xx:xx:xx:xx:xx'\n"
+	"\t    where 0xaa 0xbb & 0xcc are TSINFO octets and xx is mac address"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_cac_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register cac commands */
+	wl_module_cmds_register(wl_cac_cmds);
+}
+
+#define NUM_TSLIST_ARG 3		/* minimum number of arguments required for TSLIST */
+#define NUM_TSLIST_PER_EA_ARG 3	/* minimum number of arguments required for TSLIST */
+#define MIN_NUM_DELTS_ARG 4		/* minimum number of arguments required for DELTS */
+#define MIN_NUM_DELTS_EA_ARG 5	/* minimum number of arguments required for DELTS */
+#define MIN_NUM_ADDTS_ARG 20	/* minimum number of arguments required for ADDTS */
+#define PERIODIC_TRAFFIC 1		/* Periodic traffic type */
+#define VO_TID (0 << 1)			/* voice TID */
+#define VI_TID (1 << 1)			/* signal TID */
+#define UPLINK_DIRECTION (0 << 5)	/* uplink direction traffic stream */
+#define DOWNLINK_DIRECTION (1 << 5)	/* downlink direction traffic stream */
+#define BI_DIRECTION (3 << 5)	/* bi direction traffic stream */
+#define EDCA_ACCESS (1 << 7)	/* EDCA access policy */
+#define UAPSD_PSB (1 << 2)		/* U-APSD power saving behavior */
+#define VO_USER_PRIO (6 << 3)	/* voice user priority */
+#define VI_USER_PRIO (4 << 3)	/* signal user priority */
+#define TID_SHIFT 1				/* TID Shift */
+#define UP_SHIFT 3				/* UP Shift */
+
+static void
+wl_cac_format_tspec_htod(tspec_arg_t *tspec_arg)
+{
+	tspec_arg->version = htod16(tspec_arg->version);
+	tspec_arg->length = htod16(tspec_arg->length);
+	tspec_arg->flag = htod32(tspec_arg->flag);
+	tspec_arg->nom_msdu_size = htod16(tspec_arg->nom_msdu_size);
+	tspec_arg->max_msdu_size = htod16(tspec_arg->max_msdu_size);
+	tspec_arg->min_srv_interval = htod32(tspec_arg->min_srv_interval);
+	tspec_arg->max_srv_interval = htod32(tspec_arg->max_srv_interval);
+	tspec_arg->inactivity_interval = htod32(tspec_arg->inactivity_interval);
+	tspec_arg->suspension_interval = htod32(tspec_arg->suspension_interval);
+	tspec_arg->srv_start_time = htod32(tspec_arg->srv_start_time);
+	tspec_arg->min_data_rate = htod32(tspec_arg->min_data_rate);
+	tspec_arg->mean_data_rate = htod32(tspec_arg->mean_data_rate);
+	tspec_arg->peak_data_rate = htod32(tspec_arg->peak_data_rate);
+	tspec_arg->max_burst_size = htod32(tspec_arg->max_burst_size);
+	tspec_arg->delay_bound = htod32(tspec_arg->delay_bound);
+	tspec_arg->min_phy_rate = htod32(tspec_arg->min_phy_rate);
+	tspec_arg->surplus_bw = htod16(tspec_arg->surplus_bw);
+	tspec_arg->medium_time = htod16(tspec_arg->medium_time);
+}
+
+static void
+wl_cac_format_tspec_dtoh(tspec_arg_t *tspec_arg)
+{
+	tspec_arg->version = dtoh16(tspec_arg->version);
+	tspec_arg->length = dtoh16(tspec_arg->length);
+	tspec_arg->flag = dtoh32(tspec_arg->flag);
+	tspec_arg->nom_msdu_size = dtoh16(tspec_arg->nom_msdu_size);
+	tspec_arg->max_msdu_size = dtoh16(tspec_arg->max_msdu_size);
+	tspec_arg->min_srv_interval = dtoh32(tspec_arg->min_srv_interval);
+	tspec_arg->max_srv_interval = dtoh32(tspec_arg->max_srv_interval);
+	tspec_arg->inactivity_interval = dtoh32(tspec_arg->inactivity_interval);
+	tspec_arg->suspension_interval = dtoh32(tspec_arg->suspension_interval);
+	tspec_arg->srv_start_time = dtoh32(tspec_arg->srv_start_time);
+	tspec_arg->min_data_rate = dtoh32(tspec_arg->min_data_rate);
+	tspec_arg->mean_data_rate = dtoh32(tspec_arg->mean_data_rate);
+	tspec_arg->peak_data_rate = dtoh32(tspec_arg->peak_data_rate);
+	tspec_arg->max_burst_size = dtoh32(tspec_arg->max_burst_size);
+	tspec_arg->delay_bound = dtoh32(tspec_arg->delay_bound);
+	tspec_arg->min_phy_rate = dtoh32(tspec_arg->min_phy_rate);
+	tspec_arg->surplus_bw = dtoh16(tspec_arg->surplus_bw);
+	tspec_arg->medium_time = dtoh16(tspec_arg->medium_time);
+
+}
+
+static void wl_cac_addts_usage(void)
+{
+	fprintf(stderr, "Too few arguments\n");
+	fprintf(stderr, "wl cac_addts ver dtoken tid dir psb up a b c d e ...\n");
+	fprintf(stderr, "\twhere ver is the structure version\n");
+	fprintf(stderr, "\twhere dtoken is the dialog token [range 1-255]\n");
+	fprintf(stderr, "\twhere tid is the tspec identifier [range 0-7]\n");
+	fprintf(stderr, "\twhere dir is direction [uplink | downlink | bi-directional]\n");
+	fprintf(stderr, "\twhere psb is power save mode [legacy|U-APSD]\n");
+	fprintf(stderr, "\twhere up is user priority [range 0-7]\n");
+	fprintf(stderr, "\twhere a is the nominal MSDU size\n");
+	fprintf(stderr, "\twhere b is bool for fixed size msdu [ 0 and 1]\n");
+	fprintf(stderr, "\twhere c is the maximum MSDU size\n");
+	fprintf(stderr, "\twhere d is the minimum service interval\n");
+	fprintf(stderr, "\twhere e is the maximum service interval\n");
+	fprintf(stderr, "\twhere f is the inactivity interval\n");
+	fprintf(stderr, "\twhere g is the suspension interval\n");
+	fprintf(stderr, "\twhere h is the minimum data rate\n");
+	fprintf(stderr, "\twhere i is the mean data rate\n");
+	fprintf(stderr, "\twhere j is the peak data rate\n");
+	fprintf(stderr, "\twhere k is the max burst size\n");
+	fprintf(stderr, "\twhere l is the delay bound\n");
+	fprintf(stderr, "\twhere m is the surplus bandwidth [fixed point notation]\n");
+	fprintf(stderr, "\twhere n is the minimum PHY rate\n");
+}
+
+static void wl_cac_delts_usage(void)
+{
+	fprintf(stderr, "Too few arguments\n");
+	fprintf(stderr, "wl cac_delts ver a b c \n");
+	fprintf(stderr, "\twhere ver is the tspec version\n");
+	fprintf(stderr, "\twhere a is byte[0] of tsinfo (bits 0-7)\n");
+	fprintf(stderr, "\twhere b is byte[1] of tsinfo (bits 8-15)\n");
+	fprintf(stderr, "\twhere c is byte[2] of tsinfo (bits 16-23)\n");
+}
+
+static int
+wl_cac(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	int ap_mode = 0;
+	int apsta_mode = 0;
+	int cmd_type = 0;
+	tspec_arg_t tspec_arg;
+	char *endptr = NULL;
+	uint buflen;
+	char *arg1, *user_argv;
+	uint8 direction = BI_DIRECTION;
+	uint8 user_tid, user_prio, user_psb;
+	uint fixed;
+
+
+	if ((err = wlu_iovar_get(wl, "apsta", &apsta_mode, sizeof(apsta_mode))))
+		return err;
+
+	if (!apsta_mode) {
+		if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))))
+			return err;
+		else {
+			if (dtoh32(ap_mode)) {
+				fprintf(stderr,
+					"This command can ONLY be executed on a STA or APSTA\n");
+				return err;
+			}
+		}
+	}
+
+	if (!strcmp(*argv, "cac_addts"))
+		cmd_type = 1;
+	else if (!strcmp(*argv, "cac_delts"))
+		cmd_type = 2;
+	else {
+		fprintf(stderr, "unknown command\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* eat command name */
+	if (!*++argv) {
+		(cmd_type == 1) ? wl_cac_addts_usage():wl_cac_delts_usage();
+		return BCME_BADARG;
+	}
+
+	buflen = sizeof(tspec_arg_t);
+	memset((uint8 *)&tspec_arg, 0, buflen);
+
+	/* get direction option */
+	arg1 = *argv;
+
+	/* Unidirectional DL/UL */
+	if (!strcmp(arg1, "UDL") || (!strcmp(arg1, "UUL")))
+		direction = DOWNLINK_DIRECTION;
+
+	if (cmd_type == 1) {
+		uint argc = 0;
+
+		/* arg count */
+		while (argv[argc])
+			argc++;
+
+		/* required argments */
+		if (argc < MIN_NUM_ADDTS_ARG) {
+			wl_cac_addts_usage();
+			return BCME_USAGE_ERROR;
+		}
+
+		tspec_arg.length = sizeof(tspec_arg_t) - (2 * sizeof(uint16));
+		tspec_arg.version = (uint16)strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.dialog_token = (uint8)strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		user_tid = (uint8)strtol(*argv++, &endptr, 0);
+		user_tid <<= TID_SHIFT;
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		/* store the pointer for parsing */
+		user_argv = *argv++;
+
+		if (!strcmp(user_argv, "uplink"))
+			direction = UPLINK_DIRECTION;
+		else if (!strcmp(user_argv, "downlink"))
+			direction = DOWNLINK_DIRECTION;
+		else if (!strcmp(user_argv, "bi-directional"))
+			direction = BI_DIRECTION;
+		else
+			return BCME_USAGE_ERROR;
+
+		/* store the pointer for parsing */
+		user_argv = *argv++;
+
+		if (!strcmp(user_argv, "legacy"))
+			user_psb = 0;
+		else if (!strcmp(user_argv, "U-APSD"))
+			user_psb = UAPSD_PSB;
+		else
+			return BCME_USAGE_ERROR;
+
+		user_prio = (uint8)strtol(*argv++, &endptr, 0);
+		user_prio <<= UP_SHIFT;
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.tsinfo.octets[0] = (uint8)(user_tid |
+			direction | EDCA_ACCESS);
+
+		tspec_arg.tsinfo.octets[1] = (uint8)(user_prio | user_psb);
+		tspec_arg.tsinfo.octets[2] = 0x00;
+
+		tspec_arg.nom_msdu_size = (uint16)strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		fixed = (uint)strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		if (fixed == 1)
+			tspec_arg.nom_msdu_size |= 0x8000;
+
+		tspec_arg.max_msdu_size = (uint16)strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.min_srv_interval = strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.max_srv_interval = strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.inactivity_interval = strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.suspension_interval = strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.min_data_rate = strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.mean_data_rate = strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.peak_data_rate = strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.max_burst_size = strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.delay_bound = strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.surplus_bw = (uint16)strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.min_phy_rate = strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+		printf("Setting min_phy_rate to 0x%x\n", tspec_arg.min_phy_rate);
+	} else {
+		uint argc = 0;
+
+		/* arg count */
+		while (argv[argc])
+			argc++;
+
+		/* required argments */
+		if (argc < MIN_NUM_DELTS_ARG) {
+			wl_cac_delts_usage();
+			return BCME_USAGE_ERROR;
+		}
+
+		tspec_arg.length = sizeof(tspec_arg_t) - (2 * sizeof(uint16));
+		tspec_arg.version = (uint16)strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.tsinfo.octets[0] = (uint8)strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.tsinfo.octets[1] = (uint8)strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		tspec_arg.tsinfo.octets[2] = (uint8)strtol(*argv++, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+	}
+
+	wl_cac_format_tspec_htod(&tspec_arg);
+	err = wlu_var_setbuf(wl, cmd->name, &tspec_arg, buflen);
+
+	return err;
+}
+
+/* get a list of traffic stream (TSINFO) in driver */
+static int
+wl_tslist(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int i;
+	int ap_mode, err = -1;
+	int apsta_mode = 0;
+	struct tslist *tslist;
+
+	UNUSED_PARAMETER(argv);
+
+
+	if ((err = wlu_iovar_get(wl, "apsta", &apsta_mode, sizeof(apsta_mode))))
+		return err;
+
+	if (!apsta_mode) {
+		if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))))
+			return err;
+		else {
+			if (dtoh32(ap_mode)) {
+				fprintf(stderr,
+					"This command can ONLY be executed on a STA or APSTA\n");
+				return err;
+			}
+		}
+	}
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return err;
+
+	tslist = (struct tslist *)ptr;
+	tslist->count = dtoh32(tslist->count);
+	for (i = 0; i < tslist->count; i++)
+		printf("tsinfo 0x%02X 0x%02X 0x%02X  TID %d  User Prio %d  Direction %d\n",
+		       tslist->tsinfo[i].octets[0],
+		       tslist->tsinfo[i].octets[1],
+		       tslist->tsinfo[i].octets[2],
+		       WLC_CAC_GET_TID(tslist->tsinfo[i]),
+		       WLC_CAC_GET_USER_PRIO(tslist->tsinfo[i]),
+		       WLC_CAC_GET_DIR(tslist->tsinfo[i]));
+
+	return 0;
+}
+
+/* get specific TSPEC in driver */
+static int
+wl_tspec(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int ap_mode, err = -1;
+	tspec_arg_t *ts, tspec_arg;
+	char *temp = NULL;
+	uint argc = 0;
+
+	if ((wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))))
+		return err;
+	ap_mode = dtoh32(ap_mode);
+
+	if (ap_mode) {
+		fprintf(stderr, "This command can only be executed on the STA\n");
+		return err;
+	}
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	while (argv[argc])
+		argc++;
+
+	/* required argments */
+	if (argc < NUM_TSLIST_ARG) {
+		fprintf(stderr, "Too few arguments\n");
+		fprintf(stderr, "wl cac_tspec 0xaa 0xbb 0xcc \n");
+		fprintf(stderr, "\twhere 0xaa is byte[0] of tsinfo (bits 0-7)\n");
+		fprintf(stderr, "\twhere 0xbb is byte[1] of tsinfo (bits 8-15)\n");
+		fprintf(stderr, "\twhere 0xcc is byte[2] of tsinfo (bits 16-23)\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	memset((uint8 *)&tspec_arg, 0, sizeof(tspec_arg_t));
+
+	tspec_arg.tsinfo.octets[0] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+
+	tspec_arg.tsinfo.octets[1] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+
+	tspec_arg.tsinfo.octets[2] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+	if ((err = wlu_var_getbuf(wl, cmd->name, &tspec_arg, sizeof(tspec_arg_t), &ptr)) < 0)
+		return err;
+
+	ts = (tspec_arg_t *)ptr;
+	wl_cac_format_tspec_dtoh(ts);
+	wl_print_tspec(ts);
+
+	return 0;
+}
+
+/* get the tspec list for the given station */
+static int
+wl_tslist_ea(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int i;
+	int ap_mode, err = -1;
+	struct tslist *tslist;
+	scb_val_t scb_val;
+
+
+	if (!*++argv) {
+		printf("MAC address must be specified\n");
+		return BCME_USAGE_ERROR;
+	} else if (!wl_ether_atoe(*argv, &scb_val.ea)) {
+		printf("Malformed MAC address parameter\n");
+		return BCME_USAGE_ERROR;
+	}
+	if ((err = wlu_get(wl, WLC_GET_AP, &ap_mode, sizeof(ap_mode))))
+		return err;
+
+	ap_mode = dtoh32(ap_mode);
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, &scb_val.ea, ETHER_ADDR_LEN, &ptr)) < 0)
+		return err;
+
+	tslist = (struct tslist *)ptr;
+
+	for (i = 0; i < tslist->count; i++)
+		printf("tsinfo 0x%02X 0x%02X 0x%02X  TID %d  User Prio %d  Direction %d\n",
+		       tslist->tsinfo[i].octets[0],
+		       tslist->tsinfo[i].octets[1],
+		       tslist->tsinfo[i].octets[2],
+		       WLC_CAC_GET_TID(tslist->tsinfo[i]),
+		       WLC_CAC_GET_USER_PRIO(tslist->tsinfo[i]),
+		       WLC_CAC_GET_DIR(tslist->tsinfo[i]));
+
+	return 0;
+
+}
+
+/* get specific TSPEC for a STA */
+static int
+wl_tspec_ea(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int err = -1;
+	tspec_per_sta_arg_t tsea;
+	tspec_arg_t *ts;
+	char *temp;
+	uint argc = 0;
+
+	/* eat command name */
+	argv++;
+
+	while (argv[argc])
+		argc++;
+
+	/* required argments */
+	if (argc < (NUM_TSLIST_PER_EA_ARG + 1)) {
+		fprintf(stderr, "Too few arguments\n");
+		fprintf(stderr, "wl cac_tspec 0xaa 0xbb 0xcc xx:xx:xx:xx:xx:xx\n");
+		fprintf(stderr, "\twhere 0xaa is byte[0] of tsinfo (bits 0-7)\n");
+		fprintf(stderr, "\twhere 0xbb is byte[1] of tsinfo (bits 8-15)\n");
+		fprintf(stderr, "\twhere 0xcc is byte[2] of tsinfo (bits 16-23)\n");
+		fprintf(stderr, "\twhere xx:xx:xx:xx:xx:xx is mac address )\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	memset((uint8 *)&tsea, 0, sizeof(tspec_per_sta_arg_t));
+
+	ts = &tsea.ts;
+
+	ts->tsinfo.octets[0] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+
+	ts->tsinfo.octets[1] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+
+	ts->tsinfo.octets[2] = (uint8)strtol(*argv++, &temp, 0);
+	if (*temp != '\0')
+		return BCME_USAGE_ERROR;
+
+	/* add the ether address after tsinfo */
+	if (!*argv) {
+		printf("MAC address must be specified\n");
+		return BCME_USAGE_ERROR;
+	} else if (!wl_ether_atoe(*argv, &tsea.ea)) {
+		printf("Malformed MAC address parameter\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, &tsea, sizeof(tspec_per_sta_arg_t), &ptr)) < 0)
+		return err;
+
+	ts = (tspec_arg_t *)ptr;
+	wl_cac_format_tspec_dtoh(ts);
+	wl_print_tspec(ts);
+	return 0;
+
+}
+
+static const uint8 wlu_wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE,
+             AC_BE };
+static const uint8 wlu_prio2fifo[NUMPRIO] = {
+	0,	/* 0	BE	AC_BE	Best Effort */
+	1,	/* 1	BK	AC_BK	Background */
+	2,	/* 2	--	AC_BK	Background */
+	3,	/* 3	EE	AC_BE	Best Effort */
+	4,	/* 4	CL	AC_VI	Video */
+	5,	/* 5	VI	AC_VI	Video */
+	6,	/* 6	VO	AC_VO	Voice */
+	7	/* 7	NC	AC_VO	Voice */
+};
+#define WME_PRIO2AC(prio)	wlu_wme_fifo2ac[wlu_prio2fifo[(prio)]]
+
+static void
+wl_print_tspec(tspec_arg_t *ts)
+{
+	const char *str;
+	if (ts->version != TSPEC_ARG_VERSION) {
+		printf("\tIncorrect version of TSPEC struct: expected %d; got %d\n",
+		       TSPEC_ARG_VERSION, ts->version);
+		return;
+	}
+
+	if (ts->length < (sizeof(tspec_arg_t) - (2 * sizeof(uint16)))) {
+		printf("\tTSPEC arg length too short: expected %d; got %d\n",
+		       (int)(sizeof(tspec_arg_t) - (2 * sizeof(uint16))), ts->length);
+		return;
+	}
+
+	switch (ts->flag & TSPEC_STATUS_MASK) {
+		case TSPEC_PENDING:
+			str = "PENDING";
+			break;
+		case TSPEC_ACCEPTED:
+			str = "ACCEPTED";
+			break;
+		case TSPEC_REJECTED:
+			str = "REJECTED";
+			break;
+		default:
+			str = "UNKNOWN";
+			break;
+	}
+
+	printf("version %d\n", ts->version);
+	printf("length %d\n", ts->length);
+
+	printf("TID %d %s\n", WLC_CAC_GET_TID(ts->tsinfo), str);
+	printf("tsinfo 0x%02x 0x%02x 0x%02x\n", ts->tsinfo.octets[0],
+	       ts->tsinfo.octets[1], ts->tsinfo.octets[2]);
+
+	/* breakout bitfields for apsd */
+	if (WLC_CAC_GET_PSB(ts->tsinfo)) {
+		int ac = WME_PRIO2AC(WLC_CAC_GET_USER_PRIO(ts->tsinfo));
+		switch (WLC_CAC_GET_DIR(ts->tsinfo)) {
+			case (TS_INFO_UPLINK >> TS_INFO_DIRECTION_SHIFT):
+				printf("AC[%d] : Trigger enabled\n", ac);
+				break;
+
+			case (TS_INFO_DOWNLINK >> TS_INFO_DIRECTION_SHIFT):
+				printf("AC[%d] : Delivery enabled\n", ac);
+				break;
+
+			case (TS_INFO_BIDIRECTIONAL >>
+				TS_INFO_DIRECTION_SHIFT):
+				printf("AC[%d] : Trig & Delv enabled\n", ac);
+				break;
+		}
+	} else {
+		int ac;
+		ac = WME_PRIO2AC(WLC_CAC_GET_USER_PRIO(ts->tsinfo));
+		printf("AC [%d] : Legacy Power save\n", ac);
+	}
+
+
+	printf("nom_msdu_size %d %s\n", (ts->nom_msdu_size & 0x7fff),
+	       ((ts->nom_msdu_size & 0x8000) ? "fixed size" : ""));
+	printf("max_msdu_size %d\n", ts->max_msdu_size);
+	printf("min_srv_interval %d\n", ts->min_srv_interval);
+	printf("max_srv_interval %d\n", ts->max_srv_interval);
+	printf("inactivity_interval %d\n", ts->inactivity_interval);
+	printf("suspension_interval %d\n", ts->suspension_interval);
+	printf("srv_start_time %d\n", ts->srv_start_time);
+	printf("min_data_rate %d\n", ts->min_data_rate);
+	printf("mean_data_rate %d\n", ts->mean_data_rate);
+	printf("peak_data_rate %d\n", ts->peak_data_rate);
+	printf("max_burst_size %d\n", ts->max_burst_size);
+	printf("delay_bound %d\n", ts->delay_bound);
+	printf("min_phy_rate %d\n", ts->min_phy_rate);
+	printf("surplus_bw %d\n", ts->surplus_bw);
+	printf("medium_time %d\n", ts->medium_time);
+}
+
+
+/* send delts for a specific ea */
+/* TODO : Club this with wl_tspec_ea */
+static int
+wl_cac_delts_ea(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int err = -1;
+	char *endptr = NULL;
+	tspec_per_sta_arg_t tsea;
+	tspec_arg_t *ts;
+	uint argc = 0;
+
+	/* eat command name */
+	argv++;
+
+	while (argv[argc])
+		argc++;
+
+	/* required argments */
+	if (argc < (NUM_TSLIST_PER_EA_ARG + 1)) {
+		fprintf(stderr, "Too few arguments\n");
+		fprintf(stderr, "wl cac_delts_ea ver 0xaa 0xbb 0xcc xx:xx:xx:xx:xx:xx\n");
+		fprintf(stderr, "\twhere ver is the tspec version\n");
+		fprintf(stderr, "\twhere 0xaa is byte[0] of tsinfo (bits 0-7)\n");
+		fprintf(stderr, "\twhere 0xbb is byte[1] of tsinfo (bits 8-15)\n");
+		fprintf(stderr, "\twhere 0xcc is byte[2] of tsinfo (bits 16-23)\n");
+		fprintf(stderr, "\twhere xx:xx:xx:xx:xx:xx is mac address )\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	memset((uint8 *)&tsea, 0, sizeof(tspec_per_sta_arg_t));
+
+	ts = &tsea.ts;
+
+	ts->length = sizeof(tspec_arg_t) - (2 * sizeof(uint16));
+	ts->version = (uint16)strtol(*argv++, &endptr, 0);
+
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	ts->tsinfo.octets[0] = (uint8)strtol(*argv++, &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	ts->tsinfo.octets[1] = (uint8)strtol(*argv++, &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	ts->tsinfo.octets[2] = (uint8)strtol(*argv++, &endptr, 0);
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+
+	/* add the ether address after tsinfo */
+	if (!*argv) {
+		printf("MAC address must be specified\n");
+		return BCME_USAGE_ERROR;
+	} else if (!wl_ether_atoe(*argv, &tsea.ea)) {
+		printf("Malformed MAC address parameter\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	wl_cac_format_tspec_htod(ts);
+	if ((err = wlu_var_getbuf(wl, cmd->name, &tsea, sizeof(tspec_per_sta_arg_t), &ptr)) < 0)
+		return err;
+
+	return 0;
+
+}
diff --git a/wl/src/wl/exe/wluc_ecounters.c b/wl/src/wl/exe/wluc_ecounters.c
new file mode 100644
index 0000000..5d2fe1f
--- /dev/null
+++ b/wl/src/wl/exe/wluc_ecounters.c
@@ -0,0 +1,340 @@
+/*
+ * wl ecounters command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id:$
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#if defined(linux)
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* linux */
+
+#include <wlioctl.h>
+
+#if defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+#include <sys/stat.h>
+#include <errno.h>
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <proto/802.3.h>
+#include <proto/bcmip.h>
+#include <proto/bcmipv6.h>
+#include <proto/bcmtcp.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#define EVENT_LOG_DUMPER
+#include <event_log.h>
+
+static cmd_func_t wl_ecounters_config;
+static cmd_func_t wl_event_ecounters_config;
+
+static cmd_t wl_ecounters_cmds[] = {
+	{ "ecounters", wl_ecounters_config, -1, WLC_SET_VAR,
+	"\tDescription: Configure ecounters to retrieve statistics at periodic intervals"
+	"\tusage: wl ecounters <event_log_set_num> <event_log_buffer_size> "
+	"<periodicity in secs> <num_events> <event_log_tag_num1> <event_log_tag_num2>..."
+	"\tTo disable ecounters:  set periodicity and num_events = 0 with no tags. "
+	"For ex. wl ecounters 0 0 0 0"
+	},
+	{ "event_ecounters", wl_event_ecounters_config, -1, WLC_SET_VAR,
+	"\tDescription: Configure WLC events to trigger ecounters when an event to be \n"
+	"\tgenerated matches a hosts supplied events mask\n"
+	"\tusage: wl event_ecounters -m mask [-s set -t <tag> [<tag> ...]]\n"
+	"\twhere mask is hex bitmask of events\n"
+	"\tset is the event log set where ecounters should write data.\n"
+	"\ttag(s) is/are event log tags that ecounters should report.\n"
+	"\tNote that the host must initialize event log set of\n"
+	"\tinterest with event_log_set_init iovar\n"
+	"\tTo disable event ecounters configuration:\n"
+	"\twl event_ecounters -m 0x0\n"
+	},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+/* Command format: wl counters <event log set> < event log buffer size>
+ * <periodicity in secs> <number of events> <tag1> <tag 2> ...
+ */
+#define ECOUNTERS_ARG_EVENT_LOG_SET_POS			0
+#define ECOUNTERS_ARG_EVENT_LOG_BUFFER_SIZE_POS		1
+#define ECOUNTERS_ARG_PERIODICITY_POS			2
+#define ECOUNTERS_ARG_NUM_EVENTS			3
+#define ECOUNTERS_NUM_BASIC_ARGS			4
+
+static int wl_ecounters_config(void *wl, cmd_t *cmd, char **argv)
+{
+	ecounters_config_request_t *p_config;
+	int	rc = 0;
+	uint	i, argc, len, alloc_size_adjustment;
+	uint	ecounters_basic_args[ECOUNTERS_NUM_BASIC_ARGS];
+
+	/* Count <type> args and allocate buffer */
+	for (argv++, argc = 0; argv[argc]; argc++);
+
+	if (argc < ECOUNTERS_NUM_BASIC_ARGS) {
+		fprintf(stderr, "Minimum 4 arguments are required for Ecounters. \n");
+		fprintf(stderr, "wl ecounters <event log set > < event log buffer size> "
+				"<periodicity> <num_events> <tag1> <tag2>..\n");
+		return BCME_ERROR;
+	}
+
+	for (i = 0; i < ECOUNTERS_NUM_BASIC_ARGS; i++, argv++) {
+		char *endptr;
+		ecounters_basic_args[i] = strtoul(*argv, &endptr, 0);
+		argc--;
+		if (*endptr != '\0') {
+			fprintf(stderr, "Type '%s' (arg %d) not a number?\n", *argv, i);
+			return BCME_ERROR;
+		}
+	}
+
+	if (ecounters_basic_args[ECOUNTERS_ARG_EVENT_LOG_SET_POS] > NUM_EVENT_LOG_SETS)
+	{
+		fprintf(stderr, " Event log set > MAX sets (%d)\n", NUM_EVENT_LOG_SETS);
+		return BCME_ERROR;
+	}
+
+	if (ecounters_basic_args[ECOUNTERS_ARG_EVENT_LOG_BUFFER_SIZE_POS] >
+		EVENT_LOG_MAX_BLOCK_SIZE)
+	{
+		fprintf(stderr, " Event log buffer size > MAX buffer size (%d)\n",
+			EVENT_LOG_MAX_BLOCK_SIZE);
+		return BCME_ERROR;
+	}
+
+	/* Allocate memory for structure to be sent. If no types were passed, allocated
+	 * config structure must have aleast one type present even if not used.
+	 */
+	alloc_size_adjustment = (argc) ? argc : 1;
+
+	len = OFFSETOF(ecounters_config_request_t, type) +
+		(alloc_size_adjustment) * sizeof(uint16);
+	p_config = (ecounters_config_request_t *)malloc(len);
+	if (p_config == NULL) {
+		fprintf(stderr, "malloc failed to allocate %d bytes\n", len);
+		return -1;
+	}
+	memset(p_config, 0, len);
+
+	p_config->version = ECOUNTERS_VERSION_1;
+	p_config->set =
+		ecounters_basic_args[ECOUNTERS_ARG_EVENT_LOG_SET_POS];
+	p_config->size =
+		ecounters_basic_args[ECOUNTERS_ARG_EVENT_LOG_BUFFER_SIZE_POS];
+	p_config->timeout =
+		ecounters_basic_args[ECOUNTERS_ARG_PERIODICITY_POS];
+	p_config->num_events =
+		ecounters_basic_args[ECOUNTERS_ARG_NUM_EVENTS];
+
+	/* No types were passed. So ntypes = 0. */
+	p_config->ntypes = (argc == 0) ? 0 : argc;
+	for (i = 0; i < argc; i++, argv++) {
+		char *endptr;
+		p_config->type[i] = strtoul(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "Type '%s' (arg %d) not a number?\n", *argv, i);
+			free(p_config);
+			return -1;
+		}
+	}
+
+	rc = wlu_var_setbuf(wl, cmd->name, p_config, len);
+	free(p_config);
+	return rc;
+}
+
+/* Command format: wl event_ecounters -m <hex string> -s <set> -t <tag list> */
+static int wl_event_ecounters_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc = 0, err = 0;
+	char *mask_arg = NULL, *set_arg = NULL;
+	uint16 masksize, eventmsgs_len, trig_config_len, set, i;
+	ecounters_eventmsgs_ext_t *eventmsgs;
+	ecounters_trigger_config_t *trigger_config;
+	uint8* iovar_data_ptr = NULL;
+
+	/* Count <type> args and allocate buffer */
+	for (argv++, argc = 0; argv[argc]; argc++);
+
+	/* Look for -m. Position of these arguments is fixed. */
+	if ((*argv) && !strcmp(*argv, "-m")) {
+		mask_arg = *++argv;
+		if (!mask_arg) {
+			fprintf(stderr, "Missing argument to -m option\n");
+			return BCME_USAGE_ERROR;
+		}
+		/* Consumed 2 arguments -m and its argument */
+		argc -= 2;
+		argv++;
+	}
+	else {
+		fprintf(stderr, "Missing -m <hex string> option\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Skip any 0x if there are any */
+	if (mask_arg[0] == '0' && mask_arg[1] == 'x')
+		mask_arg += 2;
+
+	/* adjust the length. If there are  <= 2 characters, minimum 1 byte id required */
+	masksize = (strlen(mask_arg)/2);
+	if (masksize < 1) {
+		masksize = 1;
+	}
+	masksize = MIN(masksize, WL_EVENTING_MASK_LEN);
+	eventmsgs_len =
+		ROUNDUP((masksize + ECOUNTERS_EVENTMSGS_EXT_MASK_OFFSET), sizeof(uint32));
+	/* send user mask size up to WL_EVENTING_MASK_MAX_LEN */
+	eventmsgs = (ecounters_eventmsgs_ext_t*)malloc(eventmsgs_len);
+
+	if (eventmsgs == NULL) {
+		fprintf(stderr, "fail to allocate event_msgs"
+			"structure of %d bytes\n", eventmsgs_len);
+		return BCME_NOMEM;
+	}
+	memset((void*)eventmsgs, 0, eventmsgs_len);
+	err = hexstrtobitvec(mask_arg, eventmsgs->mask, masksize);
+	if (err) {
+		fprintf(stderr, "hexstrtobitvec() error: %d\n", err);
+		free(eventmsgs);
+		return BCME_BADARG;
+	}
+	eventmsgs->len = masksize;
+	eventmsgs->version = ECOUNTERS_EVENTMSGS_VERSION_1;
+
+	/* if all entries in mask = 0 => disable command
+	 * the tags do not matter in this case
+	 * A disable command results in ecounters config release in dongle
+	 */
+	for (i = 0; i < eventmsgs->len; i++) {
+		if (eventmsgs->mask[i])
+			break;
+	}
+
+	if (i == eventmsgs->len) {
+		/* Send only mask no trigger config */
+		iovar_data_ptr = (uint8*)eventmsgs;
+		trig_config_len = 0;
+	}
+	else {
+		/* look for -s */
+		if ((*argv) && !strcmp(*argv, "-s")) {
+			set_arg = *++argv;
+			if (!set_arg) {
+				if (eventmsgs)
+					free(eventmsgs);
+				fprintf(stderr, "Missing argument to -s option\n");
+				return BCME_USAGE_ERROR;
+			}
+			/* Consumed 2 arguments -s and its argument */
+			argc -= 2;
+			argv++;
+		}
+		else {
+			if (eventmsgs)
+				free(eventmsgs);
+			fprintf(stderr, "Missing -s <set> option\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		set = atoi(set_arg);
+		/* look for -t */
+		if ((*argv) && !strcmp(*argv, "-t")) {
+			/* Consumed only one argument. This will result in argc = 0
+			 * but since there is no more argv, the if condition below
+			 * will be satisfied and we will get out.
+			 */
+			argc--;
+			if (!(*++argv)) {
+				if (eventmsgs)
+					free(eventmsgs);
+				fprintf(stderr, "argc: %d Missing argument to -t option\n", argc);
+				return BCME_USAGE_ERROR;
+			}
+		}
+		else {
+			if (eventmsgs)
+				free(eventmsgs);
+			fprintf(stderr, "Missing -t <tag list> option\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		trig_config_len = ECOUNTERS_TRIG_CONFIG_TYPE_OFFSET;
+		trig_config_len += argc * sizeof(uint16);
+
+		iovar_data_ptr = (uint8*)malloc(trig_config_len + eventmsgs_len);
+		if (iovar_data_ptr == NULL) {
+			fprintf(stderr, "fail to allocate memory to populate iovar"
+				" %d bytes\n", eventmsgs_len + trig_config_len);
+			free(eventmsgs);
+			return BCME_NOMEM;
+		}
+
+		/* copy eventmsgs struct in the allocate dmemory */
+		memcpy(iovar_data_ptr, eventmsgs, eventmsgs_len);
+		trigger_config = (ecounters_trigger_config_t *)(iovar_data_ptr + eventmsgs_len);
+
+		trigger_config->version = ECOUNTERS_TRIGGER_CONFIG_VERSION_1;
+		trigger_config->set = set;
+		trigger_config->ntypes = argc;
+
+		/* we don't need this anymore. Release any associated memories */
+		free(eventmsgs);
+
+		for (i = 0; i < argc; i++, argv++) {
+			char *endptr;
+			trigger_config->type[i] = strtoul(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				fprintf(stderr, "Type '%s' (tag %d) not a number?\n", *argv, i);
+				free(iovar_data_ptr);
+				return BCME_ERROR;
+			}
+		}
+	}
+
+	err = wlu_var_setbuf(wl, cmd->name, iovar_data_ptr, (eventmsgs_len + trig_config_len));
+	free(iovar_data_ptr);
+	return err;
+}
+
+/* module initialization */
+void
+wluc_ecounters_module_init(void)
+{
+	/* register ecounters commands */
+	wl_module_cmds_register(wl_ecounters_cmds);
+}
diff --git a/wl/src/wl/exe/wluc_extlog.c b/wl/src/wl/exe/wluc_extlog.c
new file mode 100644
index 0000000..b24d720
--- /dev/null
+++ b/wl/src/wl/exe/wluc_extlog.c
@@ -0,0 +1,203 @@
+/*
+ * wl extlog command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_extlog.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#include <wlc_extlog_idstr.h>
+
+static int wl_extlog(void *wl, cmd_t *cmd, char **argv);
+static int wl_extlog_cfg(void *wl, cmd_t *cmd, char **argv);
+
+static cmd_t wl_extlog_cmds[] = {
+	{ "extlog", wl_extlog, WLC_GET_VAR, -1,
+	"get external logs\n"
+	"\tUsage: wl extlog <from_last> <number>\n"
+	"\tfrom_last: 1 - from the last log record; 0 - whole log recrods\n"
+	"\tnumber: number of log records to get, MAX is 32."},
+	{ "extlog_clr", wl_var_void, -1, WLC_SET_VAR, "clear external log records"},
+	{ "extlog_cfg", wl_extlog_cfg, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set external log configuration"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_extlog_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register extlog commands */
+	wl_module_cmds_register(wl_extlog_cmds);
+}
+
+static int
+wl_extlog(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	char *endptr;
+	int err;
+	int from_last;
+	int i, j;
+	char *log_p = NULL;
+	wlc_extlog_req_t r_args;
+	wlc_extlog_results_t *results;
+	void *ptr = NULL;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc > 3)
+		return BCME_USAGE_ERROR;
+
+	if (argc == 1)
+		from_last = 0;
+	else {
+		from_last = htod32(strtoul(argv[1], &endptr, 0));
+		if ((from_last != 0) && (from_last != 1))
+			return BCME_BADARG;
+	}
+
+	r_args.from_last = from_last;
+	if (argc == 3)
+		r_args.num = htod32(strtoul(argv[2], &endptr, 0));
+	else
+		r_args.num = 32;
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, &r_args, sizeof(wlc_extlog_req_t), &ptr)) < 0)
+			return err;
+
+	results = (wlc_extlog_results_t *)buf;
+
+	printf("get external log records: %d\n", results->num);
+	if (!results->num)
+		return 0;
+
+	if (results->version != EXTLOG_CUR_VER) {
+		printf("version mismatch: version = 0x%x, expected 0x%0x\n",
+			results->version, EXTLOG_CUR_VER);
+		return 0;
+	}
+
+	log_p = (char *)&results->logs[0];
+
+	printf("Seq:\tTime(ms) Log\n");
+	for (i = 0; i < (int)results->num; i++) {
+		printf("%d:\t%d\t ", ((log_record_t*)log_p)->seq_num,
+			((log_record_t*)log_p)->time);
+		for (j = 0; j < FMTSTR_MAX_ID; j++)
+			if (((log_record_t*)log_p)->id == extlog_fmt_str[j].id)
+				break;
+		if (j == FMTSTR_MAX_ID) {
+			printf("fmt string not found for id %d\n", ((log_record_t*)log_p)->id);
+			log_p += results->record_len;
+			continue;
+		}
+
+		switch (extlog_fmt_str[j].arg_type) {
+			case LOG_ARGTYPE_NULL:
+				printf("%s", extlog_fmt_str[j].fmt_str);
+				break;
+
+			case LOG_ARGTYPE_STR:
+				printf(extlog_fmt_str[j].fmt_str, ((log_record_t*)log_p)->str);
+				break;
+
+			case LOG_ARGTYPE_INT:
+				printf(extlog_fmt_str[j].fmt_str, ((log_record_t*)log_p)->arg);
+				break;
+
+			case LOG_ARGTYPE_INT_STR:
+				printf(extlog_fmt_str[j].fmt_str, ((log_record_t*)log_p)->arg,
+					((log_record_t*)log_p)->str);
+				break;
+
+			case LOG_ARGTYPE_STR_INT:
+				printf(extlog_fmt_str[j].fmt_str, ((log_record_t*)log_p)->str,
+					((log_record_t*)log_p)->arg);
+				break;
+			}
+		log_p += results->record_len;
+	}
+
+	return 0;
+
+}
+
+static int
+wl_extlog_cfg(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = 0;
+	char *endptr;
+	wlc_extlog_cfg_t *r_cfg;
+	wlc_extlog_cfg_t w_cfg;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc == 1) {
+		err = wl_var_get(wl, cmd, argv);
+		if (err < 0)
+			return err;
+		r_cfg = (wlc_extlog_cfg_t *)buf;
+		printf("max_number=%d, module=%x, level=%d, flag=%d, version=0x%04x\n",
+			r_cfg->max_number, r_cfg->module, r_cfg->level,
+			r_cfg->flag, r_cfg->version);
+	}
+	else if (argc == 4) {
+		w_cfg.module = htod16((uint16)(strtoul(argv[1], &endptr, 0)));
+		w_cfg.level = (uint8)strtoul(argv[2], &endptr, 0);
+		w_cfg.flag = (uint8)strtoul(argv[3], &endptr, 0);
+		err = wlu_var_setbuf(wl, cmd->name, &w_cfg, sizeof(wlc_extlog_cfg_t));
+	}
+	else {
+		fprintf(stderr, "illegal command!\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_he.c b/wl/src/wl/exe/wluc_he.c
new file mode 100644
index 0000000..88f0277
--- /dev/null
+++ b/wl/src/wl/exe/wluc_he.c
@@ -0,0 +1,818 @@
+/*
+ * wl he command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_he.c 627609 2016-03-25 21:00:45Z $
+ */
+
+#ifdef WIN32
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+
+#include <proto/802.11ah.h>
+
+#include <miniopt.h>
+
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifndef bzero
+#define bzero(mem, len)	memset(mem, 0, len)
+#endif
+
+#ifdef _WIN32
+#if defined(_MSC_VER) && _MSC_VER <= 1200
+#define NEED_STRTOULL
+#endif
+#if defined(_MSC_VER) && _MSC_VER > 1200
+#define strtoull _strtoui64
+#endif
+#endif /* _WIN32 */
+
+#define HE_CMD_HELP_STR \
+	"HE (802.11ax) protocol control commands\n\n" \
+	"\tUsage: wl he [command] [cmd options]\n\n" \
+	"Available commands and command options:\n" \
+	"\twl he enab [0|1] - query or enable/disable HE feature\n" \
+	"\twl he features [<features mask>] - query or enable/disable HE sub-features\n" \
+	"\twl he twt setup [<flow flags>] [<twt type] [<options>] <setup cmd> <flow id> - "\
+	"setup target wake time (TWT)\n" \
+	"\t\t<flow flags>:\n" \
+	"\t\t\t-b - Broadcast TWT\n" \
+	"\t\t\t-i - Implicit TWT\n" \
+	"\t\t\t-u - Unannounced\n" \
+	"\t\t\t-b - Trigger\n" \
+	"\t\t<twt type>:\n" \
+	"\t\t\t-y tsf - Absolute TSF\n" \
+	"\t\t\t-y offset - TSF offset\n" \
+	"\t\t<options>:\n" \
+	"\t\t\t-a <peer MAC address>\n" \
+	"\t\t\t-k <dialog token>\n" \
+	"\t\t\t-w <target wake time>\n" \
+	"\t\t\t-d <wake duration>\n" \
+	"\t\t\t-p <wake interval>\n" \
+	"\t\t<setup cmd>:\n" \
+	"\t\t\trequest\n" \
+	"\t\t\tsuggest\n" \
+	"\t\t\tdemand\n" \
+	"\twl he twt teardown [<flow flags>] [<options>] <flow id> - teardown flow\n" \
+	"\t\t<flow flags>:\n" \
+	"\t\t\t-b - Broadcast TWT\n" \
+	"\t\t<options>:\n" \
+	"\t\t\t-a <peer MAC address>\n" \
+	"\twl he twt info [<flow flags>] [<options>] <flow id> - request information\n" \
+	"\t\t<flow flags>:\n" \
+	"\t\t\t-r - response request\n" \
+	"\t\t<options>:\n" \
+	"\t\t\t-a <peer MAC address>\n" \
+	"\t\t\t-w <target wake time>\n"
+
+static cmd_func_t wl_he_cmd;
+
+/* wl he top level command list */
+static cmd_t wl_he_cmds[] = {
+	{ "he", wl_he_cmd, WLC_GET_VAR, WLC_SET_VAR, HE_CMD_HELP_STR },
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_he_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register HE commands */
+	wl_module_cmds_register(wl_he_cmds);
+}
+
+/* HE sub cmd */
+typedef struct sub_cmd sub_cmd_t;
+typedef int (sub_cmd_func_t)(void *wl, const cmd_t *cmd, const sub_cmd_t *sub, char **argv);
+struct sub_cmd {
+	char *name;
+	uint16 id;		/* id for the dongle f/w switch/case  */
+	uint16 type;		/* base type of argument IOVT_XXXX */
+	sub_cmd_func_t *hdlr;	/* cmd handler  */
+};
+
+/*  HE ioctl sub cmd handler functions  */
+static sub_cmd_func_t wl_he_cmd_uint;
+static sub_cmd_func_t wl_he_cmd_twt;
+static sub_cmd_func_t wl_he_cmd_twt_setup;
+static sub_cmd_func_t wl_he_cmd_twt_teardown;
+static sub_cmd_func_t wl_he_cmd_twt_info;
+
+/* wl he sub cmd list */
+static const sub_cmd_t he_cmd_list[] = {
+	/* wl he enab [0|1] */
+	{"enab", WL_HE_CMD_ENAB, IOVT_UINT8, wl_he_cmd_uint},
+	/* wl he features [<features>] */
+	{"features", WL_HE_CMD_FEATURES, IOVT_UINT32, wl_he_cmd_uint},
+	/* wl he twt ... */
+	{"twt", 0, 0, wl_he_cmd_twt},
+	{NULL, 0, 0, NULL}
+};
+
+/* wl he twt sub cmd list */
+static const sub_cmd_t twt_cmd_list[] = {
+	/* wl he twt setup ... */
+	{"setup", WL_HE_CMD_TWT_SETUP, IOVT_BUFFER, wl_he_cmd_twt_setup},
+	/* wl he twt teardown ... */
+	{"teardown", WL_HE_CMD_TWT_TEARDOWN, IOVT_BUFFER, wl_he_cmd_twt_teardown},
+	/* wl he twt info ... */
+	{"info", WL_HE_CMD_TWT_INFO, IOVT_BUFFER, wl_he_cmd_twt_info},
+	{NULL, 0, 0, NULL}
+};
+
+#ifdef NEED_STRTOULL
+static unsigned long long int
+strtoull(const char *nptr, char **endptr, int base)
+{
+	unsigned long long int result;
+	unsigned char value;
+	bool minus;
+
+	minus = FALSE;
+
+	while (bcm_isspace(*nptr)) {
+		nptr++;
+	}
+
+	if (nptr[0] == '+') {
+		nptr++;
+	}
+	else if (nptr[0] == '-') {
+		minus = TRUE;
+		nptr++;
+	}
+
+	if (base == 0) {
+		if (nptr[0] == '0') {
+			if ((nptr[1] == 'x') || (nptr[1] == 'X')) {
+				base = 16;
+				nptr = &nptr[2];
+			} else {
+				base = 8;
+				nptr = &nptr[1];
+			}
+		} else {
+			base = 10;
+		}
+	} else if (base == 16 &&
+	           (nptr[0] == '0') && ((nptr[1] == 'x') || (nptr[1] == 'X'))) {
+		nptr = &nptr[2];
+	}
+
+	result = 0;
+
+	while (bcm_isxdigit(*nptr) &&
+	       (value = bcm_isdigit(*nptr) ? *nptr - '0' : bcm_toupper(*nptr) - 'A' + 10) <
+	       (unsigned char)base) {
+		/* TODO: The strtoul() function should only convert the initial part
+		 * of the string in nptr to an unsigned long int value according to
+		 * the given base...so strtoull() should follow the same rule...
+		 */
+		result = result * base + value;
+		nptr++;
+	}
+
+	if (minus) {
+		result = result * -1;
+	}
+
+	if (endptr) {
+		*endptr = DISCARD_QUAL(nptr, char);
+	}
+
+	return result;
+}
+#endif /* NEED_STRTOULL */
+
+/* wl he command */
+static int
+wl_he_cmd(void *wl, cmd_t *cmd, char **argv)
+{
+	const sub_cmd_t *sub = he_cmd_list;
+	char *he_query[2] = {"enab", NULL};
+	char *he_en[3] = {"enab", "1", NULL};
+	char *he_dis[3] = {"enab", "0", NULL};
+	int ret = BCME_USAGE_ERROR;
+
+	/* skip to cmd name after "he" */
+	argv++;
+
+	if (!*argv) {
+		/* query he "enab" state */
+		argv = he_query;
+	}
+	else if (*argv[0] == '1') {
+		argv = he_en;
+	}
+	else if (*argv[0] == '0') {
+		argv = he_dis;
+	}
+	else if (!strcmp(*argv, "-h") || !strcmp(*argv, "help"))  {
+		/* help , or -h* */
+		return BCME_USAGE_ERROR;
+	}
+
+	while (sub->name != NULL) {
+		if (strcmp(sub->name, *argv) == 0)  {
+			/* dispacth subcmd to the handler */
+			if (sub->hdlr != NULL) {
+				ret = sub->hdlr(wl, cmd, sub, ++argv);
+			}
+			return ret;
+		}
+		sub ++;
+	}
+
+	return BCME_IOCTL_ERROR;
+}
+
+typedef struct {
+	uint16 id;
+	uint16 len;
+	uint32 val;
+} he_xtlv_v32;
+
+
+static uint
+wl_he_iovt2len(uint iovt)
+{
+	switch (iovt) {
+	case IOVT_BOOL:
+	case IOVT_INT8:
+	case IOVT_UINT8:
+		return sizeof(uint8);
+	case IOVT_INT16:
+	case IOVT_UINT16:
+		return sizeof(uint16);
+	case IOVT_INT32:
+	case IOVT_UINT32:
+		return sizeof(uint32);
+	default:
+		/* ASSERT(0); */
+		return 0;
+	}
+}
+
+static bool
+wl_he_get_uint_cb(void *ctx, uint16 *id, uint16 *len)
+{
+	he_xtlv_v32 *v32 = ctx;
+
+	*id = v32->id;
+	*len = v32->len;
+
+	return FALSE;
+}
+
+static void
+wl_he_pack_uint_cb(void *ctx, uint16 id, uint16 len, uint8 *buf)
+{
+	he_xtlv_v32 *v32 = ctx;
+
+	BCM_REFERENCE(id);
+	BCM_REFERENCE(len);
+
+	v32->val = htod32(v32->val);
+
+	switch (v32->len) {
+	case sizeof(uint8):
+		*buf = (uint8)v32->val;
+		break;
+	case sizeof(uint16):
+		store16_ua(buf, (uint16)v32->val);
+		break;
+	case sizeof(uint32):
+		store16_ua(buf, v32->val);
+		break;
+	default:
+		/* ASSERT(0); */
+		break;
+	}
+}
+
+/*  ******** generic uint8/uint16/uint32   ******** */
+static int
+wl_he_cmd_uint(void *wl, const cmd_t *cmd, const sub_cmd_t *sub, char **argv)
+{
+	int res = BCME_OK;
+
+	/* get */
+	if (*argv == NULL) {
+		bcm_xtlv_t mybuf;
+		uint8 *resp;
+
+		mybuf.id = sub->id;
+		mybuf.len = 0;
+
+		/*  send getbuf iovar */
+		res = wlu_var_getbuf_sm(wl, cmd->name, &mybuf, sizeof(mybuf),
+			(void **)&resp);
+
+		/*  check the response buff  */
+		if (res == BCME_OK && resp != NULL) {
+			uint len = wl_he_iovt2len(sub->type);
+			uint32 v32;
+
+			switch (len) {
+			case sizeof(uint8):
+				v32 = *resp;
+				break;
+			case sizeof(uint16):
+				v32 = load16_ua(resp);
+				break;
+			case sizeof(uint32):
+				v32 = load32_ua(resp);
+				break;
+			default:
+				v32 = ~0;
+				break;
+			}
+			v32 = dtoh32(v32);
+			printf("%u\n", v32);
+		}
+	}
+	/* set */
+	else {
+		uint8 mybuf[32];
+		int mybuf_len = sizeof(mybuf);
+		he_xtlv_v32 v32;
+
+		v32.id = sub->id;
+		v32.len = wl_he_iovt2len(sub->type);
+		v32.val = atoi(*argv);
+
+		res = bcm_pack_xtlv_buf((void *)&v32, mybuf, sizeof(mybuf),
+			BCM_XTLV_OPTION_ALIGN32, wl_he_get_uint_cb, wl_he_pack_uint_cb,
+			&mybuf_len);
+		if (res != BCME_OK) {
+			goto fail;
+		}
+
+		res = wlu_var_setbuf(wl, cmd->name, mybuf, mybuf_len);
+	}
+
+	return res;
+
+fail:
+	fprintf(stderr, "error:%d\n", res);
+	return res;
+}
+
+/* wl he twt top level commend */
+static int
+wl_he_cmd_twt(void *wl, const cmd_t *cmd, const sub_cmd_t *sub, char **argv)
+{
+	const sub_cmd_t *sub2 = twt_cmd_list;
+	int res = BCME_OK;
+
+	BCM_REFERENCE(sub);
+
+	if (*argv == NULL) {
+		return BCME_USAGE_ERROR;
+	}
+
+	while (sub2->name != NULL) {
+		if (strcmp(sub2->name, *argv) == 0)  {
+			/* dispacth subcmd to the handler */
+			if (sub2->hdlr != NULL) {
+				res = sub2->hdlr(wl, cmd, sub2, ++argv);
+			}
+			return res;
+		}
+		sub2 ++;
+	}
+
+	return BCME_USAGE_ERROR;
+}
+
+/* setup command name to value conversion */
+static struct {
+	const char *name;
+	uint8 val;
+} setup_cmd_val[] = {
+	{"request", TWT_SETUP_CMD_REQUEST_TWT},
+	{"suggest", TWT_SETUP_CMD_SUGGEST_TWT},
+	{"demand", TWT_SETUP_CMD_DEMAND_TWT}
+};
+
+#define WL_HE_TWT_CMD_INVAL	255
+
+static uint8
+wl_he_twt_cmd2val(const char *name)
+{
+	uint i;
+
+	for (i = 0; i < ARRAYSIZE(setup_cmd_val); i ++) {
+		if (strcmp(name, setup_cmd_val[i].name) == 0) {
+			return setup_cmd_val[i].val;
+		}
+	}
+
+	return WL_HE_TWT_CMD_INVAL;
+}
+
+/* target wake time (twt) type to value conversion */
+static struct {
+	const char *name;
+	uint8 val;
+} twt_type_val[] = {
+	{"tsf", WL_TWT_TIME_TYPE_BSS},
+	{"offset", WL_TWT_TIME_TYPE_OFFSET}
+};
+
+#define WL_HE_TWT_TYPE_INVAL	255
+
+static uint8
+wl_he_twt_type2val(const char *name)
+{
+	uint i;
+
+	for (i = 0; i < ARRAYSIZE(twt_type_val); i ++) {
+		if (strcmp(name, twt_type_val[i].name) == 0) {
+			return twt_type_val[i].val;
+		}
+	}
+
+	return WL_HE_TWT_TYPE_INVAL;
+}
+
+/* wl he twt setup command */
+static int
+wl_he_cmd_twt_setup(void *wl, const cmd_t *cmd, const sub_cmd_t *sub, char **argv)
+{
+	int res = BCME_OK;
+	uint8 mybuf[64];
+	uint8 *rem = mybuf;
+	uint16 rem_len = sizeof(mybuf);
+	wl_twt_setup_t val;
+	miniopt_t opt;
+	int opt_err;
+	int argc;
+	bool got_mandatory = FALSE;
+
+	BCM_REFERENCE(wl);
+
+	if (*argv == NULL) {
+		return BCME_USAGE_ERROR;
+	}
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	bzero(&val, sizeof(val));
+
+	val.version = WL_TWT_SETUP_VER;
+	val.length = sizeof(val.version) + sizeof(val.length);
+
+	miniopt_init(&opt, __FUNCTION__, "biut", FALSE);
+
+	while ((opt_err = miniopt(&opt, argv)) != -1) {
+
+		if (opt_err == 1) {
+			res = BCME_USAGE_ERROR;
+			goto fail;
+		}
+
+		/* flags and options */
+		if (!opt.positional) {
+
+			/* flags */
+
+			/* -b (broadcast) */
+			if (opt.opt == 'b') {
+				val.desc.flow_flags |= WL_TWT_FLOW_FLAG_BROADCAST;
+			}
+			/* -i (implicit) */
+			else if (opt.opt == 'i') {
+				val.desc.flow_flags |= WL_TWT_FLOW_FLAG_IMPLICIT;
+			}
+			/* -u (unannounced) */
+			else if (opt.opt == 'u') {
+				val.desc.flow_flags |= WL_TWT_FLOW_FLAG_UNANNOUNCED;
+			}
+			/* -t (trigger) */
+			else if (opt.opt == 't') {
+				val.desc.flow_flags |= WL_TWT_FLOW_FLAG_TRIGGER;
+			}
+
+			/* options */
+
+			/* -a peer_address */
+			else if (opt.opt == 'a') {
+				if (!wl_ether_atoe(opt.valstr, &val.peer)) {
+					fprintf(stderr, "Malformed TWT peer address '%s'\n",
+					        opt.valstr);
+					res = BCME_BADARG;
+					goto fail;
+				}
+			}
+			/* -k dialog_token */
+			else if (opt.opt == 'k') {
+				val.dialog = (uint8)strtoul(opt.valstr, NULL, 0);
+			}
+			/* -y twt type */
+			else if (opt.opt == 'y') {
+				if ((val.desc.wake_type =
+				     wl_he_twt_type2val(opt.valstr)) == WL_HE_TWT_TYPE_INVAL) {
+					fprintf(stderr, "Unrecognized TWT type '%s'\n",
+					        opt.valstr);
+					res = BCME_BADARG;
+					goto fail;
+				}
+			}
+			/* -w target_wake_time (twt) */
+			else if (opt.opt == 'w') {
+				uint64 twt = strtoull(opt.valstr, NULL, 0);
+				val.desc.wake_time_h = htod32((uint32)(twt >> 32));
+				val.desc.wake_time_l = htod32((uint32)twt);
+			}
+			/* -d duration */
+			else if (opt.opt == 'd') {
+				val.desc.wake_dur = htod32(opt.uval);
+			}
+			/* -p interval */
+			else if (opt.opt == 'p') {
+				val.desc.wake_int = htod32(opt.uval);
+			}
+			else {
+				fprintf(stderr, "Unrecognized option '%s'\n", *argv);
+				res = BCME_BADARG;
+				goto fail;
+			}
+		}
+
+		/* positional/mandatory */
+		else {
+			if (argc < 2) {
+				res = BCME_USAGE_ERROR;
+				goto fail;
+			}
+
+			/* setup_cmd */
+			if ((val.desc.setup_cmd =
+			     wl_he_twt_cmd2val(*argv)) == WL_HE_TWT_CMD_INVAL) {
+				fprintf(stderr, "Unrecognized TWT Setup command '%s'\n", *argv);
+				res = BCME_BADARG;
+				goto fail;
+			}
+			argv++;
+
+			/* flow_id */
+			val.desc.flow_id = (uint8)strtoul(*argv, NULL, 0);
+			argv++;
+
+			got_mandatory = TRUE;
+
+			break;
+		}
+
+		argv += opt.consumed;
+		argc -= opt.consumed;
+	}
+
+	if (!got_mandatory) {
+		res = BCME_USAGE_ERROR;
+		goto fail;
+	}
+
+	res = bcm_pack_xtlv_entry(&rem, &rem_len, sub->id,
+		sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
+	if (res != BCME_OK) {
+		goto fail;
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, mybuf, sizeof(mybuf) - rem_len);
+
+fail:
+	fprintf(stderr, "error:%d\n", res);
+	return res;
+}
+
+/* wl he twt teardown command */
+static int
+wl_he_cmd_twt_teardown(void *wl, const cmd_t *cmd, const sub_cmd_t *sub, char **argv)
+{
+	int res = BCME_OK;
+	uint8 mybuf[64];
+	uint8 *rem = mybuf;
+	uint16 rem_len = sizeof(mybuf);
+	wl_twt_teardown_t val;
+	miniopt_t opt;
+	int opt_err;
+	int argc;
+	bool got_mandatory = FALSE;
+
+	BCM_REFERENCE(wl);
+
+	if (*argv == NULL) {
+		return BCME_USAGE_ERROR;
+	}
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	bzero(&val, sizeof(val));
+
+	val.version = WL_TWT_TEARDOWN_VER;
+	val.length = sizeof(val.version) + sizeof(val.length);
+
+	miniopt_init(&opt, __FUNCTION__, "b", FALSE);
+
+	while ((opt_err = miniopt(&opt, argv)) != -1) {
+
+		if (opt_err == 1) {
+			res = BCME_USAGE_ERROR;
+			goto fail;
+		}
+
+		/* flags and options */
+		if (!opt.positional) {
+
+			/* flags */
+
+			/* -b (broadcast) */
+			if (opt.opt == 'b') {
+				val.flow_flags |= WL_TWT_FLOW_FLAG_BROADCAST;
+			}
+
+			/* options */
+
+			/* -a peer_address */
+			else if (opt.opt == 'a') {
+				if (!wl_ether_atoe(opt.valstr, &val.peer)) {
+					res = BCME_BADARG;
+					goto fail;
+				}
+			}
+		}
+
+		/* positionals */
+		else {
+			if (argc < 1) {
+				res = BCME_USAGE_ERROR;
+				goto fail;
+			}
+
+			/* flow_id */
+			val.flow_id = (uint8)strtoul(*argv, NULL, 0);
+			argv++;
+
+			got_mandatory = TRUE;
+
+			break;
+		}
+
+		argv += opt.consumed;
+	}
+
+	if (!got_mandatory) {
+		res = BCME_USAGE_ERROR;
+		goto fail;
+	}
+
+	res = bcm_pack_xtlv_entry(&rem, &rem_len, sub->id,
+		sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
+	if (res != BCME_OK) {
+		goto fail;
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, mybuf, sizeof(mybuf) - rem_len);
+
+fail:
+	fprintf(stderr, "error:%d\n", res);
+	return res;
+}
+
+/* wl he twt info command */
+static int
+wl_he_cmd_twt_info(void *wl, const cmd_t *cmd, const sub_cmd_t *sub, char **argv)
+{
+	int res = BCME_OK;
+	uint8 mybuf[64];
+	uint8 *rem = mybuf;
+	uint16 rem_len = sizeof(mybuf);
+	wl_twt_info_t val;
+	miniopt_t opt;
+	int opt_err;
+	int argc;
+	bool got_mandatory = FALSE;
+
+	BCM_REFERENCE(wl);
+
+	if (*argv == NULL) {
+		return BCME_USAGE_ERROR;
+	}
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	bzero(&val, sizeof(val));
+
+	val.version = WL_TWT_INFO_VER;
+	val.length = sizeof(val.version) + sizeof(val.length);
+
+	miniopt_init(&opt, __FUNCTION__, "r", FALSE);
+
+	while ((opt_err = miniopt(&opt, argv)) != -1) {
+
+		if (opt_err == 1) {
+			res = BCME_USAGE_ERROR;
+			goto fail;
+		}
+
+		/* flags and options */
+		if (!opt.positional) {
+
+			/* flags */
+
+			/* -r (response request) */
+			if (opt.opt == 'r') {
+				val.desc.flow_flags |= WL_TWT_INFO_FLAG_RESP_REQ;
+			}
+
+			/* options */
+
+			/* -a peer_address */
+			else if (opt.opt == 'a') {
+				if (!wl_ether_atoe(opt.valstr, &val.peer)) {
+					res = BCME_BADARG;
+					goto fail;
+				}
+			}
+			/* -w target_wake_time (twt) */
+			else if (opt.opt == 'w') {
+				uint64 twt = strtoull(opt.valstr, NULL, 0);
+				val.desc.next_twt_h = htod32((uint32)(twt >> 32));
+				val.desc.next_twt_l = htod32((uint32)twt);
+			}
+		}
+
+		/* positionals */
+		else {
+			if (argc < 1) {
+				res = BCME_USAGE_ERROR;
+				goto fail;
+			}
+
+			/* flow_id */
+			val.desc.flow_id = (uint8)strtoul(*argv, NULL, 0);
+			argv++;
+
+			got_mandatory = TRUE;
+
+			break;
+		}
+
+		argv += opt.consumed;
+	}
+
+	if (!got_mandatory) {
+		res = BCME_USAGE_ERROR;
+		goto fail;
+	}
+
+	res = bcm_pack_xtlv_entry(&rem, &rem_len, sub->id,
+		sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
+	if (res != BCME_OK) {
+		goto fail;
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, mybuf, sizeof(mybuf) - rem_len);
+
+fail:
+	fprintf(stderr, "error:%d\n", res);
+	return res;
+}
diff --git a/wl/src/wl/exe/wluc_ht.c b/wl/src/wl/exe/wluc_ht.c
new file mode 100644
index 0000000..62cc0a7
--- /dev/null
+++ b/wl/src/wl/exe/wluc_ht.c
@@ -0,0 +1,479 @@
+/*
+ * wl ht command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_ht.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#include <miniopt.h>
+
+static cmd_func_t wl_bw_cap;
+static cmd_func_t wl_nrate;
+static cmd_func_t wl_cur_mcsset;
+static cmd_func_t wl_txmcsset;
+static cmd_func_t wl_rxmcsset;
+
+static cmd_t wl_ht_cmds[] = {
+	{ "bw_cap", wl_bw_cap, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/set the per-band bandwidth.\n"
+	"Usage: wl bw_cap <2g|5g> [<cap>]\n"
+	"\t2g|5g - Band: 2.4GHz or 5GHz respectively\n"
+	"cap:\n"
+	"\t0x1 - 20MHz\n"
+	"\t0x3 - 20/40MHz\n"
+	"\t0x7 - 20/40/80MHz\n"
+	"\t0xf - 20/40/80/160MHz\n"
+	"\t0xff - Unrestricted" },
+	{ "cur_mcsset", wl_cur_mcsset, WLC_GET_VAR, -1,
+	"Get the current mcs set"
+	},
+	{ "mimo_ps", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set mimo power save mode, (0=Dont send MIMO, 1=proceed MIMO with RTS, 2=N/A, "
+	"3=No restriction)"},
+	{ "ofdm_txbw", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set ofdm txbw (2=20Mhz(lower), 3=20Mhz upper, 4(not allowed), 5=40Mhz dup)"},
+	{ "cck_txbw", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set cck txbw (2=20Mhz(lower), 3=20Mhz upper)"},
+	{ "frameburst", wl_int, WLC_GET_FAKEFRAG, WLC_SET_FAKEFRAG,
+	"Disable/Enable frameburst mode" },
+	{ "nrate", wl_nrate, WLC_GET_VAR, WLC_SET_VAR,
+	"\"auto\" to clear a rate override, or:\n"
+	"-r legacy rate (CCK, OFDM)\n"
+	"-m HT MCS index\n"
+	"-s stf mode (0=SISO,1=CDD,2=STBC,3=SDM)\n"
+	"-w Override MCS only to support STA's with/without STBC capability"},
+	{ "mimo_txbw", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set mimo txbw (2=20Mhz(lower), 3=20Mhz upper, 4=40Mhz, 4=40Mhz(DUP)\n"
+	"\t6=80Mhz(20LL), 7=80Mhz(20LU), 8=80Mhz(20UL), 9=80Mhz(20UU)\n"
+	"\t10=80Mhz(40L), 11=80Mhz(40U), 12=80Mhz)"},
+	{ "txmcsset", wl_txmcsset, WLC_GET_VAR, -1, "get Transmit MCS rateset for 11N device"},
+	{ "rxmcsset", wl_rxmcsset, WLC_GET_VAR, -1, "get Receive MCS rateset for 11N device"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* IOCtl version read from targeted driver */
+static int ioctl_version;
+
+
+/* module initialization */
+void
+wluc_ht_module_init(void)
+{
+	(void)g_swap;
+
+	/* get global ioctl_version */
+	ioctl_version = wl_get_ioctl_version();
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register ht commands */
+	wl_module_cmds_register(wl_ht_cmds);
+}
+
+/* Format a ratespec for "nrate" output
+ * Will handle both current wl_ratespec and legacy (ioctl_version 1) nrate ratespec
+ */
+static void
+wl_nrate_print(uint32 rspec)
+{
+	const char * rspec_auto = "auto";
+	uint encode, rate, txexp = 0, bw_val;
+	const char* stbc = "";
+	const char* ldpc = "";
+	const char* sgi = "";
+	const char* bw = "";
+	int stf;
+
+	if (rspec == 0) {
+		encode = WL_RSPEC_ENCODE_RATE;
+	} else if (ioctl_version == 1) {
+		encode = (rspec & OLD_NRATE_MCS_INUSE) ? WL_RSPEC_ENCODE_HT : WL_RSPEC_ENCODE_RATE;
+		stf = (int)((rspec & OLD_NRATE_STF_MASK) >> OLD_NRATE_STF_SHIFT);
+		rate = (rspec & OLD_NRATE_RATE_MASK);
+
+		if (rspec & OLD_NRATE_OVERRIDE) {
+			if (rspec & OLD_NRATE_OVERRIDE_MCS_ONLY)
+				rspec_auto = "fixed mcs only";
+			else
+				rspec_auto = "fixed";
+		}
+	} else {
+		int siso;
+		encode = (rspec & WL_RSPEC_ENCODING_MASK);
+		rate = (rspec & WL_RSPEC_RATE_MASK);
+		txexp = (rspec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT;
+		stbc  = ((rspec & WL_RSPEC_STBC) != 0) ? " stbc" : "";
+		ldpc  = ((rspec & WL_RSPEC_LDPC) != 0) ? " ldpc" : "";
+		sgi   = ((rspec & WL_RSPEC_SGI)  != 0) ? " sgi"  : "";
+		bw_val = (rspec & WL_RSPEC_BW_MASK);
+
+		if (bw_val == WL_RSPEC_BW_20MHZ) {
+			bw = "bw20";
+		} else if (bw_val == WL_RSPEC_BW_40MHZ) {
+			bw = "bw40";
+		} else if (bw_val == WL_RSPEC_BW_80MHZ) {
+			bw = "bw80";
+		} else if (bw_val == WL_RSPEC_BW_160MHZ) {
+			bw = "bw160";
+		}
+		else if (bw_val == WL_RSPEC_BW_10MHZ) {
+			bw = "bw10";
+		} else if (bw_val == WL_RSPEC_BW_5MHZ) {
+			bw = "bw5";
+		} else if (bw_val == WL_RSPEC_BW_2P5MHZ) {
+			bw = "bw2.5";
+		}
+
+		/* initialize stf mode to an illegal value and
+		 * fix to a backward compatable value if possible
+		 */
+		stf = -1;
+		/* for stf calculation, determine if the rate is single stream.
+		 * Legacy rates WL_RSPEC_ENCODE_RATE are single stream, and
+		 * HT rates for mcs 0-7 are single stream
+		 */
+		siso = (encode == WL_RSPEC_ENCODE_RATE) ||
+			((encode == WL_RSPEC_ENCODE_HT) && rate < 8);
+
+		/* calc a value for nrate stf mode */
+		if (txexp == 0) {
+			if ((rspec & WL_RSPEC_STBC) && siso) {
+				/* STF mode STBC */
+				stf = OLD_NRATE_STF_STBC;
+			} else {
+				/* STF mode SISO or SDM */
+				stf = (siso) ? OLD_NRATE_STF_SISO : OLD_NRATE_STF_SDM;
+			}
+		} else if (txexp == 1 && siso) {
+			/* STF mode CDD */
+			stf = OLD_NRATE_STF_CDD;
+		}
+
+		if (rspec & WL_RSPEC_OVERRIDE_RATE) {
+			rspec_auto = "fixed";
+		}
+	}
+
+	if (encode == WL_RSPEC_ENCODE_RATE) {
+		if (rspec == 0) {
+			printf("auto\n");
+		} else {
+			printf("legacy rate %d%s Mbps stf mode %d %s\n",
+			       rate/2, (rate % 2)?".5":"", stf, rspec_auto);
+		}
+	} else if (encode == WL_RSPEC_ENCODE_HT) {
+		printf("mcs index %d stf mode %d %s\n",
+		       rate, stf, rspec_auto);
+	} else {
+		uint vht = (rspec & WL_RSPEC_VHT_MCS_MASK);
+		uint Nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT;
+		printf("vht mcs %d Nss %d Tx Exp %d %s%s%s%s %s\n",
+		       vht, Nss, txexp, bw, stbc, ldpc, sgi, rspec_auto);
+	}
+}
+
+static int
+wl_nrate(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_nrate";
+	bool mcs_set = FALSE, legacy_set = FALSE, stf_set = FALSE;
+	bool mcs_only = FALSE;
+	int err, opt_err;
+	uint32 val = 0;
+	uint32 rate = 0;
+	uint32 nrate = 0;
+	uint32 mcs = 0;
+	uint stf = 0;	/* (0=SISO,1=CDD,2=STBC,3=SDM) */
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((err = wlu_iovar_getint(wl, "nrate", (int*)&val)) < 0)
+			return err;
+
+		/* print a user readable line for the nrate rspec */
+		wl_nrate_print(val);
+
+		return 0;
+	}
+
+	/* check for a single argument of "auto" or -1 */
+	if ((!strcmp(argv[0], "auto") || !strcmp(argv[0], "-1")) &&
+	    argv[1] == NULL) {
+		/* clear the nrate override */
+		err = wlu_iovar_setint(wl, "nrate", 0);
+		goto exit;
+	}
+
+	miniopt_init(&to, fn_name, "w", FALSE);
+	while ((opt_err = miniopt(&to, argv)) != -1) {
+		if (opt_err == 1) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv += to.consumed;
+
+		if (to.opt == 'r') {
+			if (!to.good_int) {
+				/* special case check for "-r 5.5" */
+				if (!strcmp(to.valstr, "5.5")) {
+					to.val = 11;
+				} else {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as a rate value\n",
+						fn_name, to.valstr);
+					err = BCME_BADARG;
+					goto exit;
+				}
+			} else
+			      to.val = to.val*2;
+			if (mcs_set) {
+				fprintf(stderr, "%s: cannot use -r and -m\n", fn_name);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+
+			legacy_set = TRUE;
+			rate = to.val;
+		}
+		if (to.opt == 'm') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for mcs\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (legacy_set) {
+				fprintf(stderr, "%s: cannot use -r and -m\n", fn_name);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			mcs_set = TRUE;
+			mcs = to.val;
+		}
+		if (to.opt == 's') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for stf mode\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			stf = to.val;
+			stf_set = TRUE;
+		}
+		if (to.opt == 'w') {
+			mcs_only = TRUE;
+		}
+	}
+
+	if ((mcs_only && !mcs_set) || (mcs_only && (stf_set || legacy_set))) {
+		fprintf(stderr, "%s: can use -w only with -m\n", fn_name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (!stf_set) {
+		if (legacy_set)
+			stf = OLD_NRATE_STF_SISO;	/* SISO */
+		else if (mcs_set) {
+			if (GET_11N_MCS_NSS(mcs & OLD_NRATE_RATE_MASK) == 1)
+				stf = OLD_NRATE_STF_SISO;	/* SISO */
+			else
+				stf = OLD_NRATE_STF_SDM;	/* SDM */
+		}
+	}
+
+	if (!legacy_set && !mcs_set) {
+		fprintf(stderr, "%s: you need to set a legacy or mcs rate\n", fn_name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (ioctl_version == 1) {
+		if (legacy_set) {
+			nrate = rate;
+		} else {
+			nrate = mcs;
+			nrate |= OLD_NRATE_MCS_INUSE;
+			if (mcs_only) {
+				nrate |= OLD_NRATE_OVERRIDE_MCS_ONLY;
+			}
+		}
+
+		nrate |= (stf << OLD_NRATE_STF_SHIFT) & OLD_NRATE_STF_MASK;
+	} else {
+		uint tx_exp = 0;
+
+		/* set the ratespec encoding type and basic rate value */
+		if (legacy_set) {
+			nrate = WL_RSPEC_ENCODE_RATE;	/* 11abg */
+			nrate |= rate;
+		} else {
+			nrate = WL_RSPEC_ENCODE_HT;	/* 11n HT */
+			nrate |= mcs;
+		}
+
+		/* decode nrate stf value into tx expansion and STBC */
+		if (stf == OLD_NRATE_STF_CDD) {
+			tx_exp = 1;
+		} else if (stf == OLD_NRATE_STF_STBC) {
+			nrate |= WL_RSPEC_STBC;
+		}
+
+		nrate |= (tx_exp << WL_RSPEC_TXEXP_SHIFT);
+	}
+
+	err = wlu_iovar_setint(wl, "nrate", (int)nrate);
+
+exit:
+	return err;
+} /* wl_nrate */
+
+/* Set per-band bandwidth */
+static int wl_bw_cap(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	struct {
+		uint32 band;
+		uint32 bw_cap;
+	} param = { 0, 0 };
+	char *s = NULL;
+	void *ptr = NULL;
+
+	/* Skip the command name */
+	argv++;
+
+	if (*argv) {
+		if (!strcmp(*argv, "a") || !strcmp(*argv, "5") || !strcmp(*argv, "5g")) {
+			param.band = WLC_BAND_5G;
+		} else if (!strcmp(*argv, "b") || !strcmp(*argv, "2") || !strcmp(*argv, "2g")) {
+			param.band = WLC_BAND_2G;
+		} else {
+			fprintf(stderr,
+			        "%s: invalid band %s\n",
+			        cmd->name, *argv);
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		argv++;
+
+		if (*argv) {
+			/* Optional 2nd arg is used to set the bandwidth cap */
+			s = NULL;
+
+			param.bw_cap = (uint32) strtoul(*argv, &s, 0);
+			if (s && *s != '\0') {
+				fprintf(stderr, "%s: invalid bandwidth '%s'\n",
+				        cmd->name, *argv);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+	} else {
+		fprintf(stderr, "%s: band unspecified\n", cmd->name);
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (param.bw_cap == 0) {
+		if ((err = wlu_var_getbuf(wl, cmd->name, &param, sizeof(param), &ptr)) < 0)
+			return err;
+
+		printf("0x%x\n", *((uint32 *)ptr));
+	} else {
+		err = wlu_var_setbuf(wl, cmd->name, &param, sizeof(param));
+	}
+
+exit:
+	return err;
+}
+
+static int
+wl_cur_mcsset(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(buf, 0, WLC_IOCTL_SMLEN);
+	ret = wlu_iovar_get(wl, "cur_mcsset", &buf[0], MCSSET_LEN);
+	if (ret < 0)
+		return ret;
+
+	wl_print_mcsset(buf);
+
+	return ret;
+}
+
+static int
+wl_txmcsset(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+
+	if ((err = wl_var_get(wl, cmd, argv)) < 0)
+		return err;
+	wl_print_mcsset(buf);
+
+	return err;
+}
+
+static int
+wl_rxmcsset(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+
+	if ((err = wl_var_get(wl, cmd, argv)) < 0)
+		return err;
+
+	wl_print_mcsset(buf);
+
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_interfere.c b/wl/src/wl/exe/wluc_interfere.c
new file mode 100644
index 0000000..ccf15ef
--- /dev/null
+++ b/wl/src/wl/exe/wluc_interfere.c
@@ -0,0 +1,103 @@
+/*
+ * wl interfere command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_interfere.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_itfr_get_stats;
+
+static cmd_t wl_interfere_cmds[] = {
+	{ "itfr_get_stats", wl_itfr_get_stats, WLC_GET_VAR, -1,
+	"get interference source information"
+	},
+	{ "itfr_enab", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set STA interference detection mode(STA only)\n"
+	"\t 0  - disable\n"
+	"\t 1  - enable maual detection\n"
+	"\t 2  - enable auto detection"
+	},
+	{ "itfr_detect", wl_var_void, -1, WLC_SET_VAR,
+	"issue an interference detection request"
+	},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_interfere_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register interfere commands */
+	wl_module_cmds_register(wl_interfere_cmds);
+}
+
+static int
+wl_itfr_get_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	interference_source_rep_t *iftr_stats = NULL;
+	const char *iftr_source[] = {"none", "wireless phone", "wireless video camera",
+		"microwave oven", "wireless baby monitor", "bluetooth device",
+		"wireless video camera or baby monitor", "bluetooth or baby monitor",
+		"video camera or phone", "unidentified"}; /* sync with interference_source_t */
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, (void*)&iftr_stats)) < 0)
+		return err;
+
+	if (iftr_stats->flags & ITFR_NOISY_ENVIRONMENT)
+		printf("Feature is stopped due to noisy environment\n");
+	else
+		printf("Interference %s detected. last interference at timestamp %d: "
+			"source is %s on %s channel\n",
+			(iftr_stats->flags & ITFR_INTERFERENCED) ? "is" : "is not",
+			iftr_stats->timestamp, iftr_source[iftr_stats->source],
+			(iftr_stats->flags & ITFR_HOME_CHANNEL) ? "home" : "non-home");
+
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_keep_alive.c b/wl/src/wl/exe/wluc_keep_alive.c
new file mode 100644
index 0000000..31633fc
--- /dev/null
+++ b/wl/src/wl/exe/wluc_keep_alive.c
@@ -0,0 +1,179 @@
+/*
+ * wl keep_alive command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_keep_alive.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_keep_alive;
+
+static cmd_t wl_keep_alive_cmds[] = {
+	{"mkeep_alive", wl_mkeep_alive, WLC_GET_VAR, WLC_SET_VAR,
+	"Send specified \"mkeep-alive\" packet periodically.\n"
+	"\tUsage: wl mkeep_alive <index0-3> <period> <packet>\n"
+	"\t\tindex: 0 - 3.\n"
+	"\t\tperiod: Re-transmission period in milli-seconds. 0 to disable packet transmits.\n"
+	"\t\tpacket: Hex packet contents to transmit. The packet contents should include "
+	"the entire ethernet packet (ethernet header, IP header, UDP header, and UDP "
+	"payload) specified in network byte order. If no packet is specified, a nulldata frame "
+	"will be sent instead.\n"
+	"\n\te.g. Send keep alive packet every 30 seconds using id-1:\n"
+	"\twl mkeep_alive 1 30000 0x0014a54b164f000f66f45b7e08004500001e000040004011c"
+	"52a0a8830700a88302513c413c4000a00000a0d" },
+	{"keep_alive", wl_keep_alive, -1, -1,
+	"Send specified \"keep-alive\" packet periodically.\n"
+	"\tUsage: wl keep_alive <period> <packet>\n"
+	"\t\tperiod: Re-transmission period in milli-seconds. 0 to disable packet transmits.\n"
+	"\t\tpacket: Hex packet contents to transmit. The packet contents should include "
+	"the entire ethernet packet (ethernet header, IP header, UDP header, and UDP "
+	"payload) specified in network byte order.\n"
+	"\n\te.g. Send keep alive packet every 30 seconds:\n"
+	"\twl keep_alive 30000 0x0014a54b164f000f66f45b7e08004500001e000040004011c"
+	"52a0a8830700a88302513c413c4000a00000a0d" },
+	{"wowl_keepalive", wl_mkeep_alive, WLC_GET_VAR, WLC_SET_VAR,
+	"Send specified keep alive packet periodically in w mode.\n"
+	"\tUsage: wl wowl_keepalive <index0-1> <period> <packet>\n"
+	"\t\tindex: 0 - 1.\n"
+	"\t\tperiod: Re-transmission period in milli-seconds. 0 to disable packet transmits.\n"
+	"\t\tpacket: Hex packet contents to transmit. The packet contents should include "
+	"the entire ethernet packet (ethernet header, IP header, UDP header, and UDP "
+	"payload) specified in network byte order.\n"
+	"\n\te.g. Send keep alive packet every 30 seconds using id-1:\n"
+	"\twl wowl_keepalive 1 30000 0x0014a54b164f000f66f45b7e08004500001e000040004011c"
+	"52a0a8830700a88302513c413c4000a00000a0d\n" },
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_keep_alive_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register keep_alive commands */
+	wl_module_cmds_register(wl_keep_alive_cmds);
+}
+
+/* Send a periodic keep-alive packet at the specificed interval. */
+static int
+wl_keep_alive(void *wl, cmd_t *cmd, char **argv)
+{
+	const char		*str;
+	wl_keep_alive_pkt_t	keep_alive_pkt;
+	wl_keep_alive_pkt_t	*keep_alive_pktp;
+	int						buf_len;
+	int						str_len;
+	int						i;
+	int						rc;
+	void						*ptr = NULL;
+
+	memset(&keep_alive_pkt, 0, sizeof(keep_alive_pkt));
+
+	if (*++argv == NULL) {
+	   /*
+	   ** Get current keep-alive status.
+	   */
+		if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return rc;
+
+		keep_alive_pktp = (wl_keep_alive_pkt_t *) ptr;
+
+		printf("Period (msec) :%d\n"
+		       "Length        :%d\n"
+		       "Packet        :0x",
+		       dtoh32(keep_alive_pktp->period_msec),
+		       dtoh16(keep_alive_pktp->len_bytes));
+
+		for (i = 0; i < keep_alive_pktp->len_bytes; i++)
+			printf("%02x", keep_alive_pktp->data[i]);
+
+		printf("\n");
+	}
+	else {
+		/*
+		** Set keep-alive attributes.
+		*/
+
+		str = "keep_alive";
+		str_len = strlen(str);
+		strncpy(buf, str, str_len);
+		buf[ str_len ] = '\0';
+
+		keep_alive_pktp = (wl_keep_alive_pkt_t *) (buf + str_len + 1);
+		keep_alive_pkt.period_msec = htod32(strtoul(*argv, NULL, 0));
+		buf_len = str_len + 1;
+
+
+		if (keep_alive_pkt.period_msec == 0) {
+			keep_alive_pkt.len_bytes = 0;
+
+			buf_len += sizeof(wl_keep_alive_pkt_t);
+		}
+		else {
+			if (NULL != *++argv) {
+				keep_alive_pkt.len_bytes =
+				htod16(wl_pattern_atoh(*argv, (char *) keep_alive_pktp->data));
+				buf_len += (WL_KEEP_ALIVE_FIXED_LEN + keep_alive_pkt.len_bytes);
+			}
+			else {
+				keep_alive_pkt.len_bytes = 0;
+				buf_len += WL_KEEP_ALIVE_FIXED_LEN;
+			}
+		}
+
+		/* Keep-alive attributes are set in local	variable (keep_alive_pkt), and
+		 * then memcpy'ed into buffer (keep_alive_pktp) since there is no
+		 * guarantee that the buffer is properly aligned.
+		 */
+		memcpy((char *)keep_alive_pktp, &keep_alive_pkt, WL_KEEP_ALIVE_FIXED_LEN);
+
+
+		rc = wlu_set(wl,
+		            WLC_SET_VAR,
+		            buf,
+		            buf_len);
+
+	}
+
+	return (rc);
+}
diff --git a/wl/src/wl/exe/wluc_keymgmt.c b/wl/src/wl/exe/wluc_keymgmt.c
new file mode 100644
index 0000000..4523a1e
--- /dev/null
+++ b/wl/src/wl/exe/wluc_keymgmt.c
@@ -0,0 +1,420 @@
+/*
+ * wl keymgmt command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_keymgmt.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_wepstatus;
+static cmd_func_t wl_addwep, wl_rmwep;
+static cmd_func_t wl_primary_key;
+static cmd_func_t wl_keys, wl_wsec_test;
+static cmd_func_t wl_tsc;
+
+static cmd_t wl_keymgmt_cmds[] = {
+	{ "wepstatus", wl_wepstatus, -1, -1, /* Deprecated. Use "wsec" */
+	"Set or Get WEP status\n"
+	"\twepstatus [on|off]" },
+	{ "primary_key", wl_primary_key, WLC_GET_KEY_PRIMARY, WLC_SET_KEY_PRIMARY,
+	"Set or get index of primary key" },
+	{ "addwep", wl_addwep, -1, WLC_SET_KEY,
+	"Set an encryption key.  The key must be 5, 13 or 16 bytes long, or\n"
+	"\t10, 26, 32, or 64 hex digits long.  The encryption algorithm is\n"
+	"\tautomatically selected based on the key size. keytype is accepted\n"
+	"\tonly when key length is 16 bytes/32 hex digits and specifies\n"
+	"\twhether AES-OCB or AES-CCM encryption is used. Default is ccm.\n"
+	"\tWAPI is selected if key len is 32 and arguments contain wapi.\n"
+	"\taddwep <keyindex> <keydata> [ocb | ccm | wapi] [notx] [xx:xx:xx:xx:xx:xx]" },
+	{ "rmwep", wl_rmwep, -1, WLC_SET_KEY,
+	"Remove the encryption key at the specified key index." },
+	{ "keys", wl_keys, WLC_GET_KEY, -1,
+	"Prints a list of the current WEP keys" },
+	{ "tsc", wl_tsc, WLC_GET_KEY_SEQ, -1,
+	"Print Tx Sequence Couter for key at specified key index." },
+	{ "wsec_test", wl_wsec_test, -1, WLC_SET_WSEC_TEST,
+	"Generate wsec errors\n"
+	"\twsec_test <test_type> <keyindex|xx:xx:xx:xx:xx:xx>\n"
+	"\ttype \'wl wsec_test ?\' for test_types" },
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_keymgmt_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register keymgmt commands */
+	wl_module_cmds_register(wl_keymgmt_cmds);
+}
+
+
+static int
+wl_wepstatus(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error;
+	const char *name = "wsec";
+	int wsec;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv) {
+		if ((error = wlu_iovar_getint(wl, name, &val) < 0))
+			return error;
+
+		printf("%d\n", val);
+		return 0;
+	} else {
+		val = atoi(*argv);
+		if ((error = wlu_iovar_getint(wl, name, &wsec) < 0))
+			return error;
+
+		if (val)
+			wsec |= WEP_ENABLED;
+		else
+			wsec &= ~WEP_ENABLED;
+
+		return wlu_iovar_setint(wl, name, wsec);
+	}
+}
+
+static int
+wl_primary_key(void *wl, cmd_t *cmd, char **argv)
+{
+	int i, val, ret = 0;
+
+	if (!*++argv) {
+		i = 0;
+		do {
+			val = htod32(i);
+			if ((ret = wlu_get(wl, cmd->get, &val, sizeof(val))) < 0) {
+				return ret;
+			}
+			if (dtoh32(val)) {
+				printf("Key %d is primary\n", i);
+				return 0;
+			}
+		} while (++i < DOT11_MAX_DEFAULT_KEYS);
+		printf("No primary key set\n");
+
+	} else {
+		val = htod32(atoi(*argv));
+		ret = wlu_set(wl, cmd->set, &val, sizeof(val));
+	}
+	return ret;
+}
+
+static int
+wl_addwep(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_wsec_key_t key;
+	int bsscfg_idx = 0;
+	int consumed;
+	int error;
+
+	memset(&key, 0, sizeof(key));
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "addwep", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	/* GET operation not allowed */
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	key.index = atoi(*argv++);
+
+	if (!*argv) {
+		fprintf(stderr, "No key specified\n");
+		return BCME_USAGE_ERROR;
+	}
+	if (parse_wep(argv, &key, TRUE))
+		return BCME_BADARG;
+
+	key.index = htod32(key.index);
+	key.len = htod32(key.len);
+	key.algo = htod32(key.algo);
+	key.flags = htod32(key.flags);
+
+	if (consumed == 0) {
+		error = wlu_set(wl, cmd->set, &key, sizeof(key));
+	} else {
+		error = wlu_bssiovar_setbuf(wl, "wsec_key", bsscfg_idx,
+			&key, sizeof(key), buf, WLC_IOCTL_MAXLEN);
+	}
+
+	return error;
+}
+
+static int
+wl_rmwep(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_wsec_key_t key;
+	int bsscfg_idx = 0;
+	int consumed;
+	int error;
+
+	memset(&key, 0, sizeof(key));
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((error = wl_cfg_option(argv, "rmwep", &bsscfg_idx, &consumed)) != 0)
+		return error;
+
+	argv += consumed;
+
+	/* GET operation not allowed */
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	key.index = htod32(atoi(*argv++));
+
+	if (*argv) {
+		if (!(wl_ether_atoe(*argv, &key.ea)))
+			return BCME_USAGE_ERROR;
+	}
+
+	if (consumed == 0) {
+		error = wlu_set(wl, cmd->set, &key, sizeof(key));
+	} else {
+		error = wlu_var_setbuf(wl, "wsec_key", &key, sizeof(key));
+	}
+
+	return error;
+}
+
+static struct {
+	uint value;
+	const char *string;
+} wsec_test[] = {
+	{WSEC_GEN_MIC_ERROR, 	"mic_error"},
+	{WSEC_GEN_REPLAY, 	"replay"},
+	{WSEC_GEN_ICV_ERROR, "icv_error"},
+	{WSEC_GEN_MFP_ACT_ERROR, "act_error"},
+	{WSEC_GEN_MFP_DISASSOC_ERROR, "disassoc_error"},
+	{WSEC_GEN_MFP_DEAUTH_ERROR, "deauth_error"},
+	{0,		NULL}
+};
+
+
+static int
+wl_wsec_test(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_wsec_key_t *key;
+	int i, len;
+	char *endptr = NULL, *wsec_buf = NULL;
+	uint32 val, last_val;
+	int err = 0;
+
+	if (!*++argv) {
+		err = BCME_USAGE_ERROR;
+		goto usage;
+	}
+
+	val = strtol(*argv, &endptr, 0);
+	if (endptr == *argv) {
+		/* the value string was not parsed by strtol */
+		for (i = 0; wsec_test[i].value; i++)
+			if (stricmp(wsec_test[i].string, *argv) == 0) {
+				val = wsec_test[i].value;
+				break;
+			}
+		if (wsec_test[i].value == 0) {
+			err = BCME_BADARG;
+			goto usage;
+		}
+	}
+	++argv;
+
+	switch (val) {
+	case WSEC_GEN_REPLAY:
+	case WSEC_GEN_MIC_ERROR:
+	case WSEC_GEN_ICV_ERROR:
+	case WSEC_GEN_MFP_ACT_ERROR:
+	case WSEC_GEN_MFP_DISASSOC_ERROR:
+	case WSEC_GEN_MFP_DEAUTH_ERROR:
+		if (!*argv) {
+			fprintf(stderr, "insufficient arguments\n");
+			return BCME_USAGE_ERROR;
+		}
+		len = sizeof(wl_wsec_key_t) + 4;
+		wsec_buf = malloc(len);
+		if (wsec_buf == NULL) {
+			fprintf(stderr, "Error allocating memory failed for wsec_buf");
+			return BCME_NOMEM;
+		}
+		*(uint32 *)wsec_buf = htod32(val);
+		key = (wl_wsec_key_t *)&wsec_buf[4];
+		memset(key, 0, sizeof(wl_wsec_key_t));
+		/* If it doesn't look like an ether addr, suppose it's a key index */
+		if (!(wl_ether_atoe(*argv, &key->ea))) {
+			memset(&key->ea, 0, ETHER_ADDR_LEN);
+			key->index = htod32(atoi(*argv));
+		}
+		break;
+	default:
+		goto usage;
+	}
+
+	err = wlu_set(wl, cmd->set, wsec_buf, len);
+	free(wsec_buf);
+	goto exit;
+
+usage:
+	fprintf(stderr, "wsec test_type may be a number or name from the following set:");
+	last_val = 0xffffffff;
+	for (i = 0; (val = wsec_test[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, wsec_test[i].string);
+		else
+			fprintf(stderr, ", %s", wsec_test[i].string);
+		last_val = val;
+	}
+	fprintf(stderr, "\n");
+
+exit:
+	return err;
+}
+
+static int
+wl_keys(void *wl, cmd_t *cmd, char **argv)
+{
+	uint i, j;
+	union {
+		int index;
+		wl_wsec_key_t key;
+	} u;
+	int wep_is_on = 0;
+	const char *addr;
+	int ret = BCME_OK;
+
+	UNUSED_PARAMETER(argv);
+
+	if (wlu_iovar_getint(wl, "wsec", &wep_is_on) < 0)
+		fprintf(stderr, "Could not query wsec status.\n");
+
+	for (i = 0; i < 256; i++) {
+		memset(&u, 0, sizeof(u));
+		u.index = htod32(i);
+		ret = wlu_get(wl, cmd->get, &u, sizeof(u));
+		if (ret == BCME_IOCTL_ERROR) {
+			int bcmerr;
+			if (wlu_iovar_getint(wl, "bcmerror", &bcmerr) >= 0 &&
+				(bcmerr == BCME_BADKEYIDX)) {
+				ret = BCME_OK;
+			}
+		}
+
+		if (ret != BCME_OK)
+			break;
+
+		/* ignore empty keys */
+		if (dtoh32(u.key.algo) == CRYPTO_ALGO_OFF || (u.key.len == 0))
+			continue;
+
+		if (ETHER_ISNULLADDR(&u.key.ea))
+			addr = "(default)";
+		else
+			addr = wl_ether_etoa(&u.key.ea);
+
+		printf("%3d: %-17s Key %d: %s ", i, addr, dtoh32(u.key.index),
+		       bcm_crypto_algo_name(dtoh32(u.key.algo)));
+
+		if (wep_is_on && dtoh32(u.key.flags) & WL_PRIMARY_KEY)
+			printf("*");
+		printf("\t");
+
+		if (dtoh32(u.key.len) == 0)
+			printf("No key present");
+		else {
+			if (dtoh32(u.key.flags) & WL_SOFT_KEY)
+				printf("soft ");
+			printf("len %d, data 0x", dtoh32(u.key.len));
+			for (j = 0; j < dtoh32(u.key.len); j++)
+				printf("%02X", u.key.data[j]);
+
+			for (j = 0; j < dtoh32(u.key.len); j++)
+				if (!isprint(u.key.data[j]))
+					break;
+			if (j == dtoh32(u.key.len))
+				printf(" (%.*s)", (int)dtoh32(u.key.len), u.key.data);
+
+		}
+
+		printf("\n");
+	}
+
+	return ret;
+}
+
+static int
+wl_tsc(void *wl, cmd_t *cmd, char **argv)
+{
+	union {
+		int32 index;
+		uint8 tsc[DOT11_WPA_KEY_RSC_LEN];
+	} u;
+	uint32 hi, lo;
+	int idx, ret;
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	idx = atoi(*argv);
+	if (idx < 0) {
+		fprintf(stderr, "Key index %d out of range. Should be positive.\n", idx);
+		return BCME_BADARG;
+	}
+	u.index = htod32(idx);
+	if ((ret = wlu_get(wl, cmd->get, &u, sizeof(u))) < 0)
+		return ret;
+	lo = u.tsc[0] | (u.tsc[1] << 8) | (u.tsc[2] << 16) | (u.tsc[3] << 24);
+	hi = u.tsc[4] | (u.tsc[5] << 8) | (u.tsc[6] << 16) | (u.tsc[7] << 24);
+
+	printf("Key %d TSC: 0x%04x:%08x\n", idx, hi, lo);
+	return 0;
+}
diff --git a/wl/src/wl/exe/wluc_led.c b/wl/src/wl/exe/wluc_led.c
new file mode 100644
index 0000000..ccfd697
--- /dev/null
+++ b/wl/src/wl/exe/wluc_led.c
@@ -0,0 +1,153 @@
+/*
+ * wl led command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_led.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_ledbh;
+static cmd_func_t wl_led_blink_sync;
+
+static cmd_t wl_led_cmds[] = {
+	{ "ledbh", wl_ledbh, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get led behavior\n"
+	"\tUsage: wl ledbh [0-3] [0-15]"},
+	{ "led_blink_sync", wl_led_blink_sync, WLC_GET_VAR, WLC_SET_VAR, "set/get led_blink_sync\n"
+	"\tUsage: wl led_blink_sync [0-3] [0/1]"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_led_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register led commands */
+	wl_module_cmds_register(wl_led_cmds);
+}
+
+static int
+wl_ledbh(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_led_info_t led;
+	void	*ptr = NULL;
+
+	memset(&led, 0, sizeof(wl_led_info_t));
+	if (*++argv == NULL) {
+		printf("Usage: ledbh [led#] [behavior#]\n");
+		return BCME_USAGE_ERROR;
+	}
+	led.index = (int)strtoul(*argv, NULL, 10);
+
+	if (led.index >= LED_MAX_INDEX) {
+		printf("only %d led supported\n", LED_MAX_INDEX);
+		return BCME_BADARG;
+	}
+
+	if (*++argv) {	/* set */
+		/* Read the original back so we don't toggle the activehi */
+		if ((err = wlu_var_getbuf(wl, cmd->name, (void*)&led,
+			sizeof(wl_led_info_t), &ptr)) < 0) {
+			printf("wl_ledbh: fail to get. code %x\n", err);
+		}
+		led.behavior = (int)strtoul(*argv, NULL, 10);
+		led.activehi = ((wl_led_info_t*)ptr)->activehi;
+
+		if ((err = wlu_var_setbuf(wl, cmd->name, (void*)&led,
+			sizeof(wl_led_info_t))) < 0) {
+			printf("wl_ledbh: fail to set\n");
+		}
+	} else {	/* get */
+		wl_led_info_t *ledo;
+
+		if ((err = wlu_var_getbuf(wl, cmd->name, (void*)&led,
+			sizeof(wl_led_info_t), &ptr)) < 0) {
+			printf("wl_ledbh: fail to get\n");
+		}
+		ledo = (wl_led_info_t*)ptr;
+
+		printf("led %d behavior %d\n", ledo->index, ledo->behavior);
+	}
+
+	return err;
+}
+
+static int
+wl_led_blink_sync(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = 0;
+	int in_arg[2];
+	void *ptr = NULL;
+	char *endptr;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc > 3 || argc < 2)
+		return BCME_USAGE_ERROR;
+
+	in_arg[0] = htod32((uint32)(strtoul(argv[1], &endptr, 0)));
+
+	if (in_arg[0] > 3) {
+		printf("only 4 led supported\n");
+		return BCME_BADARG;
+	}
+
+	if (argc == 2) {
+		err = wlu_var_getbuf(wl, cmd->name, (void*)in_arg, sizeof(int), &ptr);
+		if (err < 0)
+			return err;
+		printf("led%d, blink_sync is %s\n", in_arg[0],
+			(dtoh32(*(int*)ptr) != 0) ? "TRUE" : "FALSE");
+	}
+	else if (argc == 3) {
+		in_arg[1] = htod32((uint32)(strtoul(argv[2], &endptr, 0)));
+		err = wlu_var_setbuf(wl, cmd->name, in_arg, sizeof(in_arg));
+	}
+
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_lq.c b/wl/src/wl/exe/wluc_lq.c
new file mode 100644
index 0000000..ff493ca
--- /dev/null
+++ b/wl/src/wl/exe/wluc_lq.c
@@ -0,0 +1,550 @@
+/*
+ * wl lq command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_lq.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_rssi_event, wl_chan_qual_event;
+static cmd_func_t wl_chanim_state, wl_chanim_mode;
+static cmd_func_t wl_dump_lq;
+static cmd_func_t wl_monitor_lq;
+static cmd_func_t wl_chanim_acs_record;
+static cmd_func_t wl_chanim_stats;
+static int _wl_dump_lq(void *wl);
+
+static cmd_t wl_lq_cmds[] = {
+	{ "rssi_event", wl_rssi_event, WLC_GET_VAR, WLC_SET_VAR,
+	"Set parameters associated with RSSI event notification\n"
+	"\tusage: wl rssi_event <rate_limit> <rssi_levels>\n"
+	"\trate_limit: Number of events posted to application will be limited"
+	" to 1 per this rate limit. Set to 0 to disable rate limit.\n"
+	"\trssi_levels: Variable number of RSSI levels (maximum 8) "
+	" in increasing order (e.g. -85 -70 -60). An event will be posted"
+	" each time the RSSI of received beacons/packets crosses a level."},
+	{ "chq_event", wl_chan_qual_event, WLC_GET_VAR, WLC_SET_VAR,
+	"Set parameters associated with channel quality  event notification\n"
+	"\tusage: wl chq_event <rate_limit> <cca_levels> <nf_levels> <nf_lte_levels>\n"
+	"\trate_limit: Number of events posted to application will be limited"
+	" to 1 per this rate limit. Set to 0 to disable rate limit.\n"
+	"\tcsa/nf/nf_lte levels: Variable number of threshold levels (maximum 8)"
+	" in pairs of hi-to-low/lo-to-hi, and in increasing order (e.g. -90 -85 -80)."
+	" A 0 0 pair terminates level array for one metric."
+	" An event will be posted whenever a threshold is being crossed."},
+	{"chanim_state", wl_chanim_state, WLC_GET_VAR, -1,
+	"get channel interference state\n"
+	"\tUsage: wl chanim_state channel\n"
+	"\tValid channels: 1 - 14\n"
+	"\treturns: 0 - Acceptable; 1 - Severe"
+	},
+	{"chanim_mode", wl_chanim_mode, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set channel interference measure (chanim) mode\n"
+	"\tUsage: wl chanim_mode <value>\n"
+	"\tvalue: 0 - disabled; 1 - detection only; 2 - detection and avoidance"
+	},
+	{"chanim_acs_record", wl_chanim_acs_record, WLC_GET_VAR, -1,
+	"get the auto channel scan record. \n"
+	"\t Usage: wl acs_record"
+	},
+	{"chanim_stats", wl_chanim_stats, WLC_GET_VAR, -1,
+	"get chanim stats \n"
+	"\t Usage: wl chanim_stats"
+	},
+	{ "monitor_lq", wl_monitor_lq, WLC_GET_VAR, WLC_SET_VAR,
+	"Start/Stop monitoring link quality metrics - RSSI and SNR\n"
+	"\tUsage: wl monitor_lq <0: turn off / 1: turn on"},
+	{ "monitor_lq_status", wl_dump_lq, WLC_GET_VAR, -1 /* Set not reqd */,
+	"Returns averaged link quality metrics - RSSI and SNR values"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_lq_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register lq commands */
+	wl_module_cmds_register(wl_lq_cmds);
+}
+
+static int
+wl_chan_qual_event(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	const char *CHAN_QUAL_NAME[WL_CHAN_QUAL_TOTAL] = {"   CCA", "    NF", "NF_LTE"};
+
+	if (!*++argv) {
+		/* get */
+		void *ptr = NULL;
+		wl_chan_qual_event_t chq;
+		uint i, j;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		memcpy(&chq, ptr, sizeof(chq));
+		chq.rate_limit_msec = dtoh32(chq.rate_limit_msec);
+
+		printf("rate per %dms\n", chq.rate_limit_msec);
+		for (i = 0; i < WL_CHAN_QUAL_TOTAL; i++) {
+			printf("%s[%d]:", CHAN_QUAL_NAME[i], chq.metric[i].id);
+			for (j = 0; (j < chq.metric[i].num_levels) &&
+				(j < MAX_CHAN_QUAL_LEVELS); j++) {
+				printf(" (%d, %d)", chq.metric[i].htol[j], chq.metric[i].ltoh[j]);
+			}
+			printf("\n");
+		}
+	} else {
+		/* set */
+		wl_chan_qual_event_t chq;
+		uint i;
+
+		memset(&chq, 0, sizeof(wl_chan_qual_event_t));
+		chq.rate_limit_msec = atoi(*argv++);
+		chq.rate_limit_msec = htod32(chq.rate_limit_msec);
+		chq.num_metrics = htod16(WL_CHAN_QUAL_TOTAL);
+
+		for (i = 0; i < WL_CHAN_QUAL_TOTAL; i++) {
+			chq.metric[i].id = i;
+			while (argv[0] && argv[1]) {
+				int16 htol, ltoh;
+				htol = htod16(atoi(*argv++));
+				ltoh = htod16(atoi(*argv++));
+
+				/* double zeros terminate one metric */
+				if ((htol == 0) && (ltoh == 0))
+					break;
+
+				/* make sure that ltoh >= htol */
+				if (ltoh < htol)
+					return -1;
+
+				/* ignore extra thresholds */
+				if (chq.metric[i].num_levels >= MAX_CHAN_QUAL_LEVELS)
+					continue;
+
+				chq.metric[i].htol[chq.metric[i].num_levels] = htol;
+				chq.metric[i].ltoh[chq.metric[i].num_levels] = ltoh;
+
+				/* all metric threshold levels must be in increasing order */
+				if (chq.metric[i].num_levels > 0) {
+					if ((chq.metric[i].htol[chq.metric[i].num_levels] <=
+						chq.metric[i].htol[chq.metric[i].num_levels - 1]) ||
+					    (chq.metric[i].ltoh[chq.metric[i].num_levels] <=
+						chq.metric[i].ltoh[chq.metric[i].num_levels - 1])) {
+						return -1;
+					}
+				}
+
+				(chq.metric[i].num_levels)++;
+			}
+		}
+
+		if (*argv) {
+			/* too many parameters */
+			return -1;
+		}
+
+		ret = wlu_var_setbuf(wl, cmd->name, &chq, sizeof(chq));
+	}
+	return ret;
+}
+
+static int
+wl_rssi_event(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+
+	if (!*++argv) {
+		/* get */
+		void *ptr = NULL;
+		wl_rssi_event_t rssi;
+		uint i;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		memcpy(&rssi, ptr, sizeof(rssi));
+		rssi.rate_limit_msec = dtoh32(rssi.rate_limit_msec);
+
+		printf("%d", rssi.rate_limit_msec);
+		for (i = 0; i < rssi.num_rssi_levels; i++) {
+			printf(" %d", rssi.rssi_levels[i]);
+		}
+		printf("\n");
+	} else {
+		/* set */
+		wl_rssi_event_t rssi;
+
+		memset(&rssi, 0, sizeof(wl_rssi_event_t));
+		rssi.rate_limit_msec = atoi(*argv);
+
+		while (*++argv && rssi.num_rssi_levels < MAX_RSSI_LEVELS) {
+			rssi.rssi_levels[rssi.num_rssi_levels++] = atoi(*argv);
+			if (rssi.num_rssi_levels > 1) {
+				if (rssi.rssi_levels[rssi.num_rssi_levels - 1] <=
+					rssi.rssi_levels[rssi.num_rssi_levels - 2]) {
+					/* rssi levels must be in increasing order */
+					return BCME_USAGE_ERROR;
+				}
+			}
+		}
+
+		if (*argv) {
+			/* too many parameters */
+			return BCME_USAGE_ERROR;
+		}
+
+		rssi.rate_limit_msec = htod32(rssi.rate_limit_msec);
+		ret = wlu_var_setbuf(wl, cmd->name, &rssi, sizeof(rssi));
+	}
+	return ret;
+}
+
+static int
+wl_chanim_state(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 chanspec;
+	int argc = 0;
+	int ret, val;
+
+	argv++;
+
+	/* find the arg count */
+	while (argv[argc])
+		argc++;
+
+	if (argc != 1)
+		return BCME_USAGE_ERROR;
+
+	chanspec = wf_chspec_aton(*argv);
+	chanspec = wl_chspec32_to_driver(chanspec);
+	if (chanspec == INVCHANSPEC) {
+		return BCME_USAGE_ERROR;
+	}
+
+	ret = wlu_iovar_getbuf(wl, cmd->name, &chanspec, sizeof(chanspec),
+	                       buf, WLC_IOCTL_SMLEN);
+	if (ret < 0)
+		return ret;
+	val = *(int*)buf;
+	val = dtoh32(val);
+
+	printf("%d\n", val);
+	return 0;
+}
+
+static int
+wl_chanim_mode(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char *endptr;
+	int mode;
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((ret = wlu_iovar_getint(wl, cmd->name, &mode)) < 0)
+			return ret;
+
+		switch (mode) {
+		case CHANIM_DISABLE:
+			printf("CHANIM mode: disabled.\n");
+			break;
+		case CHANIM_DETECT:
+			printf("CHANIM mode: detect only.\n");
+			break;
+		case CHANIM_EXT:
+			printf("CHANIM mode: external (acsd).\n");
+			break;
+		case CHANIM_ACT:
+			printf("CHANIM mode: detect + act.\n");
+			break;
+		}
+		return 0;
+	} else {
+		mode = CHANIM_DETECT;
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		switch (val) {
+			case 0:
+				mode = CHANIM_DISABLE;
+				break;
+			case 1:
+				mode = CHANIM_DETECT;
+				break;
+			case 2:
+				mode = CHANIM_EXT;
+				break;
+			case 3:
+				mode = CHANIM_ACT;
+				break;
+			default:
+				return BCME_BADARG;
+		}
+
+		mode = htod32(mode);
+		return wlu_iovar_setint(wl, cmd->name, mode);
+	}
+}
+
+static int
+_wl_dump_lq(void *wl)
+{
+	int ret = BCME_OK, noise = 0;
+	wl_lq_t *plq = NULL;
+	void *ptr = NULL;
+
+	memset(buf, 0, sizeof(wl_lq_t));
+
+	/* Display stats when disabled */
+	if ((ret = wlu_get(wl, WLC_GET_PHY_NOISE, &noise, sizeof(int))) < 0) {
+		printf("wlc_get noise failed with retcode:%d\n", ret);
+		return ret;
+	}
+
+	if ((ret = wlu_var_getbuf_sm (wl, "monitor_lq_status", NULL, 0, &ptr)) < 0) {
+		printf("wlc_get lq_status failed with retcode:%d\n", ret);
+		return ret;
+	}
+
+	plq = (wl_lq_t *)ptr;
+
+	if (!plq->isvalid) {
+		printf("Stats collection currently disabled"
+	               "['wl monitor_lq 1' to enable statistics collection]\n");
+		return ret;
+	}
+
+	noise = dtoh32(noise);
+	plq->rssi[LQ_IDX_MIN] = dtoh32(plq->rssi[LQ_IDX_MIN]);
+	plq->rssi[LQ_IDX_MAX] = dtoh32(plq->rssi[LQ_IDX_MAX]);
+	plq->rssi[LQ_IDX_AVG] = dtoh32(plq->rssi[LQ_IDX_AVG]);
+
+	printf("rss: %d, %d, %d\nsnr: %d, %d, %d\n",
+		plq->rssi[LQ_IDX_MIN],
+		plq->rssi[LQ_IDX_AVG],
+		plq->rssi[LQ_IDX_MAX],
+		plq->rssi[LQ_IDX_MIN]-noise,
+		plq->rssi[LQ_IDX_AVG]-noise,
+		plq->rssi[LQ_IDX_MAX]-noise);
+
+	return ret;
+} /* _wl_dump_lq */
+
+static int
+wl_dump_lq(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv)
+		ret = _wl_dump_lq(wl);
+
+	return ret;
+} /* wl_dump_lq */
+
+static int
+wl_monitor_lq(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	char *endptr = NULL;
+	char **startptr = argv;
+
+	if (!*++startptr) { /* Get */
+		ret = wl_varint(wl, cmd, argv);
+	}
+	else {
+		int val = *startptr[0];
+		val = strtol(*startptr, &endptr, 0);
+
+		if (*endptr != '\0') {
+			return BCME_USAGE_ERROR;
+		}
+
+		val = htod32(val);
+
+		if (val == LQ_STOP_MONITOR) {
+			if ((ret = _wl_dump_lq(wl)))
+				return ret;
+		}
+
+		ret = wl_varint(wl, cmd, argv); /* Standard set call after getting stats */
+	}
+
+	return ret;
+} /* wl_monitor_lq */
+
+static int
+wl_chanim_acs_record(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr = NULL;
+	int err = 0, i;
+	wl_acs_record_t *result;
+
+	/* need to add to this str if new acs trigger type is added */
+	const char *trig_str[] = {"None", "IOCTL", "CHANIM", "TIMER", "BTA"};
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return err;
+
+	result = (wl_acs_record_t *) ptr;
+
+	if (!result->count) {
+		printf("There is no ACS recorded\n");
+		return err;
+	}
+
+	printf("current timestamp: %u (ms)\n", result->timestamp);
+
+	printf("Timestamp(ms)  ACS Trigger  Selected Channel  Glitch Count  CCA Count\n");
+	for (i = 0; i < result->count; i++) {
+		uint8 idx = CHANIM_ACS_RECORD - result->count + i;
+		chanim_acs_record_t * record = &result->acs_record[idx];
+
+		record->selected_chspc = wl_chspec_from_driver(record->selected_chspc);
+
+		printf("%10u \t%s \t%10d \t%12d \t%8d\n", record->timestamp,
+		   trig_str[record->trigger], wf_chspec_ctlchan(record->selected_chspc),
+		   record->glitch_cnt, record->ccastats);
+	}
+	return err;
+}
+
+static int
+wl_chanim_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_chanim_stats_t *stats;
+	int stats_size;
+	int i, err;
+	void *ptr;
+
+	UNUSED_PARAMETER(argv);
+
+	/* get fw chanim stats version */
+	stats_size = WL_CHANIM_STATS_FIXED_LEN +
+		MAX(sizeof(chanim_stats_t), sizeof(chanim_stats_v2_t));
+	stats = (wl_chanim_stats_t *)malloc(stats_size);
+	if (stats == NULL) {
+		fprintf(stderr, "memory alloc failure\n");
+		return BCME_NOMEM;
+	}
+	memset(stats, 0, stats_size);
+
+	stats->buflen = htod32(stats_size);
+	if ((err = wlu_var_getbuf(wl, cmd->name, stats, stats_size, &ptr)) < 0) {
+		printf("failed to get chanim results");
+		free(stats);
+		return err;
+	}
+	memcpy(stats, ptr, stats_size);
+
+	stats->version = dtoh32(stats->version);
+	if (!((stats->version == WL_CHANIM_STATS_VERSION) ||
+		(stats->version == WL_CHANIM_STATS_V2))) {
+		printf("Sorry, your driver has wl_chanim_stats version %d "
+			"but this program supports only version %d and %d.\n",
+			stats->version, WL_CHANIM_STATS_V2, WL_CHANIM_STATS_VERSION);
+		free(stats);
+		return 0;
+	}
+
+	/* get fw chanim stats */
+	stats->buflen = htod32(stats_size);
+	stats->count = htod32(WL_CHANIM_COUNT_ONE);
+	if ((err = wlu_var_getbuf(wl, cmd->name, stats, stats_size, &ptr)) < 0) {
+		printf("failed to get chanim results");
+		free(stats);
+		return err;
+	}
+	memcpy(stats, ptr, stats_size);
+	stats->version = dtoh32(stats->version);
+	stats->buflen = dtoh32(stats->buflen);
+	stats->count = dtoh32(stats->count);
+
+	printf("version: %d \n", stats->version);
+
+	if (stats->version == WL_CHANIM_STATS_VERSION) {
+		chanim_stats_t *stats_v3 = (chanim_stats_t *)stats->stats;
+		stats_v3->glitchcnt = dtoh32(stats_v3->glitchcnt);
+		stats_v3->badplcp = dtoh32(stats_v3->badplcp);
+		stats_v3->chanspec = dtoh16(stats_v3->chanspec);
+		stats_v3->timestamp = dtoh32(stats_v3->timestamp);
+
+		printf("chanspec tx   inbss   obss   nocat   nopkt   doze     txop     "
+				"goodtx  badtx   glitch   badplcp  knoise  idle  timestamp\n");
+		printf("0x%4x\t", stats_v3->chanspec);
+		for (i = 0; i < CCASTATS_MAX; i++) {
+			printf("%d\t", stats_v3->ccastats[i]);
+		}
+		printf("%d\t%d\t%d\t%d\t%d", stats_v3->glitchcnt, stats_v3->badplcp,
+				stats_v3->bgnoise, stats_v3->chan_idle, stats_v3->timestamp);
+		printf("\n");
+	} else if (stats->version == WL_CHANIM_STATS_V2) {
+		chanim_stats_v2_t *stats_v2 = (chanim_stats_v2_t *)stats->stats;
+		stats_v2->glitchcnt = dtoh32(stats_v2->glitchcnt);
+		stats_v2->badplcp = dtoh32(stats_v2->badplcp);
+		stats_v2->chanspec = dtoh16(stats_v2->chanspec);
+		stats_v2->timestamp = dtoh32(stats_v2->timestamp);
+
+		printf("chanspec tx   inbss   obss   nocat   nopkt   doze     txop     "
+				"goodtx  badtx   glitch   badplcp  knoise  idle  timestamp\n");
+		printf("0x%4x\t", stats_v2->chanspec);
+		for (i = 0; i < CCASTATS_V2_MAX; i++) {
+			 printf("%d\t", stats_v2->ccastats[i]);
+		}
+		printf("%d\t%d\t%d\t%d\t%d", stats_v2->glitchcnt, stats_v2->badplcp,
+				stats_v2->bgnoise, stats_v2->chan_idle, stats_v2->timestamp);
+		printf("\n");
+	}
+
+	free(stats);
+	return (err);
+}
diff --git a/wl/src/wl/exe/wluc_ltecx.c b/wl/src/wl/exe/wluc_ltecx.c
new file mode 100644
index 0000000..2931490
--- /dev/null
+++ b/wl/src/wl/exe/wluc_ltecx.c
@@ -0,0 +1,516 @@
+/*
+ * wl ltecx command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_ltecx.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+/* LTE coex funcs */
+static cmd_func_t wl_wci2_config;
+static cmd_func_t wl_mws_params;
+static cmd_func_t wl_mws_wci2_msg;
+static cmd_func_t wl_mws_frame_config;
+static cmd_func_t wl_mws_antmap;
+static cmd_func_t wl_mws_oclmap;
+static cmd_func_t wl_mws_scanreq_bm;
+
+static cmd_t wl_ltecx_cmds[] = {
+	{ "wci2_config", wl_wci2_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set LTE coex MWS signaling config\n"
+	"\tUsage: wl wci2_config <rxassert_off> <rxassert_jit> <rxdeassert_off> <rxdeassert_jit> "
+	"<txassert_off> <txassert_jit> <txdeassert_off> <txdeassert_jit> "
+	"<patassert_off> <patassert_jit> <inactassert_off> <inactassert_jit> "
+	"<scanfreqassert_off> <scanfreqassert_jit> <priassert_off_req>"},
+	{ "mws_params", wl_mws_params, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set LTE coex MWS channel params\n"
+	"\tUsage: wl mws_params <rx_center_freq> <tx_center_freq> "
+	"<rx_channel_bw> <tx_channel_bw> <channel_en> <channel_type>"},
+	{ "mws_debug_msg", wl_mws_wci2_msg, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set LTE coex BT-SIG message\n"
+	"\tUsage: wl mws_debug_msg <Message> <Interval 20us-32000us> "
+	"<Repeats>"},
+	{ "mws_frame_config", wl_mws_frame_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set LTE Frame configuration\n"
+	"\tUsage: wl mws_frame_config <mws_frame_dur> <mws_framesync_assert_offset>"
+	"<mws_framesync_assert_jitter> <mws_num_periods>"
+	"{<mws_period_dur[i]> <mws_period_type>[i]}"},
+	{ "mws_antenna_selection", wl_mws_antmap, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set Antenna selection params\n"
+	"\tUsage: wl mws_antenna_selection <band-AntTx-combo1> <band-AntTx-combo2> "
+	"<band-AntTx-combo3> <band-AntTx-combo4>\n"},
+	{ "mws_ocl_override", wl_mws_oclmap, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set OCL maps\n"
+	"\tUsage: wl mws_ocl_override <bitmap_2G> <bitmap_5G_lo> "
+	"<bitmap_5G_mid> <bitmap_5G_high>\n"},
+	{ "mws_scanreq_bm", wl_mws_scanreq_bm, WLC_GET_VAR, WLC_SET_VAR,
+	"\tusage: wl mws_scanreq_bm [idx 2.4G-bitmap 5G-bitmap-lo 5G-bitmap-mid 5G-bitmap-hi]\n"
+	"Set/Get the channel bitmaps corresponding to MWS (cellular) scan index <idx>"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_ltecx_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register ltecx commands */
+	wl_module_cmds_register(wl_ltecx_cmds);
+}
+
+static int
+wl_wci2_config(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+	char *endptr = NULL;
+	uint argc;
+	wci2_config_t wci2_config;
+	uint16 *configp = (uint16 *)&wci2_config;
+	int ret, i;
+
+	UNUSED_PARAMETER(cmd);
+
+	val = 0;
+
+	/* eat command name */
+	argv++;
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	memset(&wci2_config, '\0', sizeof(wci2_config_t));
+
+	if (argc == 0) {
+		/* Get and print the values */
+		ret = wlu_iovar_getbuf(wl, "wci2_config", &wci2_config, sizeof(wci2_config_t),
+		buf, WLC_IOCTL_SMLEN);
+		if (ret)
+			return ret;
+
+		printf("rxassert_off %d rxassert_jit %d rxdeassert_off %d rxdeassert_jit %d "
+			"txassert_off %d txassert_jit %d txdeassert_off %d txdeassert_jit %d "
+			"patassert_off %d patassert_jit %d inactassert_off %d inactassert_jit %d "
+			"scanfreqassert_off %d scanfreqassert_jit %d priassert_off_req %d\n",
+			dtoh16(((uint16 *)buf)[0]), dtoh16(((uint16 *)buf)[1]),
+			dtoh16(((uint16 *)buf)[2]), dtoh16(((uint16 *)buf)[3]),
+			dtoh16(((uint16 *)buf)[4]), dtoh16(((uint16 *)buf)[5]),
+			dtoh16(((uint16 *)buf)[6]), dtoh16(((uint16 *)buf)[7]),
+			dtoh16(((uint16 *)buf)[8]), dtoh16(((uint16 *)buf)[9]),
+			dtoh16(((uint16 *)buf)[10]), dtoh16(((uint16 *)buf)[11]),
+			dtoh16(((uint16 *)buf)[12]), dtoh16(((uint16 *)buf)[13]),
+			dtoh16(((uint16 *)buf)[14]));
+		return 0;
+	}
+
+	if (argc < 15)
+		goto usage;
+
+	for (i = 0; i < 15; ++i) {
+		val = strtoul(argv[i], &endptr, 0);
+		if (*endptr != '\0')
+			goto usage;
+		configp[i] = htod16((uint16)val);
+	}
+	return wlu_iovar_setbuf(wl, "wci2_config", &wci2_config, sizeof(wci2_config_t),
+		buf, WLC_IOCTL_SMLEN);
+
+usage:
+	return BCME_USAGE_ERROR;
+}
+
+static int
+wl_mws_params(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+	char *endptr = NULL;
+	uint argc;
+	mws_params_t mws_params;
+	uint16 *paramsp = (uint16 *)&mws_params;
+	int ret, i;
+
+	UNUSED_PARAMETER(cmd);
+
+	val = 0;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	memset(&mws_params, '\0', sizeof(mws_params_t));
+
+	if (argc == 0) {
+		/* Get and print the values */
+		ret = wlu_iovar_getbuf(wl, "mws_params", &mws_params, sizeof(mws_params_t),
+		buf, WLC_IOCTL_SMLEN);
+		if (ret)
+			return ret;
+
+		printf("rx_center_freq %d tx_center_freq %d  rx_channel_bw %d tx_channel_bw %d "
+			"channel_en %d channel_type %d\n",
+			dtoh16(((uint16 *)buf)[0]), dtoh16(((uint16 *)buf)[1]),
+			dtoh16(((uint16 *)buf)[2]), dtoh16(((uint16 *)buf)[3]), buf[8], buf[9]);
+		return 0;
+	}
+
+	if (argc < 6)
+		goto usage;
+	for (i = 0; i < 4; ++i) {
+		val = strtoul(argv[i], &endptr, 0);
+		if (*endptr != '\0')
+			goto usage;
+		paramsp[i] = htod16((uint16)val);
+	}
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	mws_params.mws_channel_en = val;
+	++i;
+	val = strtoul(argv[i], &endptr, 0);
+	if (*endptr != '\0')
+		goto usage;
+	mws_params.mws_channel_type = val;
+
+	return wlu_iovar_setbuf(wl, "mws_params", &mws_params, sizeof(mws_params_t),
+		buf, WLC_IOCTL_SMLEN);
+
+usage:
+	return BCME_USAGE_ERROR;
+}
+
+static int
+wl_mws_wci2_msg(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+	char *endptr = NULL;
+	uint argc;
+	mws_wci2_msg_t mws_wci2_msg;
+	uint16 *paramsp = (uint16 *)&mws_wci2_msg;
+	int ret, i = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	val = 0;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	memset(&mws_wci2_msg, '\0', sizeof(mws_wci2_msg_t));
+
+	if (argc == 0) {
+		/* Get and print the values */
+		ret = wlu_iovar_getbuf(wl, "mws_debug_msg", &mws_wci2_msg, sizeof(mws_wci2_msg_t),
+		buf, WLC_IOCTL_SMLEN);
+		if (ret)
+			return ret;
+
+		printf("Message %d Interval %d  Repeats %d \n",
+			dtoh16(((uint16 *)buf)[0]), dtoh16(((uint16 *)buf)[1]),
+			dtoh16(((uint16 *)buf)[2]));
+		return 0;
+	}
+
+	if (argc < 3)
+		goto usage;
+
+	for (i = 0; i < 3; ++i) {
+		val = strtoul(argv[i], &endptr, 0);
+		if (*endptr != '\0')
+			goto usage;
+		paramsp[i] = htod16((uint16)val);
+	}
+	if ((paramsp[1] < 20) || (paramsp[1] > 32000))
+		goto usage;
+	return wlu_iovar_setbuf(wl, "mws_debug_msg", &mws_wci2_msg, sizeof(mws_wci2_msg_t),
+		buf, WLC_IOCTL_SMLEN);
+
+usage:
+	return BCME_USAGE_ERROR;
+}
+
+static int
+wl_mws_frame_config(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+	char *endptr = NULL;
+	uint argc;
+	mws_frame_config_t mws_frame_config;
+	uint16 *paramsp = (uint16 *)&mws_frame_config;
+	int ret, j = 3, k = 4, l = 20;
+	uint8 i = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	val = 0;
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	memset(&mws_frame_config, '\0', sizeof(mws_frame_config_t));
+
+	if (argc == 0) {
+		/* Get and print the values */
+		ret = wlu_iovar_getbuf(wl, "mws_frame_config", &mws_frame_config,
+		sizeof(mws_frame_config_t), buf, WLC_IOCTL_SMLEN);
+		if (ret) {
+			return ret;
+		}
+		printf("mws_frame_dur %d us mws_framesync_assert_offset %d "
+		"mws_framesync_assert_jitter %d mws_num_periods %d \n",
+		dtoh16(((uint16 *)buf)[0]), dtoh16(((uint16 *)buf)[1]),
+		dtoh16(((uint16 *)buf)[2]), buf[27]);
+		for (i = 0; i < buf[27]; i++) {
+			printf("mws_period_dur[%d] %d us mws_period_type[%d] %d\n",
+			i, dtoh16(((uint16 *)buf)[j]), i, buf[l]);
+			j++;
+			l++;
+		}
+		return 0;
+	}
+
+	if (argc <= 4)
+		goto usage;
+	/* Loop to populate the first three elements of the structure */
+	for (i = 0; i < 3; ++i) {
+		val = strtoul(argv[i], &endptr, 0);
+		if (*endptr != '\0')
+			goto usage;
+		paramsp[i] = htod16((uint16)val);
+	}
+
+	val = strtoul(argv[3], &endptr, 0);
+		if (*endptr != '\0')
+			goto usage;
+		mws_frame_config.mws_num_periods = val;
+
+	/* Error check for insufficient data entered */
+	if ((uint8)argc != ((mws_frame_config.mws_num_periods * 2) + 4)) {
+		goto usage;
+	}
+	/* Loop to populate the arrays of size equal to mws_frame_config.mws_num_periods */
+	for (i = 0; i < mws_frame_config.mws_num_periods; i++)
+	{
+		val = strtoul(argv[k], &endptr, 0);
+		if (*endptr != '\0') {
+			goto usage;
+		}
+		mws_frame_config.mws_period_dur[i] = val;
+		k++;
+
+		val = strtoul(argv[k], &endptr, 0);
+		if (*endptr != '\0') {
+			goto usage;
+		}
+		mws_frame_config.mws_period_type[i] = val;
+		k++;
+	}
+	/* Set the values */
+	return wlu_iovar_setbuf(wl, "mws_frame_config", &mws_frame_config,
+		sizeof(mws_frame_config_t), buf, WLC_IOCTL_SMLEN);
+
+	usage:
+	return BCME_USAGE_ERROR;
+}
+
+static int
+wl_mws_antmap(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+	char *endptr = NULL;
+	uint argc;
+	mws_ant_map_t mws_antmap;
+	uint16 *paramsp = (uint16 *)&mws_antmap;
+	int ret, i = 0, j = 0;
+	uint16 error_mask = 0xc000;
+	uint16 ant_set[4];
+	UNUSED_PARAMETER(cmd);
+	val = 0;
+	/* eat command name */
+	argv++;
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	memset(&mws_antmap, '\0', sizeof(mws_antmap));
+	if (argc == 0) {
+		/* Get and print the values */
+		ret = wlu_iovar_getbuf(wl, "mws_antenna_selection",
+			&mws_antmap, sizeof(mws_antmap),
+			buf, WLC_IOCTL_SMLEN);
+		if (ret)
+			return ret;
+		printf("band_ant_combo1 %x band_ant_combo2 %x "
+			"band_ant_combo3 %x band_ant_combo4 %x\n",
+			dtoh16(((uint16 *)buf)[0]), dtoh16(((uint16 *)buf)[1]),
+			dtoh16(((uint16 *)buf)[2]), dtoh16(((uint16 *)buf)[3]));
+		return 0;
+	}
+	if (argc < 4)
+		goto usage;
+	for (i = 0; i < 4; ++i) {
+		val = strtoul(argv[i], &endptr, 0);
+		if (*endptr != '\0')
+			goto usage;
+		paramsp[i] = htod16((uint16)val);
+		ant_set[i] = (paramsp[i] & error_mask) >> 14;
+		for (j = 0; j < i; ++j) {
+			if (ant_set[i] == ant_set[j]) {
+				printf("duplicate band ant_tx combiniation\n");
+				goto usage;
+			}
+		}
+	}
+	return wlu_iovar_setbuf(wl, "mws_antenna_selection", paramsp, sizeof(mws_antmap),
+		buf, WLC_IOCTL_SMLEN);
+usage:
+	return BCME_USAGE_ERROR;
+}
+
+static int
+wl_mws_oclmap(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 val;
+	char *endptr = NULL;
+	uint argc;
+	wl_mws_ocl_override_t mws_oclmap;
+	uint16 *paramsp = (uint16 *)&mws_oclmap;
+	int ret, i = 0;
+	UNUSED_PARAMETER(cmd);
+	val = 0;
+	/* eat command name */
+	argv++;
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	memset(&mws_oclmap, '\0', sizeof(mws_oclmap));
+	if (argc == 0) {
+		/* Get and print the values */
+		ret = wlu_iovar_getbuf(wl, "mws_ocl_override",
+			&mws_oclmap, sizeof(mws_oclmap),
+			buf, WLC_IOCTL_SMLEN);
+		if (ret)
+			return ret;
+		printf(" bitmap_2g %x bitmap_5g_lo %x "
+			"babitmap_5g_mid %x bitmap_5g_high %x\n",
+			dtoh16(((uint16 *)buf)[1]), dtoh16(((uint16 *)buf)[2]),
+			dtoh16(((uint16 *)buf)[3]), dtoh16(((uint16 *)buf)[4]));
+		return 0;
+	}
+	if (argc < 4)
+		goto usage;
+	paramsp[0] = WL_MWS_OCL_OVERRIDE_VERSION;
+	for (i = 0; i < 4; ++i) {
+		val = strtoul(argv[i], &endptr, 0);
+		if (*endptr != '\0')
+			goto usage;
+		paramsp[i+1] = htod16((uint16)val);
+	}
+	return wlu_iovar_setbuf(wl, "mws_ocl_override", paramsp, sizeof(mws_oclmap),
+		buf, WLC_IOCTL_SMLEN);
+usage:
+	return BCME_USAGE_ERROR;
+}
+
+static int
+wl_mws_scanreq_bm(void *wl, cmd_t *cmd, char **argv)
+{
+	mws_scanreq_params_t mws_scanreq_params;
+	uint16 *paramsp = (uint16 *)&mws_scanreq_params;
+	char *endptr = NULL;
+	uint32 val;
+	uint argc, i;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* eat command name */
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	memset(&mws_scanreq_params, 0, sizeof(mws_scanreq_params_t));
+
+	if (argc == 0) {
+		goto usage;
+	} else if (argc == 1) {
+		val = strtoul(argv[0], &endptr, 0);
+		if (*endptr != '\0')
+			goto usage;
+		mws_scanreq_params.idx = htod16((uint16)val);
+
+		if ((mws_scanreq_params.idx < 1) || (mws_scanreq_params.idx > 31)) {
+			printf("LTE Index should be in range 1-31\n");
+			goto usage;
+		}
+
+		err = wlu_iovar_getbuf(wl, cmd->name, &mws_scanreq_params,
+			sizeof(mws_scanreq_params_t), buf, WLC_IOCTL_SMLEN);
+		if (err < 0)
+			return err;
+		mws_scanreq_params = *(mws_scanreq_params_t *)buf;
+		printf("\n Current LTE Timesharing coex : \n"
+		"\t LTE channel index = %d\n \t 2G Channel = %d \n\t 5G low channel= %d\n"
+		"\t 5G Middle channel= %d\n\t 5G High channel= %d\n",
+		mws_scanreq_params.idx, mws_scanreq_params.bm_2g, mws_scanreq_params.bm_5g_lo,
+		mws_scanreq_params.bm_5g_mid, mws_scanreq_params.bm_5g_hi);
+		return 0;
+	} else if (argc > 1 && argc < 5) {
+		goto usage;
+	}
+	memset(&mws_scanreq_params, 0, sizeof(mws_scanreq_params_t));
+	for (i = 0; i < 5; ++i) {
+		val = strtoul(argv[i], &endptr, 0);
+		if (*endptr != '\0')
+			goto usage;
+		paramsp[i] = htod16((uint16)val);
+	}
+
+	return wlu_iovar_setbuf(wl, "mws_scanreq_bm", &mws_scanreq_params,
+		sizeof(mws_scanreq_params_t), buf, WLC_IOCTL_SMLEN);
+usage:
+	return BCME_USAGE_ERROR;
+}
diff --git a/wl/src/wl/exe/wluc_mbo.c b/wl/src/wl/exe/wluc_mbo.c
new file mode 100644
index 0000000..e55e2f5
--- /dev/null
+++ b/wl/src/wl/exe/wluc_mbo.c
@@ -0,0 +1,875 @@
+/*
+ * wl mbo command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id:$
+ */
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+#include <wlioctl.h>
+#include <bcmiov.h>
+#include <proto/mbo.h>
+
+/* from bcmiov.h: non-batched command version = major|minor w/ major <= 127 */
+#define WL_MBO_IOV_MAJOR_VER 1
+#define WL_MBO_IOV_MINOR_VER 1
+#define WL_MBO_IOV_MAJOR_VER_SHIFT 8
+#define WL_MBO_IOV_VERSION \
+	((WL_MBO_IOV_MAJOR_VER << WL_MBO_IOV_MAJOR_VER_SHIFT)| WL_MBO_IOV_MINOR_VER)
+
+typedef struct wl_mbo_sub_cmd wl_mbo_sub_cmd_t;
+typedef int (subcmd_handler_t)(void *wl, const wl_mbo_sub_cmd_t *cmd,
+	char **argv);
+typedef void (help_handler_t) (void);
+struct wl_mbo_sub_cmd {
+	char *name;
+	uint8 version;
+	uint16 cmd_id;
+	uint16 type;
+	subcmd_handler_t *hndler;
+	help_handler_t *help;
+};
+
+static cmd_func_t wl_mbo_main;
+
+static cmd_t wl_mbo_cmds[] = {
+	{ "mbo", wl_mbo_main, WLC_GET_VAR, WLC_SET_VAR,
+	"Please follow usage shown above\n"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+/* command handlers */
+static subcmd_handler_t wl_mbo_sub_cmd_add_chan_pref;
+static subcmd_handler_t wl_mbo_sub_cmd_del_chan_pref;
+static subcmd_handler_t wl_mbo_sub_cmd_list_chan_pref;
+static subcmd_handler_t wl_mbo_sub_cmd_cell_data_cap;
+static subcmd_handler_t wl_mbo_sub_cmd_dump_counters;
+static subcmd_handler_t wl_mbo_sub_cmd_clear_counters;
+static subcmd_handler_t wl_mbo_sub_cmd_force_assoc;
+static subcmd_handler_t wl_mbo_sub_cmd_bsstrans_reject;
+
+/* help handlers */
+static help_handler_t wl_mbo_add_chan_pref_help_fn;
+static help_handler_t wl_mbo_del_chan_pref_help_fn;
+static help_handler_t wl_mbo_list_chan_pref_help_fn;
+static help_handler_t wl_mbo_cell_data_cap_help_fn;
+static help_handler_t wl_mbo_counters_help_fn;
+static help_handler_t wl_mbo_clear_counters_help_fn;
+static help_handler_t wl_mbo_force_assoc_help_fn;
+static help_handler_t wl_mbo_bsstrans_reject_help_fn;
+
+#define WL_MBO_CMD_ALL 0
+static const wl_mbo_sub_cmd_t mbo_subcmd_lists[] = {
+	{ "add_chan_pref", 0x1, WL_MBO_CMD_ADD_CHAN_PREF,
+	IOVT_BUFFER, wl_mbo_sub_cmd_add_chan_pref,
+	wl_mbo_add_chan_pref_help_fn
+	},
+	{ "del_chan_pref", 0x1, WL_MBO_CMD_DEL_CHAN_PREF,
+	IOVT_BUFFER, wl_mbo_sub_cmd_del_chan_pref,
+	wl_mbo_del_chan_pref_help_fn
+	},
+	{ "list_chan_pref", 0x1, WL_MBO_CMD_LIST_CHAN_PREF,
+	IOVT_BUFFER, wl_mbo_sub_cmd_list_chan_pref,
+	wl_mbo_list_chan_pref_help_fn
+	},
+	{ "cell_data_cap", 0x1, WL_MBO_CMD_CELLULAR_DATA_CAP,
+	IOVT_BUFFER, wl_mbo_sub_cmd_cell_data_cap,
+	wl_mbo_cell_data_cap_help_fn
+	},
+	{ "counters", 0x1, WL_MBO_CMD_DUMP_COUNTERS,
+	IOVT_BUFFER, wl_mbo_sub_cmd_dump_counters,
+	wl_mbo_counters_help_fn
+	},
+	{ "clear_counters", 0x1, WL_MBO_CMD_CLEAR_COUNTERS,
+	IOVT_BUFFER, wl_mbo_sub_cmd_clear_counters,
+	wl_mbo_clear_counters_help_fn
+	},
+#ifdef WL_MBO_WFA_CERT
+	{ "force_assoc", 0x1, WL_MBO_CMD_FORCE_ASSOC,
+	IOVT_BUFFER, wl_mbo_sub_cmd_force_assoc,
+	wl_mbo_force_assoc_help_fn
+	},
+	{ "bsstrans_reject", 0x1, WL_MBO_CMD_BSSTRANS_REJECT,
+	IOVT_BUFFER, wl_mbo_sub_cmd_bsstrans_reject,
+	wl_mbo_bsstrans_reject_help_fn
+	},
+#endif /* WL_MBO_WFA_CERT */
+	{ NULL, 0, 0, 0, NULL, NULL }
+};
+
+void wluc_mbo_module_init(void)
+{
+	/* register mbo commands */
+	wl_module_cmds_register(wl_mbo_cmds);
+}
+
+static void
+wl_mbo_usage(int cmd_id)
+{
+	const wl_mbo_sub_cmd_t *subcmd = &mbo_subcmd_lists[0];
+
+	if (cmd_id > (WL_MBO_CMD_LAST - 1)) {
+		return;
+	}
+	while (subcmd->name) {
+		if (cmd_id == WL_MBO_CMD_ALL) {
+			subcmd->help();
+		} else if (cmd_id == subcmd->cmd_id) {
+			subcmd->help();
+		} else {
+			/* do nothing */
+		}
+		subcmd++;
+	}
+	return;
+}
+
+static int
+wl_mbo_main(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	const wl_mbo_sub_cmd_t *subcmd = &mbo_subcmd_lists[0];
+
+	UNUSED_PARAMETER(cmd);
+	/* skip to command name */
+	argv++;
+
+	if (*argv) {
+		if (!strcmp(*argv, "-h") || !strcmp(*argv, "help")) {
+			wl_mbo_usage(WL_MBO_CMD_ALL);
+			return BCME_OK;
+		}
+		while (subcmd->name) {
+			if (strcmp(subcmd->name, *argv) == 0) {
+				if (subcmd->hndler) {
+					ret = subcmd->hndler(wl, subcmd, ++argv);
+					return ret;
+				}
+			}
+			subcmd++;
+		}
+	} else {
+		wl_mbo_usage(WL_MBO_CMD_ALL);
+		return BCME_USAGE_ERROR;
+	}
+
+	return ret;
+}
+
+static int
+wl_mbo_sub_cmd_add_chan_pref(void *wl, const wl_mbo_sub_cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	bcm_iov_buf_t *iov_buf = NULL;
+	uint8 *pxtlv = NULL;
+	uint16 buflen = 0, buflen_start = 0;
+	char *param = NULL, *val_p = NULL;
+	uint16 iovlen = 0;
+	bool opclass_set = FALSE, chan_set = FALSE, reason_set = FALSE, pref_set = FALSE;
+
+	/* only set */
+	if (*argv == NULL) {
+		wl_mbo_usage(WL_MBO_CMD_ADD_CHAN_PREF);
+		return BCME_USAGE_ERROR;
+	} else {
+		iov_buf = (bcm_iov_buf_t *)calloc(1, WLC_IOCTL_MEDLEN);
+		if (iov_buf == NULL) {
+			return BCME_NOMEM;
+		}
+		/* fill header */
+		iov_buf->version = WL_MBO_IOV_VERSION;
+		iov_buf->id = cmd->cmd_id;
+
+		pxtlv = (uint8 *)&iov_buf->data[0];
+		buflen = buflen_start = WLC_IOCTL_MEDLEN - sizeof(bcm_iov_buf_t);
+
+		/* parse and pack config parameters */
+		while ((param = *argv++)) {
+			val_p = *argv++;
+			if (!val_p || *val_p == '-') {
+				fprintf(stderr, "%s: No value following %s\n", __FUNCTION__, param);
+				wl_mbo_usage(WL_MBO_CMD_ADD_CHAN_PREF);
+				ret = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			if (strcmp(param, "-o") == 0) {
+				uint8 opclass = strtoul(val_p, NULL, 0);
+				/* TBD: validation */
+				opclass_set = TRUE;
+				ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_OPCLASS,
+						sizeof(opclass), &opclass, BCM_XTLV_OPTION_ALIGN32);
+				if (ret != BCME_OK) {
+					goto fail;
+				}
+			} else if (strcmp(param, "-c") == 0) {
+				uint8 chan = strtoul(val_p, NULL, 0);
+				/* TBD: validation */
+				chan_set = TRUE;
+				ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_CHAN,
+						sizeof(chan), &chan, BCM_XTLV_OPTION_ALIGN32);
+				if (ret != BCME_OK) {
+					goto fail;
+				}
+			} else if (strcmp(param, "-p") == 0) {
+				uint8 pref = strtoul(val_p, NULL, 0);
+				if ((pref != MBO_STA_NON_OPERABLE_BAND_CHAN) &&
+					(pref != MBO_STA_NON_PREFERRED_BAND_CHAN) &&
+					(pref != MBO_STA_PREFERRED_BAND_CHAN)) {
+					fprintf(stderr, "Wrong preference value %u\n", pref);
+					ret = BCME_BADOPTION;
+					goto fail;
+				}
+				pref_set = TRUE;
+				ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_PREFERENCE,
+						sizeof(pref), &pref, BCM_XTLV_OPTION_ALIGN32);
+				if (ret != BCME_OK) {
+					goto fail;
+				}
+			} else if (strcmp(param, "-r") == 0) {
+				uint8 rc = strtoul(val_p, NULL, 0);
+				reason_set = TRUE;
+				ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_REASON_CODE,
+						sizeof(rc), &rc, BCM_XTLV_OPTION_ALIGN32);
+				if (ret != BCME_OK) {
+					goto fail;
+				}
+			} else {
+				fprintf(stderr, "Unknown param %s\n", param);
+			}
+		}
+		if (opclass_set && chan_set && pref_set && reason_set) {
+			iov_buf->len = buflen_start - buflen;
+			iovlen = sizeof(bcm_iov_buf_t) + iov_buf->len;
+			ret = wlu_var_setbuf(wl, "mbo", (void *)iov_buf, iovlen);
+		} else {
+			wl_mbo_usage(WL_MBO_CMD_ADD_CHAN_PREF);
+			ret = BCME_USAGE_ERROR;
+		}
+	}
+fail:
+	if (iov_buf) {
+		free(iov_buf);
+	}
+	return ret;
+}
+
+static void
+wl_mbo_add_chan_pref_help_fn(void)
+{
+	printf("wl mbo add_chan_pref -o <op_class> -c <chan> -p <pref val> -r <reason_code>\n");
+	printf("\top class: operating class defined by IEEE\n");
+	printf("\tchan: valid channel number\n");
+	printf("\tpref val: preference value [<0/1/255>]\n");
+	printf("\t\t 0 = non operable band/chan\n");
+	printf("\t\t 1 = non preferred band/chan\n");
+	printf("\t\t 255 = preferred band/chan\n");
+	printf("\treason code: [<0-3>]\n");
+}
+
+static int
+wl_mbo_sub_cmd_del_chan_pref(void *wl, const wl_mbo_sub_cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	bcm_iov_buf_t *iov_buf = NULL;
+	uint8 *pxtlv = NULL;
+	uint16 buflen = 0, buflen_start = 0;
+	char *param = NULL, *val_p = NULL;
+	uint16 iovlen = 0;
+	bool opclass_set = FALSE, chan_set = FALSE;
+
+	/* only set */
+	if (*argv == NULL) {
+		wl_mbo_usage(WL_MBO_CMD_DEL_CHAN_PREF);
+		return BCME_USAGE_ERROR;
+	} else {
+		iov_buf = (bcm_iov_buf_t *)calloc(1, WLC_IOCTL_MEDLEN);
+		if (iov_buf == NULL) {
+			return BCME_NOMEM;
+		}
+		/* fill header */
+		iov_buf->version = WL_MBO_IOV_VERSION;
+		iov_buf->id = cmd->cmd_id;
+
+		pxtlv = (uint8 *)&iov_buf->data[0];
+		buflen = buflen_start = WLC_IOCTL_MEDLEN - sizeof(bcm_iov_buf_t);
+
+		/* parse and pack config parameters */
+		while ((param = *argv++)) {
+			val_p = *argv++;
+			if (!val_p || *val_p == '-') {
+				fprintf(stderr, "%s: No value following %s\n", __FUNCTION__, param);
+				wl_mbo_usage(WL_MBO_CMD_DEL_CHAN_PREF);
+				ret = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			if (strcmp(param, "-o") == 0) {
+				uint8 opclass = strtoul(val_p, NULL, 0);
+				opclass_set = TRUE;
+				ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_OPCLASS,
+						sizeof(opclass), &opclass, BCM_XTLV_OPTION_ALIGN32);
+				if (ret != BCME_OK) {
+					goto fail;
+				}
+			} else if (strcmp(param, "-c") == 0) {
+				uint8 chan = strtoul(val_p, NULL, 0);
+				chan_set = TRUE;
+				ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_CHAN,
+						sizeof(chan), &chan, BCM_XTLV_OPTION_ALIGN32);
+				if (ret != BCME_OK) {
+					goto fail;
+				}
+			} else {
+				fprintf(stderr, "Unknown param %s\n", param);
+			}
+		}
+		if (opclass_set && chan_set) {
+			iov_buf->len = buflen_start - buflen;
+			iovlen = sizeof(bcm_iov_buf_t) + iov_buf->len;
+			ret = wlu_var_setbuf(wl, "mbo", (void *)iov_buf, iovlen);
+		} else {
+			wl_mbo_usage(WL_MBO_CMD_DEL_CHAN_PREF);
+			ret = BCME_USAGE_ERROR;
+		}
+	}
+fail:
+	if (iov_buf) {
+		free(iov_buf);
+	}
+	return ret;
+}
+
+static void
+wl_mbo_del_chan_pref_help_fn(void)
+{
+	printf("wl mbo del_chan_pref -o <op_class> -c <chan>\n");
+	printf("\top class: operating class defined by IEEE\n");
+	printf("\tchan: valid channel number\n");
+}
+
+static int
+wl_mbo_process_iov_resp_buf(void *iov_resp, uint16 cmd_id, bcm_xtlv_unpack_cbfn_t cbfn)
+{
+	int ret = BCME_OK;
+	uint16 version;
+
+	/* Check for version */
+	version = dtoh16(*(uint16 *)iov_resp);
+	if (version != WL_MBO_IOV_VERSION) {
+		ret = BCME_UNSUPPORTED;
+	}
+	bcm_iov_buf_t *p_resp = (bcm_iov_buf_t *)iov_resp;
+	if (p_resp->id == cmd_id && cbfn != NULL) {
+		ret = bcm_unpack_xtlv_buf((void *)p_resp, (uint8 *)p_resp->data, p_resp->len,
+			BCM_XTLV_OPTION_ALIGN32, cbfn);
+	}
+	return ret;
+}
+
+static int
+wl_mbo_get_iov_resp(void *wl, const wl_mbo_sub_cmd_t *cmd, bcm_xtlv_unpack_cbfn_t cbfn)
+{
+	int ret = BCME_OK;
+	bcm_iov_buf_t *iov_buf = NULL;
+	uint8 *iov_resp = NULL;
+
+	UNUSED_PARAMETER(wl);
+	iov_buf = (bcm_iov_buf_t *)calloc(1, WLC_IOCTL_SMLEN);
+	if (iov_buf == NULL) {
+		ret = BCME_NOMEM;
+		goto fail;
+	}
+	iov_resp = (uint8 *)calloc(1, WLC_IOCTL_MAXLEN);
+	if (iov_resp == NULL) {
+		ret = BCME_NOMEM;
+		goto fail;
+	}
+	/* fill header */
+	iov_buf->version = WL_MBO_IOV_VERSION;
+	iov_buf->id = cmd->cmd_id;
+
+	ret = wlu_iovar_getbuf(wl, "mbo", iov_buf, WLC_IOCTL_SMLEN, iov_resp, WLC_IOCTL_MAXLEN);
+	if ((ret == BCME_OK) && (iov_resp != NULL)) {
+		wl_mbo_process_iov_resp_buf(iov_resp, cmd->cmd_id, cbfn);
+	}
+fail:
+	if (iov_buf) {
+		free(iov_buf);
+	}
+	if (iov_resp) {
+		free(iov_resp);
+	}
+	return ret;
+}
+
+static int
+wl_mbo_list_chan_pref_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
+{
+	UNUSED_PARAMETER(ctx);
+	UNUSED_PARAMETER(len);
+	if (data == NULL) {
+		printf("%s: Bad argument !!\n", __FUNCTION__);
+		return BCME_BADARG;
+	}
+	switch (type) {
+		case WL_MBO_XTLV_OPCLASS:
+			printf("Opclass: %u\t", *data);
+			break;
+		case WL_MBO_XTLV_CHAN:
+			printf("Chan: %u\t", *data);
+			break;
+		case WL_MBO_XTLV_PREFERENCE:
+			printf("Preference: %u\t", *data);
+			break;
+		case WL_MBO_XTLV_REASON_CODE:
+			printf("Reason Code: %u\n", *data);
+			break;
+		default:
+			printf("%s: Unknown tlv %u\n", __FUNCTION__, type);
+	}
+	return BCME_OK;
+}
+
+static int
+wl_mbo_sub_cmd_list_chan_pref(void *wl, const wl_mbo_sub_cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	/* only get */
+	if (*argv == NULL) {
+		ret = wl_mbo_get_iov_resp(wl, cmd, wl_mbo_list_chan_pref_cbfn);
+	} else {
+		wl_mbo_usage(WL_MBO_CMD_LIST_CHAN_PREF);
+		return BCME_USAGE_ERROR;
+	}
+	return ret;
+}
+
+static void
+wl_mbo_list_chan_pref_help_fn(void)
+{
+	printf("wl mbo list_chan_pref\n");
+}
+
+static int
+wl_mbo_cell_data_cap_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
+{
+	UNUSED_PARAMETER(ctx);
+	UNUSED_PARAMETER(len);
+	if (data == NULL) {
+		printf("%s: Bad argument !!\n", __FUNCTION__);
+		return BCME_BADARG;
+	}
+	switch (type) {
+		case WL_MBO_XTLV_CELL_DATA_CAP:
+			if (*data == 0) {
+				printf("Cellular data capability: value not set\n");
+			} else {
+				printf("Cellular data capability: %0x\n", *data);
+			}
+			break;
+		default:
+			printf("%s: Unknown tlv %u\n", __FUNCTION__, type);
+	}
+	return BCME_OK;
+}
+
+static int
+wl_mbo_sub_cmd_cell_data_cap(void *wl, const wl_mbo_sub_cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	bcm_iov_buf_t *iov_buf = NULL;
+	uint8 *pxtlv = NULL;
+	uint16 buflen = 0, buflen_start = 0;
+	char *param = NULL, *val_p = NULL;
+	uint16 iovlen = 0;
+
+	/* get */
+	if (*argv == NULL) {
+		ret = wl_mbo_get_iov_resp(wl, cmd, wl_mbo_cell_data_cap_cbfn);
+	} else {
+		iov_buf = (bcm_iov_buf_t *)calloc(1, WLC_IOCTL_MEDLEN);
+		if (iov_buf == NULL) {
+			ret = BCME_NOMEM;
+			goto fail;
+		}
+		/* fill header */
+		iov_buf->version = WL_MBO_IOV_VERSION;
+		iov_buf->id = cmd->cmd_id;
+
+		pxtlv = (uint8 *)&iov_buf->data[0];
+		param = *argv++;
+		if (strcmp(param, "-c") == 0) {
+			val_p = *argv;
+			if (val_p == NULL || *val_p == '-') {
+				wl_mbo_usage(WL_MBO_CMD_CELLULAR_DATA_CAP);
+				ret = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			uint8 cell_data_cap = strtoul(val_p, NULL, 0);
+			if (cell_data_cap < MBO_CELL_DATA_CONN_AVAILABLE ||
+				cell_data_cap > MBO_CELL_DATA_CONN_NOT_CAPABLE) {
+				fprintf(stderr, "wrong value %u\n", cell_data_cap);
+				ret = BCME_BADARG;
+				goto fail;
+			}
+			buflen = buflen_start = WLC_IOCTL_MEDLEN - sizeof(bcm_iov_buf_t);
+			ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_CELL_DATA_CAP,
+				sizeof(cell_data_cap), &cell_data_cap, BCM_XTLV_OPTION_ALIGN32);
+			if (ret != BCME_OK) {
+				goto fail;
+			}
+		} else {
+			fprintf(stderr, "wrong parameter %s\n", param);
+			wl_mbo_usage(WL_MBO_CMD_CELLULAR_DATA_CAP);
+			ret = BCME_USAGE_ERROR;
+			goto fail;
+		}
+		iov_buf->len = buflen_start - buflen;
+		iovlen = sizeof(bcm_iov_buf_t) + iov_buf->len;
+		ret = wlu_var_setbuf(wl, "mbo", (void *)iov_buf, iovlen);
+	}
+fail:
+	if (iov_buf) {
+		free(iov_buf);
+	}
+	return ret;
+}
+
+static void
+wl_mbo_cell_data_cap_help_fn(void)
+{
+	printf("wl mbo cell_data_cap -c <capability>\n");
+	printf("\tcapability: cellular connection capability <1/2/3>\n");
+	printf("\t\t 1 = Cellular data connection available\n");
+	printf("\t\t 2 = Cellular data connection not available\n");
+	printf("\t\t 3 = Cellular data connection not capable\n");
+}
+
+static int
+wl_mbo_dump_counters_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
+{
+	UNUSED_PARAMETER(ctx);
+	UNUSED_PARAMETER(len);
+	if (data == NULL) {
+		printf("%s: Bad argument !!\n", __FUNCTION__);
+		return BCME_BADARG;
+	}
+	switch (type) {
+		case WL_MBO_XTLV_COUNTERS:
+			{
+				wl_mbo_counters_t *cntr = (wl_mbo_counters_t *)data;
+				printf("BTM req::\n");
+				printf("\trcvd:%u disassoc:%u termination:%u\n",
+					cntr->trans_req_rcvd, cntr->trans_req_disassoc,
+					cntr->trans_req_bss_term);
+				printf("Transition Reason::\n");
+				printf("\tunspecified:%u frame loss:%u traffic delay:%u "
+					"low bandwidth:%u\n",
+					cntr->trans_resn_unspec, cntr->trans_resn_frm_loss,
+					cntr->trans_resn_traffic_delay, cntr->trans_resn_insuff_bw);
+				printf("\tload balance:%u low rssi:%u excss retransmission:%u\n",
+					cntr->trans_resn_load_bal, cntr->trans_resn_low_rssi,
+					cntr->trans_resn_xcess_retransmn);
+				printf("\tGray zone:%u premium AP switch:%u\n",
+					cntr->trans_resn_gray_zone, cntr->trans_resn_prem_ap_sw);
+				printf("Num of transition rejection:%u\n", cntr->trans_rejn_sent);
+				printf("Transition rejection reason::\n");
+				printf("\texcess frame loss:%u traffic delay:%u low QoS:%u\n",
+					cntr->trans_rejn_insuffic_qos_cap,
+					cntr->trans_rejn_xcess_frm_loss,
+					cntr->trans_rejn_xcess_traffic_delay);
+				printf("\tlow RSSI:%u: high interference:%u service unavail:%u\n",
+					cntr->trans_rejn_low_rssi,
+					cntr->trans_rejn_high_interference,
+					cntr->trans_rejn_service_unavail);
+				printf("Beacon req_rcvd:%u\n", cntr->bcn_req_rcvd);
+				printf("Beacon rep sent:%u\n", cntr->bcn_rep_sent);
+				printf("NULL beacon rep sent:%u\n", cntr->null_bcn_rep_sent);
+				printf("Switch wlan to cell:%u\n", cntr->wifi_to_cell);
+			}
+			break;
+		default:
+			printf("%s: Unknown tlv %u\n", __FUNCTION__, type);
+	}
+	return BCME_OK;
+}
+
+static int
+wl_mbo_sub_cmd_dump_counters(void *wl, const wl_mbo_sub_cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	/* only get */
+	if (*argv == NULL) {
+		ret = wl_mbo_get_iov_resp(wl, cmd, wl_mbo_dump_counters_cbfn);
+	} else {
+		wl_mbo_usage(WL_MBO_CMD_DUMP_COUNTERS);
+		return BCME_USAGE_ERROR;
+	}
+	return ret;
+}
+
+static void
+wl_mbo_counters_help_fn(void)
+{
+	printf("wl mbo counters\n");
+}
+
+static int
+wl_mbo_sub_cmd_clear_counters(void *wl, const wl_mbo_sub_cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	bcm_iov_buf_t *iov_buf = NULL;
+	uint16 iovlen = 0;
+	/* only set */
+	if (*argv == NULL) {
+		iov_buf = (bcm_iov_buf_t *)calloc(1, WLC_IOCTL_MEDLEN);
+		if (iov_buf == NULL) {
+			ret = BCME_NOMEM;
+			goto fail;
+		}
+		/* fill header */
+		iov_buf->version = WL_MBO_IOV_VERSION;
+		iov_buf->id = cmd->cmd_id;
+		iov_buf->len = 0;
+		iovlen = sizeof(bcm_iov_buf_t);
+		ret = wlu_var_setbuf(wl, "mbo", (void *)iov_buf, iovlen);
+	} else {
+		wl_mbo_usage(WL_MBO_CMD_CLEAR_COUNTERS);
+		return BCME_USAGE_ERROR;
+	}
+fail:
+	if (iov_buf) {
+		free(iov_buf);
+	}
+	return ret;
+}
+
+static void
+wl_mbo_clear_counters_help_fn(void)
+{
+	printf("wl mbo clear_counters\n");
+}
+
+#ifdef WL_MBO_WFA_CERT
+static int
+wl_mbo_force_assoc_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
+{
+	UNUSED_PARAMETER(ctx);
+	UNUSED_PARAMETER(len);
+	if (data == NULL) {
+		printf("%s: Bad argument !!\n", __FUNCTION__);
+		return BCME_BADARG;
+	}
+	switch (type) {
+		case WL_MBO_XTLV_ENABLE:
+			printf("Force association: %s\n", (*data == 0) ? "disabled" : "enabled");
+			break;
+		default:
+			printf("%s: Unknown tlv %u\n", __FUNCTION__, type);
+	}
+	return BCME_OK;
+}
+
+static int
+wl_mbo_sub_cmd_force_assoc(void *wl, const wl_mbo_sub_cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	bcm_iov_buf_t *iov_buf = NULL;
+	uint8 *pxtlv = NULL;
+	uint16 buflen = 0, buflen_start = 0;
+	char *param = NULL, *val_p = NULL;
+	uint16 iovlen = 0;
+
+	/* get */
+	if (*argv == NULL) {
+		ret = wl_mbo_get_iov_resp(wl, cmd, wl_mbo_force_assoc_cbfn);
+	} else {
+		iov_buf = (bcm_iov_buf_t *)calloc(1, WLC_IOCTL_MEDLEN);
+		if (iov_buf == NULL) {
+			ret = BCME_NOMEM;
+			goto fail;
+		}
+		/* fill header */
+		iov_buf->version = WL_MBO_IOV_VERSION;
+		iov_buf->id = cmd->cmd_id;
+
+		pxtlv = (uint8 *)&iov_buf->data[0];
+		param = *argv++;
+		if (strcmp(param, "-e") == 0) {
+			val_p = *argv;
+			if (val_p == NULL || *val_p == '-') {
+				wl_mbo_usage(WL_MBO_CMD_FORCE_ASSOC);
+				ret = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			uint8 force = strtoul(val_p, NULL, 0);
+			if ((force != 0) && (force != 1)) {
+				fprintf(stderr, "wrong value %u\n", force);
+				ret = BCME_BADARG;
+				goto fail;
+			}
+			buflen = buflen_start = WLC_IOCTL_MEDLEN - sizeof(bcm_iov_buf_t);
+			ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_ENABLE,
+				sizeof(force), &force, BCM_XTLV_OPTION_ALIGN32);
+			if (ret != BCME_OK) {
+				goto fail;
+			}
+		} else {
+			fprintf(stderr, "wrong parameter %s\n", param);
+			wl_mbo_usage(WL_MBO_CMD_FORCE_ASSOC);
+			ret = BCME_USAGE_ERROR;
+			goto fail;
+		}
+		iov_buf->len = buflen_start - buflen;
+		iovlen = sizeof(bcm_iov_buf_t) + iov_buf->len;
+		ret = wlu_var_setbuf(wl, "mbo", (void *)iov_buf, iovlen);
+	}
+fail:
+	if (iov_buf) {
+		free(iov_buf);
+	}
+	return ret;
+}
+
+static void
+wl_mbo_force_assoc_help_fn(void)
+{
+	printf("wl mbo force_assoc -e <value>\n");
+	printf("\tvalue: Enable/disable assoc attempt even if "
+		"association disallowed by AP <1/0>\n");
+	printf("\t\t 1 = Enable force association attempt when "
+		"AP is not accepting new connection\n");
+	printf("\t\t 0 = disable force association attempt\n");
+}
+
+static int
+wl_mbo_bsstrans_reject_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
+{
+	UNUSED_PARAMETER(ctx);
+	UNUSED_PARAMETER(len);
+	if (data == NULL) {
+		printf("%s: Bad argument !!\n", __FUNCTION__);
+		return BCME_BADARG;
+	}
+	switch (type) {
+		case WL_MBO_XTLV_ENABLE:
+			printf("Bss Transition Reject: %s\n",
+				(*data == 0) ? "disabled" : "enabled");
+			break;
+		case WL_MBO_XTLV_REASON_CODE:
+			printf("Reason Code: %u\n", *data);
+			break;
+		default:
+			printf("%s: Unknown tlv %u\n", __FUNCTION__, type);
+	}
+	return BCME_OK;
+}
+
+static int
+wl_mbo_sub_cmd_bsstrans_reject(void *wl, const wl_mbo_sub_cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	bcm_iov_buf_t *iov_buf = NULL;
+	uint8 *pxtlv = NULL;
+	uint16 buflen = 0, buflen_start = 0;
+	char *param = NULL, *val_p = NULL;
+	uint16 iovlen = 0;
+	bool reason_set = FALSE;
+	uint8 enable = 0;
+
+	/* get */
+	if (*argv == NULL) {
+		ret = wl_mbo_get_iov_resp(wl, cmd, wl_mbo_bsstrans_reject_cbfn);
+	} else {
+		iov_buf = (bcm_iov_buf_t *)calloc(1, WLC_IOCTL_MEDLEN);
+		if (iov_buf == NULL) {
+			return BCME_NOMEM;
+		}
+		/* fill header */
+		iov_buf->version = WL_MBO_IOV_VERSION;
+		iov_buf->id = cmd->cmd_id;
+
+		pxtlv = (uint8 *)&iov_buf->data[0];
+		buflen = buflen_start = WLC_IOCTL_MEDLEN - sizeof(bcm_iov_buf_t);
+
+		/* parse and pack config parameters */
+		while ((param = *argv++)) {
+			val_p = *argv++;
+			if (!val_p || *val_p == '-') {
+				fprintf(stderr, "%s: wrong usage %s\n", __FUNCTION__, param);
+				wl_mbo_usage(WL_MBO_CMD_BSSTRANS_REJECT);
+				ret = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			if (strcmp(param, "-e") == 0) {
+				enable = strtoul(val_p, NULL, 0);
+				if ((enable != 0) && (enable != 1)) {
+					fprintf(stderr, "wrong value %u\n", enable);
+					ret = BCME_BADARG;
+					goto fail;
+				}
+				ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_ENABLE,
+						sizeof(enable), &enable, BCM_XTLV_OPTION_ALIGN32);
+				if (ret != BCME_OK) {
+					goto fail;
+				}
+			} else if (strcmp(param, "-r") == 0) {
+				uint8 reason = strtoul(val_p, NULL, 0);
+				if (reason > MBO_TRANS_REJ_REASON_SERVICE_UNAVAIL) {
+					fprintf(stderr, "wrong reason value %u\n", reason);
+					ret = BCME_BADARG;
+					goto fail;
+				}
+				reason_set = TRUE;
+				ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_MBO_XTLV_REASON_CODE,
+						sizeof(reason), &reason, BCM_XTLV_OPTION_ALIGN32);
+				if (ret != BCME_OK) {
+					goto fail;
+				}
+			} else {
+				fprintf(stderr, "Unknown param %s\n", param);
+			}
+		}
+		if ((enable && reason_set) || (!enable)) {
+			iov_buf->len = buflen_start - buflen;
+			iovlen = sizeof(bcm_iov_buf_t) + iov_buf->len;
+			ret = wlu_var_setbuf(wl, "mbo", (void *)iov_buf, iovlen);
+		} else {
+			wl_mbo_usage(WL_MBO_CMD_BSSTRANS_REJECT);
+			ret = BCME_USAGE_ERROR;
+		}
+	}
+fail:
+	if (iov_buf) {
+		free(iov_buf);
+	}
+	return ret;
+}
+
+static void
+wl_mbo_bsstrans_reject_help_fn(void)
+{
+	printf("wl mbo bsstrans_reject -e <value> -r <reason>\n");
+	printf("\tvalue: Enable/Disable bsstrans rejection <1/0>\n");
+	printf("\t\t 1 = Enable bsstrans rejection\n");
+	printf("\t\t 0 = Disable bsstrans rejection\n");
+	printf("\treason: reason code for rejection <0-6>\n");
+	printf("\t\t 0 = Unspecified reason\n");
+	printf("\t\t 1 = Excessive frame loss expected on transition\n");
+	printf("\t\t 2 = Excessive delay for current traffic stream on transition\n");
+	printf("\t\t 3 = Insufficient QoS capacity expected on transition\n");
+	printf("\t\t 4 = Low RSSI observed on suggested BSS\n");
+	printf("\t\t 5 = High interference observed on suggested BSS\n");
+	printf("\t\t 6 = Service unavailability on suggested BSS\n");
+}
+#endif /* WL_MBO_WFA_CERT */
diff --git a/wl/src/wl/exe/wluc_mfp.c b/wl/src/wl/exe/wluc_mfp.c
new file mode 100644
index 0000000..d62bf9f
--- /dev/null
+++ b/wl/src/wl/exe/wluc_mfp.c
@@ -0,0 +1,345 @@
+/*
+ * wl mfp command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_mfp.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static int wl_mfp_config(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_sha256(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_sa_query(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_disassoc(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_deauth(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_assoc(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_auth(void *wl, cmd_t *cmd, char **argv);
+static int wl_mfp_reassoc(void *wl, cmd_t *cmd, char **argv);
+
+static cmd_t wl_mfp_cmds[] = {
+	{ "mfp_config", wl_mfp_config, -1, WLC_SET_VAR,
+	"Config PMF capability\n"
+	"\tusage: wl mfp 0/disable, 1/capable, 2/requred" },
+	{ "mfp_sha256", wl_mfp_sha256, WLC_GET_VAR, WLC_SET_VAR,
+	"Config SHA256 capability\n"
+	"\tusage: wl sha256 0/disable, 1/enable" },
+	{ "mfp_sa_query", wl_mfp_sa_query, -1, WLC_SET_VAR,
+	"Send a sa query req/resp to a peer\n"
+	"\tusage: wl mfp_sa_query flag action id" },
+	{ "mfp_disassoc", wl_mfp_disassoc, WLC_GET_VAR, WLC_SET_VAR,
+	"send bogus disassoc\n"
+	"\tUsage: wl mfp_disassoc"},
+	{ "mfp_deauth", wl_mfp_deauth, WLC_GET_VAR, WLC_SET_VAR,
+	"send bogus deauth\n"
+	"\tUsage: wl mfp_dedauth"},
+	{ "mfp_assoc", wl_mfp_assoc, WLC_GET_VAR, WLC_SET_VAR,
+	"send assoc\n"
+	"\tUsage: wl mfp_assoc"},
+	{ "mfp_auth", wl_mfp_auth, WLC_GET_VAR, WLC_SET_VAR,
+	"send auth\n"
+	"\tUsage: wl mfp_auth"},
+	{ "mfp_reassoc", wl_mfp_reassoc, WLC_GET_VAR, WLC_SET_VAR,
+	"send reassoc\n"
+	"\tUsage: wl mfp_reassoc"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_mfp_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register mfp commands */
+	wl_module_cmds_register(wl_mfp_cmds);
+}
+
+static int
+wl_mfp_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = 0;
+	int flag = 0;
+	const char *cmdname = "mfp";
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)buf = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, buf, 256);
+
+	return (err);
+
+}
+
+static int
+wl_mfp_sha256(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = 0;
+	int flag = 0;
+	const char *cmdname = "mfp_sha256";
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)buf = flag;
+		err = wlu_iovar_set(wl, cmdname, buf, 256);
+	} else {
+		/* get */
+		err = wlu_iovar_getint(wl, cmdname, &flag);
+		if (err == BCME_OK)
+			printf("%d\n", flag);
+	}
+
+	return (err);
+
+}
+
+static int
+wl_mfp_sa_query(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_sa_query_t * query;
+	int argc;
+	int err = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if ((query = (wl_sa_query_t *) malloc(sizeof(wl_sa_query_t))) == NULL) {
+		printf("unable to allocate frame \n");
+		return BCME_NOMEM;
+	}
+	memset(query, 0, sizeof(wl_sa_query_t));
+
+	/* add the flag */
+	if (argc > 1 && argv[1]) {
+		query->flag = htod32(atoi(argv[1]));
+	}
+
+	/* add the action */
+	if (argc > 2 && argv[2]) {
+		query->action = htod32(atoi(argv[2]));
+	}
+
+	/* add the id */
+	if (argc > 3 && argv[3]) {
+		query->id = htod32(atoi(argv[3]));
+	}
+
+	err = wlu_var_setbuf(wl, "mfp_sa_query", query, sizeof(wl_sa_query_t));
+
+	free(query);
+
+	return (err);
+
+}
+
+static int
+wl_mfp_disassoc(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "mfp_disassoc";
+	int argc;
+	int	flag;
+	char varbuf[256];
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+	memset(varbuf, 0, 256);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* add the action */
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)varbuf = flag;
+	}
+	if (argc > 2 && argv[2]) {
+		flag = htod32(atoi(argv[2]));
+		*(int *)(varbuf + sizeof(flag)) = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, varbuf, 256);
+
+	return err;
+}
+
+static int
+wl_mfp_deauth(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "mfp_deauth";
+	int argc;
+	int	flag;
+	char varbuf[256];
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(varbuf, 0, 256);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* add the action */
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)varbuf = flag;
+	}
+	if (argc > 2 && argv[2]) {
+		flag = htod32(atoi(argv[2]));
+		*(int *)(varbuf + sizeof(flag)) = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, varbuf, 256);
+
+	return err;
+}
+
+static int
+wl_mfp_assoc(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "mfp_assoc";
+	int argc;
+	int	flag;
+	char varbuf[256];
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+	memset(varbuf, 0, 256);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* add the action */
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)varbuf = flag;
+	}
+	if (argc > 2 && argv[2]) {
+		flag = htod32(atoi(argv[2]));
+		*(int *)(varbuf + sizeof(int)) = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, varbuf, 256);
+
+	return err;
+}
+
+static int
+wl_mfp_auth(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "mfp_auth";
+	int argc;
+	int	flag;
+	char varbuf[256];
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+	memset(varbuf, 0, 256);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* add the action */
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)varbuf = flag;
+	}
+	if (argc > 2 && argv[2]) {
+		flag = htod32(atoi(argv[2]));
+		*(int *)(varbuf + sizeof(int)) = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, varbuf, 256);
+
+	return err;
+}
+
+static int
+wl_mfp_reassoc(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname = "mfp_reassoc";
+	int argc;
+	int	flag;
+	char varbuf[256];
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+	memset(varbuf, 0, 256);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* add the action */
+	if (argc > 1 && argv[1]) {
+		flag = htod32(atoi(argv[1]));
+		*(int *)varbuf = flag;
+	}
+	if (argc > 2 && argv[2]) {
+		flag = htod32(atoi(argv[2]));
+		*(int *)(varbuf + sizeof(int)) = flag;
+	}
+
+	err = wlu_iovar_set(wl, cmdname, varbuf, 256);
+
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_msch.c b/wl/src/wl/exe/wluc_msch.c
new file mode 100644
index 0000000..244b2e2
--- /dev/null
+++ b/wl/src/wl/exe/wluc_msch.c
@@ -0,0 +1,2539 @@
+/*
+ * wl msch command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlu_msch.c 502986 2014-09-16 23:06:58Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifdef WIN32
+#define bzero(b, len)	memset((b), 0, (len))
+#endif
+
+#ifdef LINUX
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* LINUX */
+
+#include <miniopt.h>
+#include <sys/stat.h>
+#include <trxhdr.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef WIN32
+#include <fcntl.h>
+#endif /* WIN32 */
+
+#include <event_log.h>
+
+#if defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION >= 0x00020000)
+extern int wlu_efi_stat(char *filename, struct stat *filest);
+extern long wlu_efi_ftell(void *fp);
+extern int wlu_efi_fseek(void *fp, long offset, int whence);
+extern size_t wlu_efi_fwrite(void *buf, size_t size, size_t nmemb, void *fp);
+extern size_t wlu_efi_fread(void *buf, size_t size, size_t nmemb, void *fp);
+extern void wlu_efi_fclose(void *fp);
+extern void * wlu_efi_fopen(char *filename, char *mode);
+
+#define fopen(filename, mode)		(FILE *)wlu_efi_fopen(filename, mode)
+#define fread(buf, size, nmemb, fp)	wlu_efi_fread(buf, size, nmemb, fp)
+#define fwrite(buf, size, nmemb, fp)	wlu_efi_fwrite(buf, size, nmemb, fp)
+#define fseek(fp, offset, origin)	wlu_efi_fseek(fp, offset, origin)
+#define ftell(fp)			wlu_efi_ftell(fp)
+#define stat(fname, filest)		wlu_efi_stat(fname, (struct stat *)(filest))
+#define fclose(fp)			wlu_efi_fclose(fp)
+#ifdef stderr
+#undef stderr
+#define stderr stdout
+#endif
+#endif /* defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION >= 0x00020000) */
+
+#if defined(linux)
+static cmd_func_t wl_msch_event_check;
+#endif   /* linux */
+static cmd_func_t wl_msch_request;
+static cmd_func_t wl_msch_collect;
+static cmd_func_t wl_msch_dump;
+static cmd_func_t wl_msch_profiler;
+
+static char *mschbufp = NULL, *mschdata = NULL;
+static FILE *mschfp = NULL;
+
+#define MSCH_COLLECT_USAGE \
+	"{enable|disable} [+/-register] [+/-callback] [+/-profiler] " \
+	"[+/-error] [+/-debug] [+/-info] [+/-trace]\n" \
+	"\tenable: alloc memory to save profiler data\n" \
+	"\tdisable: stop monitor, and free memory\n" \
+	"\t+/-register: save or skip register data\n" \
+	"\t+/-callback: save or skip register data\n" \
+	"\t+/-profiler: save or skip profiler data\n" \
+	"\t+/-error: save or skip error messages\n" \
+	"\t+/-debug: save or skip debug messages\n" \
+	"\t+/-info: save or skip infomation messages\n" \
+	"\t+/-trace: save or skip trace messages\n"
+
+#define MSCH_FMTFILE_USAGE \
+	"-D copydir -F \"logstrs_path=xxxx st_str_file_path=xxxx " \
+	"map_file_path=xxxx rom_st_str_file_path=xxxx rom_map_file_path=xxxx\"\n"
+
+static cmd_t wl_msch_cmds[] = {
+	{ "msch_req", wl_msch_request, WLC_GET_VAR, WLC_SET_VAR,
+	"register multiple channel scheduler \n"
+	"\tUsage: msch_req <id> -w wlc_index -c \"channel_list\" -f flags -t type [params] "
+	"-p priority -s start_time -d duration -i interval"
+	"\t-w W, --wlc_index=W\tset wlc index\n"
+	"\t-c L, --channels=L\tcomma or space separated list of channels to scheduler\n"
+	"\t-f F, --flags=F\tset flags, 1 for contiguous cahhhel scheduler\n"
+	"\t-t T, --type=T\tset scheduler type: fix, sf, df dur-flex, bf params\n\n"
+	"\t-p P, --priority=P\tpriority for the scheduler\n"
+	"\t-s S, --start-time=S\tstart time(ms) for the scheduler\n"
+	"\t-d D, --duration=D\tduration(ms) for the scheduler\n"
+	"\t-i I, --interval=I\tinterval(ms) for the scheduler\n"},
+
+	{ "msch_collect", wl_msch_collect, WLC_GET_VAR, WLC_SET_VAR,
+	"control multiple channel scheduler profiler saving data\n"
+	"\tUsage: msch_collect " MSCH_COLLECT_USAGE},
+
+	{ "msch_dump", wl_msch_dump, WLC_GET_VAR, WLC_SET_VAR,
+	"dump multiple channel scheduler profiler data\n"
+	"\tUsage: msch_dump [filename] " MSCH_FMTFILE_USAGE},
+
+	{ "msch_profiler", wl_msch_profiler, WLC_GET_VAR, WLC_SET_VAR,
+	"dump multiple channel scheduler profiler data\n"
+	"\tUsage: msch_profiler [uploadfilename] [filename] " MSCH_FMTFILE_USAGE},
+
+	{ "msch_event", wl_msch_collect, WLC_GET_VAR, WLC_SET_VAR,
+	"control multiple channel scheduler profiler event data\n"
+	"\tUsage: msch_event " MSCH_COLLECT_USAGE},
+
+	{ "msch_event_log", wl_msch_collect, WLC_GET_VAR, WLC_SET_VAR,
+	"control multiple channel scheduler profiler event Log data\n"
+	"\tUsage: msch_event_log " MSCH_COLLECT_USAGE},
+
+#if defined(linux)
+	{ "msch_event_check", wl_msch_event_check, -1, -1,
+	"Listen and print Multiple channel scheduler events\n"
+	"\tmsch_event_check syntax is: msch_event_check ifname [filename]"
+	"[+/-register] [+/-callback] [+/-profiler] "
+	"[+/-error] [+/-debug] [+/-info] [+/-trace] " MSCH_FMTFILE_USAGE},
+#endif   /* linux */
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+/* module initialization */
+void
+wluc_msch_module_init(void)
+{
+	/* get the global buf */
+	if (WLC_IOCTL_MAXLEN >= 2 * WL_MSCH_PROFILER_BUFFER_SIZE) {
+		mschdata = wl_get_buf();
+	} else {
+		mschdata = (char *)malloc(2 * WL_MSCH_PROFILER_BUFFER_SIZE);
+		if (!mschdata)
+			return;
+	}
+	mschbufp = (char *)&mschdata[WL_MSCH_PROFILER_BUFFER_SIZE];
+
+	/* register proxd commands */
+	wl_module_cmds_register(wl_msch_cmds);
+}
+
+static int
+wl_parse_msch_chanspec_list(char *list_str, chanspec_t *chanspec_list, int chanspec_num)
+{
+	int num = 0;
+	chanspec_t chanspec;
+	char *next, str[8];
+	size_t len;
+
+	if ((next = list_str) == NULL)
+		return BCME_ERROR;
+
+	while ((len = strcspn(next, " ,")) > 0) {
+		if (len >= sizeof(str)) {
+			fprintf(stderr, "string \"%s\" before ',' or ' ' is too long\n", next);
+			return BCME_ERROR;
+		}
+		strncpy(str, next, len);
+		str[len] = 0;
+		chanspec = wf_chspec_aton(str);
+		if (chanspec == 0) {
+			fprintf(stderr, "could not parse chanspec starting at "
+			        "\"%s\" in list:\n%s\n", str, list_str);
+			return BCME_ERROR;
+		}
+		if (num == chanspec_num) {
+			fprintf(stderr, "too many chanspecs (more than %d) in chanspec list:\n%s\n",
+				chanspec_num, list_str);
+			return BCME_ERROR;
+		}
+		chanspec_list[num++] = htodchanspec(chanspec);
+		next += len;
+		next += strspn(next, " ,");
+	}
+
+	return num;
+}
+
+static int
+wl_parse_msch_bf_param(char *param_str, uint32 *param)
+{
+	int num;
+	uint32 val;
+	char* str;
+	char* endptr = NULL;
+
+	if (param_str == NULL)
+		return BCME_ERROR;
+
+	str = param_str;
+	num = 0;
+	while (*str != '\0') {
+		val = (uint32)strtol(str, &endptr, 0);
+		if (endptr == str) {
+			fprintf(stderr,
+				"could not parse bf param starting at"
+				" substring \"%s\" in list:\n%s\n",
+				str, param_str);
+			return -1;
+		}
+		str = endptr + strspn(endptr, " ,");
+
+		if (num >= 4) {
+			fprintf(stderr, "too many bf param (more than 6) in param str:\n%s\n",
+				param_str);
+			return BCME_ERROR;
+		}
+
+		param[num++] = htod32(val);
+	}
+
+	return num;
+}
+
+static int
+wl_msch_request(void *wl, cmd_t *cmd, char **argv)
+{
+	int params_size = sizeof(msch_register_params_t);
+	msch_register_params_t *params;
+	uint32 val = 0;
+	uint16 val16;
+	char key[64];
+	int keylen;
+	char *p, *eq, *valstr, *endptr = NULL;
+	char opt;
+	bool good_int;
+	int err = BCME_OK;
+	int i;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	params = (msch_register_params_t*)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for msch register params\n",
+			params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	/* skip the command name */
+	argv++;
+
+	params->id = 0;
+
+	while ((p = *argv) != NULL) {
+		argv++;
+		memset(key, 0, sizeof(key));
+		opt = '\0';
+		valstr = NULL;
+		good_int = FALSE;
+
+		if (!strncmp(p, "--", 2)) {
+			eq = strchr(p, '=');
+			if (eq == NULL) {
+				fprintf(stderr,
+				"wl_msch_request: missing \" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			keylen = eq - (p + 2);
+			if (keylen > 63)
+				keylen = 63;
+			memcpy(key, p + 2, keylen);
+
+			valstr = eq + 1;
+			if (*valstr == '\0') {
+				fprintf(stderr, "wl_msch_request: missing value after "
+					"\" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		else if (!strncmp(p, "-", 1)) {
+			opt = p[1];
+			if (strlen(p) > 2) {
+				fprintf(stderr, "wl_msch_request: only single char options, "
+					"error on param \"%s\"\n", p);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (*argv == NULL) {
+				fprintf(stderr,
+				"wl_msch_request: missing value parameter after \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			valstr = *argv;
+			argv++;
+		} else {
+			val = (uint32)strtol(p, &endptr, 0);
+			if (*endptr == '\0') {
+				/* not all the value string was parsed by strtol */
+				good_int = TRUE;
+			}
+			if (!good_int) {
+				fprintf(stderr,
+				"wl_msch_request: parameter error \"%s\"\n", p);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			val16 = (uint16)val;
+			params->id = htod16(val16);
+			continue;
+		}
+
+		/* parse valstr as int just in case */
+		val = (uint32)strtol(valstr, &endptr, 0);
+		if (*endptr == '\0') {
+			/* not all the value string was parsed by strtol */
+			good_int = TRUE;
+		}
+
+		if (opt == 'h' || !strcmp(key, "help")) {
+			printf("%s", cmd->help);
+			goto exit;
+		} else if (opt == 'w' || !strcmp(key, "wlc_index")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an wlc_index\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			val16 = (uint16)val;
+			params->wlc_index = htod16(val16);
+		} else if (opt == 'c' || !strcmp(key, "channels")) {
+			i = wl_parse_msch_chanspec_list(valstr,
+				(chanspec_t *)params->chanspec_list, WL_MSCH_NUMCHANNELS);
+			if (i == BCME_ERROR) {
+				fprintf(stderr, "error parsing channel list arg\n");
+				err = BCME_BADARG;
+				goto exit;
+			}
+			val = (uint32)i;
+			params->chanspec_cnt = htod32(val);
+		} else if (opt == 'n' || !strcmp(key, "id")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an register id\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			val16 = (uint16)val;
+			params->id = htod16(val16);
+		} else if (opt == 'f' || !strcmp(key, "flags")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an flages\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			val16 = (uint16)val;
+			params->flags = htod16(val16);
+		} else if (opt == 't' || !strcmp(key, "type")) {
+			if (!strcmp(valstr, "f") || !strncmp(valstr, "fix", 3)) {
+				params->req_type = (uint32)WL_MSCH_RT_BOTH_FIXED;
+			} else if (!strcmp(valstr, "sf") || !strcmp(valstr, "start-flex")) {
+				params->req_type = (uint32)WL_MSCH_RT_START_FLEX;
+			} else if (!strcmp(valstr, "df") || !strcmp(valstr, "dur-flex")) {
+				if (*argv == NULL) {
+					fprintf(stderr,
+					"wl_msch_request: missing param of dur-flex\n");
+					err = BCME_USAGE_ERROR;
+					goto exit;
+				}
+				valstr = *argv;
+				argv++;
+
+				val = (uint32)strtol(valstr, &endptr, 0);
+				if (*endptr != '\0') {
+					fprintf(stderr,
+					"could not parse \"%s\" as dur-flex value\n", valstr);
+					err = BCME_USAGE_ERROR;
+					goto exit;
+				}
+
+				params->req_type = (uint32)WL_MSCH_RT_DUR_FLEX;
+				params->dur_flex = htod32(val);
+			} else if (!strcmp(valstr, "bf") || !strcmp(valstr, "both-flex")) {
+				if (*argv == NULL) {
+					fprintf(stderr,
+					"wl_msch_request: missing param of both-flex\n");
+					err = BCME_USAGE_ERROR;
+					goto exit;
+				}
+				valstr = *argv;
+				argv++;
+
+				if (wl_parse_msch_bf_param(valstr, &params->min_dur) != 4) {
+					fprintf(stderr, "error parsing both flex params\n");
+					err = BCME_BADARG;
+					goto exit;
+				}
+				params->req_type = (uint32)WL_MSCH_RT_BOTH_FLEX;
+			} else {
+				fprintf(stderr,
+				"error type param \"%s\"\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+
+			params->req_type = htod32(params->req_type);
+		} else if (opt == 'p' || !strcmp(key, "priority")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as priority\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			val16 = (uint16)val;
+			params->priority = htod16(val16);
+		} else if (opt == 's' || !strcmp(key, "start-time")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as start time\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->start_time = htod32(val);
+		} else if (opt == 'd' || !strcmp(key, "duration")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as duration\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->duration = htod32(val);
+		} else if (opt == 'i' || !strcmp(key, "interval")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as interval\n",
+					valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->interval = htod32(val);
+		} else {
+			fprintf(stderr,
+			"wl_msch_request: error option param \"%s\"\n", p);
+			err = BCME_BADARG;
+			goto exit;
+		}
+	}
+
+	err = wlu_var_setbuf(wl, cmd->name, params, params_size);
+exit:
+	free(params);
+	return err;
+}
+
+static int
+wl_msch_collect(void *wl, cmd_t *cmd, char **argv)
+{
+	bool eventcmd = (!strcmp(cmd->name, "msch_event"));
+	bool eventlogcmd = (!strcmp(cmd->name, "msch_event_log"));
+	bool collectcmd = (!strcmp(cmd->name, "msch_collect"));
+	char *p, *endptr;
+	int opt, v, val, err = BCME_OK;
+
+	UNUSED_PARAMETER(wl);
+
+	if ((err = wlu_iovar_getint(wl, cmd->name, &val)) < 0)
+		return err;
+
+	err = BCME_OK;
+	if (!*++argv) {
+		printf("MSCH %s: %sable {", (eventcmd? "Event" : (eventlogcmd? "EventLog" :
+			"Profile")), ((val & WL_MSCH_CMD_ENABLE_BIT)? "En" : "Dis"));
+		if (val & WL_MSCH_CMD_REGISTER_BIT)
+			printf("registe ");
+		if (val & WL_MSCH_CMD_CALLBACK_BIT)
+			printf("callbac ");
+		if (val & WL_MSCH_CMD_PROFILE_BIT)
+			printf("profiler ");
+		if (val & WL_MSCH_CMD_ERROR_BIT)
+			printf("error ");
+		if (val & WL_MSCH_CMD_DEBUG_BIT)
+			printf("debug ");
+		if (val & WL_MSCH_CMD_INFOM_BIT)
+			printf("info ");
+		if (val & WL_MSCH_CMD_TRACE_BIT)
+			printf("trace ");
+		printf("\x08}\n");
+		return err;
+	}
+
+	while ((p = *argv) != NULL) {
+		opt = 0;
+		if (p[0] == '+') {
+			opt = 1;
+			p++;
+		}
+		else if (p[0] == '-') {
+			opt = 2;
+			p++;
+		}
+
+		if (opt == 0) {
+			v = (uint32)strtol(p, &endptr, 0);
+			if (*endptr == '\0') {
+				if (v == 1)
+					val |= WL_MSCH_CMD_ENABLE_BIT;
+				else if (v == 0)
+					val &= ~WL_MSCH_CMD_ENABLE_BIT;
+				else {
+					err = BCME_EPERM;
+					break;
+				}
+			}
+			else if (!strcmp(p, "enable") || !strcmp(p, "start")) {
+				val |= WL_MSCH_CMD_ENABLE_BIT;
+			}
+			else if (!strcmp(p, "disable") || !strcmp(p, "stop"))
+				val &= ~WL_MSCH_CMD_ENABLE_BIT;
+			else if (collectcmd && !strcmp(p, "dump"))
+				return wl_msch_dump(wl, cmd, argv);
+			else {
+				err = BCME_EPERM;
+				break;
+			}
+		} else {
+			if (opt == 2 && (!strcmp(p, "-help") || !strcmp(p, "h"))) {
+				printf("%s", cmd->help);
+				return BCME_OK;
+			} else if (opt == 2 && (!strcmp(p, "all") || !strcmp(p, "a"))) {
+				val &= ~WL_MSCH_CMD_ALL_BITS;
+			} else if (!strcmp(p, "profiler") || !strcmp(p, "p")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_PROFILE_BIT;
+				else
+					val &= ~WL_MSCH_CMD_PROFILE_BIT;
+			}
+			else if (!strcmp(p, "callback") || !strcmp(p, "c")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_CALLBACK_BIT;
+				else
+					val &= ~WL_MSCH_CMD_CALLBACK_BIT;
+			}
+			else if (!strcmp(p, "register") || !strcmp(p, "r")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_REGISTER_BIT;
+				else
+					val &= ~WL_MSCH_CMD_REGISTER_BIT;
+			}
+			else if (!strcmp(p, "error") || !strcmp(p, "e")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_ERROR_BIT;
+				else
+					val &= ~WL_MSCH_CMD_ERROR_BIT;
+			}
+			else if (!strcmp(p, "debug") || !strcmp(p, "d")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_DEBUG_BIT;
+				else
+					val &= ~WL_MSCH_CMD_DEBUG_BIT;
+			}
+			else if (!strcmp(p, "info") || !strcmp(p, "i")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_INFOM_BIT;
+				else
+					val &= ~WL_MSCH_CMD_INFOM_BIT;
+			}
+			else if (!strcmp(p, "trace") || !strcmp(p, "t")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_TRACE_BIT;
+				else
+					val &= ~WL_MSCH_CMD_TRACE_BIT;
+			}
+			else if (collectcmd && opt == 2 && !strcmp(p, "s") && *++argv) {
+				p = *argv;
+				v = (uint32)strtol(p, &endptr, 0);
+				if (*endptr == '\0') {
+					val &= ~WL_MSCH_CMD_SIZE_MASK;
+					val |= (v << WL_MSCH_CMD_SIZE_SHIFT);
+				} else {
+					err = BCME_EPERM;
+					break;
+				}
+			}
+			else {
+				err = BCME_EPERM;
+				break;
+			}
+		}
+
+		argv++;
+	}
+
+	if (eventcmd && (val & WL_MSCH_CMD_ENABLE_BIT)) {
+		uint8 event_inds_mask[WL_EVENTING_MASK_LEN];
+		/*  read current mask state  */
+		if ((err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask,
+			WL_EVENTING_MASK_LEN))) {
+			fprintf(stderr, "couldn't read event_msgs\n");
+			goto exit;
+		}
+		event_inds_mask[WLC_E_MSCH / 8] |= (1 << (WLC_E_MSCH % 8));
+		if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask,
+			WL_EVENTING_MASK_LEN))) {
+			fprintf(stderr, "couldn't write event_msgs\n");
+			goto exit;
+		}
+	}
+
+	val &= ~WL_MSCH_CMD_VER_MASK;
+	val |= (WL_MSCH_PROFILER_VER << WL_MSCH_CMD_VER_SHIFT);
+	if (err == BCME_OK)
+		err = wlu_iovar_setint(wl, cmd->name, val);
+exit:
+	return err;
+}
+
+typedef struct {
+	int  num_fmts;
+	char **fmts;
+	char *raw_fmts;
+	char *raw_sstr;
+	uint32 fmts_size;
+	uint32 raw_fmts_size;
+	uint32 raw_sstr_size;
+	uint32 ramstart;
+	uint32 rodata_start;
+	uint32 rodata_end;
+	char *rom_raw_sstr;
+	uint32 rom_raw_sstr_size;
+	uint32 rom_ramstart;
+	uint32 rom_rodata_start;
+	uint32 rom_rodata_end;
+} wl_event_log_t;
+
+wl_event_log_t raw_event;
+
+#define BYTES_AHEAD_NUM		11	/* address in map file is before these many bytes */
+#define READ_NUM_BYTES		1000 /* read map file each time this No. of bytes */
+#define GO_BACK_FILE_POS_NUM_BYTES	100 /* set file pos back to cur pos */
+static char *ramstart_str = "text_start"; /* string in mapfile has addr ramstart */
+static char *rodata_start_str = "rodata_start"; /* string in mapfile has addr rodata start */
+static char *rodata_end_str = "rodata_end"; /* string in mapfile has addr rodata end */
+#define RAMSTART_BIT	0x01
+#define RDSTART_BIT		0x02
+#define RDEND_BIT		0x04
+#define ALL_MAP_VAL		(RAMSTART_BIT | RDSTART_BIT | RDEND_BIT)
+
+static char *logstrs_path = "/root/logstrs.bin";
+static char *st_str_file_path = "/root/rtecdc.bin";
+static char *map_file_path = "/root/rtecdc.map";
+static char *rom_st_str_file_path = "/root/roml.bin";
+static char *rom_map_file_path = "/root/roml.map";
+static char *ram_file_str = "rtecdc";
+static char *rom_file_str = "roml";
+
+static int
+wl_read_map(char *fname, uint32 *ramstart, uint32 *rodata_start, uint32 *rodata_end)
+{
+	FILE *filep = NULL;
+	char *raw_fmts =  NULL;
+	int read_size = READ_NUM_BYTES;
+	int keep_size = GO_BACK_FILE_POS_NUM_BYTES;
+	int error = 0;
+	char * cptr = NULL;
+	char c;
+	uint8 count = 0;
+
+	if (fname == NULL) {
+		fprintf(stderr, "%s: ERROR fname is NULL \n", __FUNCTION__);
+		return BCME_ERROR;
+	}
+
+	filep = fopen(fname, "rb");
+	if (!filep) {
+		perror(fname);
+		fprintf(stderr, "Cannot open file %s\n", fname);
+		return BCME_ERROR;
+	}
+
+	*ramstart = 0;
+	*rodata_start = 0;
+	*rodata_end = 0;
+
+	/* Allocate 1 byte more than read_size to terminate it with NULL */
+	raw_fmts = (char *)malloc(read_size + keep_size + 1);
+	if (raw_fmts == NULL) {
+		fprintf(stderr, "%s: Failed to allocate raw_fmts memory \n", __FUNCTION__);
+		goto fail;
+	}
+	memset(raw_fmts, ' ', GO_BACK_FILE_POS_NUM_BYTES);
+
+	/* read ram start, rodata_start and rodata_end values from map	file */
+	while (count != ALL_MAP_VAL)
+	{
+		error = fread(&raw_fmts[keep_size], 1, read_size, filep);
+		if (error < 0) {
+			fprintf(stderr, "%s: map file read failed err:%d \n", __FUNCTION__,
+				error);
+			goto fail;
+		}
+
+		/* End raw_fmts with NULL as strstr expects NULL terminated strings */
+		raw_fmts[read_size + keep_size] = '\0';
+
+		/* Get ramstart address */
+		if ((cptr = strstr(raw_fmts, ramstart_str))) {
+			cptr = cptr - BYTES_AHEAD_NUM;
+			sscanf(cptr, "%x %c text_start", ramstart, &c);
+			count |= RAMSTART_BIT;
+		}
+
+		/* Get ram rodata start address */
+		if ((cptr = strstr(raw_fmts, rodata_start_str))) {
+			cptr = cptr - BYTES_AHEAD_NUM;
+			sscanf(cptr, "%x %c rodata_start", rodata_start, &c);
+			count |= RDSTART_BIT;
+		}
+
+		/* Get ram rodata end address */
+		if ((cptr = strstr(raw_fmts, rodata_end_str))) {
+			cptr = cptr - BYTES_AHEAD_NUM;
+			sscanf(cptr, "%x %c rodata_end", rodata_end, &c);
+			count |= RDEND_BIT;
+		}
+
+		if (error < read_size) {
+			/*
+			 * since we reset file pos back to earlier pos by
+			 * GO_BACK_FILE_POS_NUM_BYTES bytes we won't reach EOF.
+			 * The reason for this is if string is spreaded across
+			 * bytes, the read function should not miss it.
+			 * So if ret value is less than read_size, reached EOF don't read further
+			 */
+			break;
+		}
+		/*
+		* go back to predefined NUM of bytes so that we won't miss
+		* the string and  addr even if it comes as splited in next read.
+		*/
+		memcpy(raw_fmts, &raw_fmts[read_size], keep_size);
+	}
+
+fail:
+	if (filep) {
+		fclose(filep);
+	}
+
+	if (raw_fmts) {
+		free(raw_fmts);
+	}
+
+	if (count != ALL_MAP_VAL) {
+		fprintf(stderr, "%s: readmap error 0X%x \n", __FUNCTION__, count);
+		return BCME_ERROR;
+	}
+	return BCME_OK;
+}
+
+static void
+wl_init_static_strs_array(char *str_file, char *map_file)
+{
+	FILE *filep = NULL;
+	char *raw_fmts =  NULL;
+	uint32 logstrs_size = 0;
+
+	int error = 0;
+	uint32 ramstart = 0;
+	uint32 rodata_start = 0;
+	uint32 rodata_end = 0;
+	uint32 logfilebase = 0;
+
+	error = wl_read_map(map_file, &ramstart, &rodata_start, &rodata_end);
+	if (error != BCME_OK) {
+		fprintf(stderr, "readmap Error!! \n");
+		/* don't do event log parsing in actual case */
+		if (strstr(str_file, ram_file_str) != NULL) {
+			raw_event.raw_sstr = NULL;
+		} else if (strstr(str_file, rom_file_str) != NULL) {
+			raw_event.rom_raw_sstr = NULL;
+		}
+		return;
+	}
+
+	if (str_file == NULL) {
+		fprintf(stderr, "%s: ERROR fname is NULL \n", __FUNCTION__);
+		return;
+	}
+
+	filep = fopen(str_file, "rb");
+	if (!filep) {
+		perror(str_file);
+		fprintf(stderr, "Cannot open file %s\n", str_file);
+		return;
+	}
+
+	/* Full file size is huge. Just read required part */
+	logstrs_size = rodata_end - rodata_start;
+
+	raw_fmts = (char *)malloc(logstrs_size);
+	if (raw_fmts == NULL) {
+		fprintf(stderr, "%s: Failed to allocate raw_fmts memory \n", __FUNCTION__);
+		goto fail;
+	}
+
+	logfilebase = rodata_start - ramstart;
+
+	error = fseek(filep, logfilebase, SEEK_SET);
+	if (error < 0) {
+		fprintf(stderr, "%s: %s llseek failed %d \n", __FUNCTION__, str_file, error);
+		goto fail;
+	}
+
+	error = fread(raw_fmts, 1, logstrs_size, filep);
+	if (error != (int)logstrs_size) {
+		fprintf(stderr, "%s: %s read failed %d \n", __FUNCTION__, str_file, error);
+		goto fail;
+	}
+
+	if (strstr(str_file, ram_file_str) != NULL) {
+		raw_event.raw_sstr = raw_fmts;
+		raw_event.raw_sstr_size = logstrs_size;
+		raw_event.ramstart = ramstart;
+		raw_event.rodata_start = rodata_start;
+		raw_event.rodata_end = rodata_end;
+	} else if (strstr(str_file, rom_file_str) != NULL) {
+		raw_event.rom_raw_sstr = raw_fmts;
+		raw_event.rom_raw_sstr_size = logstrs_size;
+		raw_event.rom_ramstart = ramstart;
+		raw_event.rom_rodata_start = rodata_start;
+		raw_event.rom_rodata_end = rodata_end;
+	}
+
+	fclose(filep);
+
+	free(raw_fmts);
+
+	return;
+
+fail:
+	if (raw_fmts) {
+		free(raw_fmts);
+	}
+
+	if (filep) {
+		fclose(filep);
+	}
+
+	if (strstr(str_file, ram_file_str) != NULL) {
+		raw_event.raw_sstr = NULL;
+	} else if (strstr(str_file, rom_file_str) != NULL) {
+		raw_event.rom_raw_sstr = NULL;
+	}
+
+	return;
+}
+
+static void
+wl_init_logstrs_array(char *logstrs_path)
+{
+	FILE *filep = NULL;
+	char *raw_fmts =  NULL;
+	int logstrs_size = 0;
+	int error = 0;
+	logstr_header_t *hdr = NULL;
+	uint32 *lognums = NULL;
+	char *logstrs = NULL;
+	int ram_index = 0;
+	char **fmts = NULL;
+	int num_fmts = 0;
+	int i = 0;
+
+	if (logstrs_path == NULL) {
+		fprintf(stderr, "%s: ERROR fname is NULL \n", __FUNCTION__);
+		return;
+	}
+
+	filep = fopen(logstrs_path, "rb");
+	if (!filep) {
+		perror(logstrs_path);
+		fprintf(stderr, "Cannot open file %s\n", logstrs_path);
+		return;
+	}
+
+	if (fseek(filep, 0, SEEK_END) < 0 ||
+	    (logstrs_size = ftell(filep)) < 0) {
+		fprintf(stderr, "%s: Could not determine size of %s \n", __FUNCTION__,
+			logstrs_path);
+		goto fail;
+	}
+
+	raw_fmts = (char *)malloc(logstrs_size);
+	if (raw_fmts == NULL) {
+		fprintf(stderr, "%s: Failed to allocate memory \n", __FUNCTION__);
+		goto fail;
+	}
+
+	fseek(filep, 0, SEEK_SET);
+	error = fread(raw_fmts, 1, logstrs_size, filep);
+	if (error != logstrs_size) {
+		fprintf(stderr, "%s: Failed to read file %s", __FUNCTION__, logstrs_path);
+		goto fail;
+	}
+
+	/* Remember header from the logstrs.bin file */
+	hdr = (logstr_header_t *) (raw_fmts + logstrs_size -
+			sizeof(logstr_header_t));
+
+	if (hdr->log_magic == LOGSTRS_MAGIC) {
+		/*
+		 * logstrs.bin start with header.
+		 */
+		num_fmts = hdr->rom_logstrs_offset / sizeof(uint32);
+		ram_index = (hdr->ram_lognums_offset -
+			hdr->rom_lognums_offset) / sizeof(uint32);
+		lognums = (uint32 *)&raw_fmts[hdr->rom_lognums_offset];
+		logstrs = (char *)&raw_fmts[hdr->rom_logstrs_offset];
+	} else {
+		/*
+		 * Legacy logstrs.bin format without header.
+		 */
+		num_fmts = *((uint32 *) (raw_fmts)) / sizeof(uint32);
+		if (num_fmts == 0) {
+			/* Legacy ROM/RAM logstrs.bin format:
+			 *  - ROM 'lognums' section
+			 *   - RAM 'lognums' section
+			 *   - ROM 'logstrs' section.
+			 *   - RAM 'logstrs' section.
+			 *
+			 * 'lognums' is an array of indexes for the strings in the
+			 * 'logstrs' section. The first uint32 is 0 (index of first
+			 * string in ROM 'logstrs' section).
+			 *
+			 * The 4324b5 is the only ROM that uses this legacy format. Use the
+			 * fixed number of ROM fmtnums to find the start of the RAM
+			 * 'lognums' section. Use the fixed first ROM string ("Con\n") to
+			 * find the ROM 'logstrs' section.
+			 */
+			#define NUM_4324B5_ROM_FMTS	186
+			#define FIRST_4324B5_ROM_LOGSTR "Con\n"
+			ram_index = NUM_4324B5_ROM_FMTS;
+			lognums = (uint32 *) raw_fmts;
+			num_fmts =	ram_index;
+			logstrs = (char *) &raw_fmts[num_fmts << 2];
+			while (strncmp(FIRST_4324B5_ROM_LOGSTR, logstrs, 4)) {
+				num_fmts++;
+				logstrs = (char *) &raw_fmts[num_fmts << 2];
+			}
+		} else {
+			/* Legacy RAM-only logstrs.bin format:
+			 *	  - RAM 'lognums' section
+			 *	  - RAM 'logstrs' section.
+			 *
+			 * 'lognums' is an array of indexes for the strings in the
+			 * 'logstrs' section. The first uint32 is an index to the
+			 * start of 'logstrs'. Therefore, if this index is divided
+			 * by 'sizeof(uint32)' it provides the number of logstr
+			 *	entries.
+			 */
+			ram_index = 0;
+			lognums = (uint32 *)raw_fmts;
+			logstrs = (char *)&raw_fmts[num_fmts << 2];
+		}
+	}
+	if (num_fmts)
+		fmts = (char **)malloc(num_fmts * sizeof(char *));
+	if (fmts == NULL) {
+		fprintf(stderr, "%s: Failed to allocate fmts memory\n", __FUNCTION__);
+		goto fail;
+	}
+
+	raw_event.fmts_size = num_fmts  * sizeof(char *);
+
+	for (i = 0; i < num_fmts; i++) {
+		/* ROM lognums index into logstrs using 'rom_logstrs_offset' as a base
+		 * (they are 0-indexed relative to 'rom_logstrs_offset').
+		 *
+		 * RAM lognums are already indexed to point to the correct RAM logstrs (they
+		 * are 0-indexed relative to the start of the logstrs.bin file).
+		 */
+		if (i == ram_index) {
+			logstrs = raw_fmts;
+		}
+		fmts[i] = &logstrs[lognums[i]];
+	}
+	raw_event.fmts = fmts;
+	raw_event.raw_fmts_size = logstrs_size;
+	raw_event.raw_fmts = raw_fmts;
+	raw_event.num_fmts = num_fmts;
+
+	fclose(filep);
+	return;
+
+fail:
+	if (raw_fmts) {
+		free(raw_fmts);
+	}
+
+	if (filep) {
+		fclose(filep);
+	}
+}
+
+static int wl_init_frm_array(char *dir, char *files)
+{
+	char *logstrs = NULL, *logstrs_d = NULL;
+	char *st_str_file = NULL, *st_str_file_d = NULL;
+	char *map_file = NULL, *map_file_d = NULL;
+	char *rom_st_str_file = NULL, *rom_st_str_file_d = NULL;
+	char *rom_map_file = NULL, *rom_map_file_d = NULL;
+	char *next, *str, *eq, *valstr;
+	size_t len;
+
+	if ((next = files)) {
+		while ((len = strcspn(next, " ,")) > 0) {
+			str = next;
+			next += len;
+			next += strspn(next, " ,");
+
+			str[len] = '\0';
+			eq = strchr(str, '=');
+			if (eq == NULL) {
+				fprintf(stderr, "wl_init_frm_array: missing \" = \" in file "
+					"param \"%s\"\n", str);
+				return BCME_USAGE_ERROR;
+			}
+			valstr = eq + 1;
+			if (*valstr == '\0') {
+				fprintf(stderr, "wl_init_frm_array: missing value after "
+					"\" = \" in file param \"%s\"\n", str);
+				return BCME_USAGE_ERROR;
+			}
+			*eq = '\0';
+
+			if (!strcmp(str, "logstrs_path"))
+				logstrs = valstr;
+			else if (!strcmp(str, "st_str_file_path"))
+				st_str_file = valstr;
+			else if (!strcmp(str, "map_file_path"))
+				map_file = valstr;
+			else if (!strcmp(str, "rom_st_str_file_path"))
+				rom_st_str_file = valstr;
+			else if (!strcmp(str, "rom_map_file_path"))
+				rom_map_file = valstr;
+			else {
+				fprintf(stderr, "wl_init_frm_array: error file %s\n", str);
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	if (dir) {
+		len = strlen(dir);
+		if (!logstrs) {
+			logstrs_d = (char *)malloc(len + 32);
+			logstrs = logstrs_d;
+			if (logstrs) {
+				strcpy(logstrs, dir);
+				strcat(logstrs, "/logstrs.bin");
+			}
+		}
+		if (!st_str_file) {
+			st_str_file_d = (char *)malloc(len + 32);
+			st_str_file = st_str_file_d;
+			if (st_str_file) {
+				strcpy(st_str_file, dir);
+				strcat(st_str_file, "/rtecdc.bin");
+			}
+		}
+		if (!map_file) {
+			map_file_d = (char *)malloc(len + 32);
+			map_file = map_file_d;
+			if (map_file) {
+				strcpy(map_file, dir);
+				strcat(map_file, "/rtecdc.map");
+			}
+		}
+		if (!rom_st_str_file) {
+			rom_st_str_file_d = (char *)malloc(len + 32);
+			rom_st_str_file = rom_st_str_file_d;
+			if (rom_st_str_file) {
+				strcpy(rom_st_str_file, dir);
+				strcat(rom_st_str_file, "/roml.bin");
+			}
+		}
+		if (!rom_map_file) {
+			rom_map_file_d = (char *)malloc(len + 32);
+			rom_map_file = rom_map_file_d;
+			if (rom_map_file) {
+				strcpy(rom_map_file, dir);
+				strcat(rom_map_file, "/roml.map");
+			}
+		}
+	}
+
+	if (!logstrs)
+		logstrs = logstrs_path;
+	if (!st_str_file)
+		st_str_file = st_str_file_path;
+	if (!map_file)
+		map_file = map_file_path;
+	if (!rom_st_str_file)
+		rom_st_str_file = rom_st_str_file_path;
+	if (!rom_map_file)
+		rom_map_file = rom_map_file_path;
+
+	wl_init_logstrs_array(logstrs);
+	wl_init_static_strs_array(st_str_file, map_file);
+	wl_init_static_strs_array(rom_st_str_file, rom_map_file);
+
+	if (dir) {
+		if (logstrs_d) {
+			free(logstrs_d);
+		}
+		if (st_str_file_d) {
+			free(st_str_file_d);
+		}
+		if (map_file_d) {
+			free(map_file_d);
+		}
+		if (rom_st_str_file_d) {
+			free(rom_st_str_file_d);
+		}
+		if (rom_map_file_d) {
+			free(rom_map_file_d);
+		}
+	}
+
+	return BCME_OK;
+}
+
+#define MSCH_EVENTS_PRINT(nbytes) \
+	do { \
+		printf("%s", mschbufp); \
+		if (mschfp) \
+			fwrite(mschbufp, 1, nbytes, mschfp); \
+	} while (0)
+
+#define MSCH_EVENTS_SPPRINT(space) \
+	do { \
+		if (space > 0) { \
+			int ii; \
+			for (ii = 0; ii < space; ii++) mschbufp[ii] = ' '; \
+			mschbufp[space] = '\0'; \
+			MSCH_EVENTS_PRINT(space); \
+		} \
+	} while (0)
+
+#define MSCH_EVENTS_PRINTF(fmt) \
+	do { \
+		int nbytes = snprintf(mschbufp, WL_MSCH_PROFILER_BUFFER_SIZE, fmt); \
+		MSCH_EVENTS_PRINT(nbytes); \
+	} while (0)
+
+#define MSCH_EVENTS_PRINTF1(fmt, a) \
+	do { \
+		int nbytes = snprintf(mschbufp, WL_MSCH_PROFILER_BUFFER_SIZE, fmt, \
+			(a)); \
+		MSCH_EVENTS_PRINT(nbytes); \
+	} while (0)
+
+#define MSCH_EVENTS_PRINTF2(fmt, a, b) \
+	do { \
+		int nbytes = snprintf(mschbufp, WL_MSCH_PROFILER_BUFFER_SIZE, fmt, \
+			(a), (b)); \
+		MSCH_EVENTS_PRINT(nbytes); \
+	} while (0)
+
+#define MSCH_EVENTS_PRINTF3(fmt, a, b, c) \
+	do { \
+		int nbytes = snprintf(mschbufp, WL_MSCH_PROFILER_BUFFER_SIZE, fmt, \
+			(a), (b), (c)); \
+		MSCH_EVENTS_PRINT(nbytes); \
+	} while (0)
+
+#define MSCH_EVENTS_PRINTF4(fmt, a, b, c, d) \
+	do { \
+		int nbytes = snprintf(mschbufp, WL_MSCH_PROFILER_BUFFER_SIZE, fmt, \
+			(a), (b), (c), (d)); \
+		MSCH_EVENTS_PRINT(nbytes); \
+	} while (0)
+
+#define MSCH_EVENTS_PRINTF5(fmt, a, b, c, d, e) \
+	do { \
+		int nbytes = snprintf(mschbufp, WL_MSCH_PROFILER_BUFFER_SIZE, fmt, \
+			(a), (b), (c), (d), (e)); \
+		MSCH_EVENTS_PRINT(nbytes); \
+	} while (0)
+
+#define MSCH_EVENTS_SPPRINTF(space, fmt) \
+	do { \
+		MSCH_EVENTS_SPPRINT(space); \
+		MSCH_EVENTS_PRINTF(fmt); \
+	} while (0)
+
+#define MSCH_EVENTS_SPPRINTF1(space, fmt, a) \
+	do { \
+		MSCH_EVENTS_SPPRINT(space); \
+		MSCH_EVENTS_PRINTF1(fmt, (a)); \
+	} while (0)
+
+#define MSCH_EVENTS_SPPRINTF2(space, fmt, a, b) \
+	do { \
+		MSCH_EVENTS_SPPRINT(space); \
+		MSCH_EVENTS_PRINTF2(fmt, (a), (b)); \
+	} while (0)
+
+#define MSCH_EVENTS_SPPRINTF3(space, fmt, a, b, c) \
+	do { \
+		MSCH_EVENTS_SPPRINT(space); \
+		MSCH_EVENTS_PRINTF3(fmt, (a), (b), (c)); \
+	} while (0)
+
+#define MSCH_EVENTS_SPPRINTF4(space, fmt, a, b, c, d) \
+	do { \
+		MSCH_EVENTS_SPPRINT(space); \
+		MSCH_EVENTS_PRINTF4(fmt, (a), (b), (c), (d)); \
+	} while (0)
+
+#define MSCH_EVENTS_SPPRINTF5(space, fmt, a, b, c, d, e) \
+	do { \
+		MSCH_EVENTS_SPPRINT(space); \
+		MSCH_EVENTS_PRINTF5(fmt, (a), (b), (c), (d), (e)); \
+	} while (0)
+
+static char *wl_msch_display_time(uint32 time_h, uint32 time_l)
+{
+	static char display_time[32];
+	uint64 t;
+	uint32 s, ss;
+
+	if (time_h == 0xffffffff && time_l == 0xffffffff) {
+		snprintf(display_time, 31, "-1");
+	} else {
+		t = ((uint64)(ntoh32(time_h)) << 32) | ntoh32(time_l);
+		s = (uint32)(t / 1000000);
+		ss = (uint32)(t % 1000000);
+		snprintf(display_time, 31, "%d.%06d", s, ss);
+	}
+	return display_time;
+}
+
+static void
+wl_msch_chanspec_list(int sp, char *data, uint16 ptr, uint16 chanspec_cnt)
+{
+	int i, cnt = (int)ntoh16(chanspec_cnt);
+	uint16 *chanspec_list = (uint16 *)(data + ntoh16(ptr));
+	char buf[CHANSPEC_STR_LEN];
+	chanspec_t c;
+
+	MSCH_EVENTS_SPPRINTF(sp, "<chanspec_list>:");
+	for (i = 0; i < cnt; i++) {
+		c = (chanspec_t)ntoh16(chanspec_list[i]);
+		MSCH_EVENTS_PRINTF1(" %s", wf_chspec_ntoa(c, buf));
+	}
+	MSCH_EVENTS_PRINTF("\n");
+}
+
+static void
+wl_msch_elem_list(int sp, char *title, char *data, uint16 ptr, uint16 list_cnt)
+{
+	int i, cnt = (int)ntoh16(list_cnt);
+	uint32 *list = (uint32 *)(data + ntoh16(ptr));
+
+	MSCH_EVENTS_SPPRINTF1(sp, "%s_list: ", title);
+	for (i = 0; i < cnt; i++) {
+		MSCH_EVENTS_PRINTF1("0x%08x->", ntoh32(list[i]));
+	}
+	MSCH_EVENTS_PRINTF("null\n");
+}
+
+static void
+wl_msch_req_param_profiler_data(int sp, int ver, char *data, uint16 ptr)
+{
+	int sn = sp + 4;
+	msch_req_param_profiler_event_data_t *p =
+		(msch_req_param_profiler_event_data_t *)(data + ntoh16(ptr));
+	uint32 type, flags;
+
+	UNUSED_PARAMETER(ver);
+
+	MSCH_EVENTS_SPPRINTF(sp, "<request parameters>\n");
+	MSCH_EVENTS_SPPRINTF(sn, "req_type: ");
+
+	type = p->req_type;
+	if (type < 4) {
+		char *req_type[] = {"fixed", "start-flexible", "duration-flexible",
+			"both-flexible"};
+		MSCH_EVENTS_PRINTF1("%s", req_type[type]);
+	}
+	else
+		MSCH_EVENTS_PRINTF1("unknown(%d)", type);
+
+	flags = ntoh16(p->flags);
+	if (flags & WL_MSCH_REQ_FLAGS_CHAN_CONTIGUOUS)
+		MSCH_EVENTS_PRINTF(", CHAN_CONTIGUOUS");
+	if (flags & WL_MSCH_REQ_FLAGS_MERGE_CONT_SLOTS)
+		MSCH_EVENTS_PRINTF(", MERGE_CONT_SLOTS");
+	if (flags & WL_MSCH_REQ_FLAGS_PREMTABLE)
+		MSCH_EVENTS_PRINTF(", PREMTABLE");
+	if (flags & WL_MSCH_REQ_FLAGS_PREMT_CURTS)
+		MSCH_EVENTS_PRINTF(", PREMT_CURTS");
+	if (flags & WL_MSCH_REQ_FLAGS_PREMT_IMMEDIATE)
+		MSCH_EVENTS_PRINTF(", PREMT_IMMEDIATE");
+	MSCH_EVENTS_PRINTF1(", priority: %d\n", p->priority);
+
+	MSCH_EVENTS_SPPRINTF3(sn, "start-time: %s, duration: %d(us), interval: %d(us)\n",
+		wl_msch_display_time(p->start_time_h, p->start_time_l),
+		ntoh32(p->duration), ntoh32(p->interval));
+
+	if (type == WL_MSCH_RT_DUR_FLEX)
+		MSCH_EVENTS_SPPRINTF1(sn, "dur_flex: %d(us)\n", ntoh32(p->flex.dur_flex));
+	else if (type == WL_MSCH_RT_BOTH_FLEX) {
+		MSCH_EVENTS_SPPRINTF2(sn, "min_dur: %d(us), max_away_dur: %d(us)\n",
+			ntoh32(p->flex.bf.min_dur), ntoh32(p->flex.bf.max_away_dur));
+
+		MSCH_EVENTS_SPPRINTF2(sn, "hi_prio_time: %s, hi_prio_interval: %d(us)\n",
+			wl_msch_display_time(p->flex.bf.hi_prio_time_h,
+			p->flex.bf.hi_prio_time_l),
+			ntoh32(p->flex.bf.hi_prio_interval));
+	}
+}
+
+static void
+wl_msch_timeslot_profiler_data(int sp, int ver, char *title, char *data, uint16 ptr, bool empty)
+{
+	int s, sn = sp + 4;
+	msch_timeslot_profiler_event_data_t *p =
+		(msch_timeslot_profiler_event_data_t *)(data + ntoh16(ptr));
+	char *state[] = {"NONE", "CHN_SW", "ONCHAN_FIRE", "OFF_CHN_PREP",
+		"OFF_CHN_DONE", "TS_COMPLETE"};
+
+	UNUSED_PARAMETER(ver);
+
+	MSCH_EVENTS_SPPRINTF1(sp, "<%s timeslot>: ", title);
+	if (empty) {
+		MSCH_EVENTS_PRINTF(" null\n");
+		return;
+	}
+	else
+		MSCH_EVENTS_PRINTF1("0x%08x\n", ntoh32(p->p_timeslot));
+
+	s = (int)(ntoh32(p->state));
+	if (s > 5) s = 0;
+
+	MSCH_EVENTS_SPPRINTF4(sn, "id: %d, state[%d]: %s, chan_ctxt: [0x%08x]\n",
+		ntoh32(p->timeslot_id), ntoh32(p->state), state[s], ntoh32(p->p_chan_ctxt));
+
+	MSCH_EVENTS_SPPRINTF1(sn, "fire_time: %s",
+		wl_msch_display_time(p->fire_time_h, p->fire_time_l));
+
+	MSCH_EVENTS_PRINTF1(", pre_start_time: %s",
+		wl_msch_display_time(p->pre_start_time_h, p->pre_start_time_l));
+
+	MSCH_EVENTS_PRINTF1(", end_time: %s",
+		wl_msch_display_time(p->end_time_h, p->end_time_l));
+
+	MSCH_EVENTS_PRINTF1(", sch_dur: %s\n",
+		wl_msch_display_time(p->sch_dur_h, p->sch_dur_l));
+}
+
+static void
+wl_msch_req_timing_profiler_data(int sp, int ver, char *title, char *data, uint16 ptr, bool empty)
+{
+	int sn = sp + 4;
+	msch_req_timing_profiler_event_data_t *p =
+		(msch_req_timing_profiler_event_data_t *)(data + ntoh16(ptr));
+	uint32 type;
+
+	UNUSED_PARAMETER(ver);
+
+	MSCH_EVENTS_SPPRINTF1(sp, "<%s req_timing>: ", title);
+	if (empty) {
+		MSCH_EVENTS_PRINTF(" null\n");
+		return;
+	}
+	else
+		MSCH_EVENTS_PRINTF3("0x%08x (prev 0x%08x, next 0x%08x)\n",
+			ntoh32(p->p_req_timing), ntoh32(p->p_prev), ntoh32(p->p_next));
+
+	MSCH_EVENTS_SPPRINTF(sn, "flags:");
+	type = ntoh16(p->flags);
+	if ((type & 0x7f) == 0)
+		MSCH_EVENTS_PRINTF(" NONE");
+	else {
+		if (type & WL_MSCH_RC_FLAGS_ONCHAN_FIRE)
+			MSCH_EVENTS_PRINTF(" ONCHAN_FIRE");
+		if (type & WL_MSCH_RC_FLAGS_START_FIRE_DONE)
+			MSCH_EVENTS_PRINTF(" START_FIRE");
+		if (type & WL_MSCH_RC_FLAGS_END_FIRE_DONE)
+			MSCH_EVENTS_PRINTF(" END_FIRE");
+		if (type & WL_MSCH_RC_FLAGS_ONFIRE_DONE)
+			MSCH_EVENTS_PRINTF(" ONFIRE_DONE");
+		if (type & WL_MSCH_RC_FLAGS_SPLIT_SLOT_START)
+			MSCH_EVENTS_PRINTF(" SPLIT_SLOT_START");
+		if (type & WL_MSCH_RC_FLAGS_SPLIT_SLOT_END)
+			MSCH_EVENTS_PRINTF(" SPLIT_SLOT_END");
+		if (type & WL_MSCH_RC_FLAGS_PRE_ONFIRE_DONE)
+			MSCH_EVENTS_PRINTF(" PRE_ONFIRE_DONE");
+	}
+	MSCH_EVENTS_PRINTF("\n");
+
+	MSCH_EVENTS_SPPRINTF1(sn, "pre_start_time: %s",
+		wl_msch_display_time(p->pre_start_time_h, p->pre_start_time_l));
+
+	MSCH_EVENTS_PRINTF1(", start_time: %s",
+		wl_msch_display_time(p->start_time_h, p->start_time_l));
+
+	MSCH_EVENTS_PRINTF1(", end_time: %s\n",
+		wl_msch_display_time(p->end_time_h, p->end_time_l));
+
+	if (p->p_timeslot && (p->timeslot_ptr == 0))
+		MSCH_EVENTS_SPPRINTF2(sn, "<%s timeslot>: 0x%08x\n", title, ntoh32(p->p_timeslot));
+	else
+		wl_msch_timeslot_profiler_data(sn, ver, title, data, p->timeslot_ptr,
+			(p->timeslot_ptr == 0));
+}
+
+static void
+wl_msch_chan_ctxt_profiler_data(int sp, int ver, char *data, uint16 ptr, bool empty)
+{
+	int sn = sp + 4;
+	msch_chan_ctxt_profiler_event_data_t *p =
+		(msch_chan_ctxt_profiler_event_data_t *)(data + ntoh16(ptr));
+	chanspec_t c;
+	char buf[CHANSPEC_STR_LEN];
+
+	UNUSED_PARAMETER(ver);
+
+	MSCH_EVENTS_SPPRINTF(sp, "<chan_ctxt>: ");
+	if (empty) {
+		MSCH_EVENTS_PRINTF(" null\n");
+		return;
+	}
+	else
+		MSCH_EVENTS_PRINTF3("0x%08x (prev 0x%08x, next 0x%08x)\n",
+			ntoh32(p->p_chan_ctxt), ntoh32(p->p_prev), ntoh32(p->p_next));
+
+	c = (chanspec_t)ntoh16(p->chanspec);
+	MSCH_EVENTS_SPPRINTF3(sn, "channel: %s, bf_sch_pending: %s, bf_skipped: %d\n",
+		wf_chspec_ntoa(c, buf), p->bf_sch_pending? "TRUE" : "FALSE",
+		ntoh32(p->bf_skipped_count));
+	MSCH_EVENTS_SPPRINTF2(sn, "bf_link: prev 0x%08x, next 0x%08x\n",
+		ntoh32(p->bf_link_prev), ntoh32(p->bf_link_next));
+
+	MSCH_EVENTS_SPPRINTF1(sn, "onchan_time: %s",
+		wl_msch_display_time(p->onchan_time_h, p->onchan_time_l));
+
+	MSCH_EVENTS_PRINTF1(", actual_onchan_dur: %s",
+		wl_msch_display_time(p->actual_onchan_dur_h, p->actual_onchan_dur_l));
+
+	MSCH_EVENTS_PRINTF1(", pend_onchan_dur: %s\n",
+		wl_msch_display_time(p->pend_onchan_dur_h, p->pend_onchan_dur_l));
+
+	wl_msch_elem_list(sn, "req_entity", data, p->req_entity_list_ptr, p->req_entity_list_cnt);
+	wl_msch_elem_list(sn, "bf_entity", data, p->bf_entity_list_ptr, p->bf_entity_list_cnt);
+}
+
+static void
+wl_msch_req_entity_profiler_data(int sp, int ver, char *data, uint16 ptr, bool empty)
+{
+	int sn = sp + 4;
+	msch_req_entity_profiler_event_data_t *p =
+		(msch_req_entity_profiler_event_data_t *)(data + ntoh16(ptr));
+	char buf[CHANSPEC_STR_LEN];
+	chanspec_t c;
+	uint32 flags;
+
+	MSCH_EVENTS_SPPRINTF(sp, "<req_entity>: ");
+	if (empty) {
+		MSCH_EVENTS_PRINTF(" null\n");
+		return;
+	}
+	else
+		MSCH_EVENTS_PRINTF3("0x%08x (prev 0x%08x, next 0x%08x)\n",
+			ntoh32(p->p_req_entity), ntoh32(p->req_hdl_link_prev),
+			ntoh32(p->req_hdl_link_next));
+
+	MSCH_EVENTS_SPPRINTF1(sn, "req_hdl: [0x%08x]\n", ntoh32(p->p_req_hdl));
+	MSCH_EVENTS_SPPRINTF2(sn, "chan_ctxt_link: prev 0x%08x, next 0x%08x\n",
+		ntoh32(p->chan_ctxt_link_prev), ntoh32(p->chan_ctxt_link_next));
+	MSCH_EVENTS_SPPRINTF2(sn, "rt_specific_link: prev 0x%08x, next 0x%08x\n",
+		ntoh32(p->rt_specific_link_prev), ntoh32(p->rt_specific_link_next));
+	MSCH_EVENTS_SPPRINTF2(sn, "start_fixed_link: prev 0x%08x, next 0x%08x\n",
+		ntoh32(p->start_fixed_link_prev), ntoh32(p->start_fixed_link_next));
+	MSCH_EVENTS_SPPRINTF2(sn, "both_flex_list: prev 0x%08x, next 0x%08x\n",
+		ntoh32(p->both_flex_list_prev), ntoh32(p->both_flex_list_next));
+
+	c = (chanspec_t)ntoh16(p->chanspec);
+	if (ver >= 2) {
+		MSCH_EVENTS_SPPRINTF4(sn, "channel: %s, onchan Id %d, current chan Id %d, "
+			"priority %d", wf_chspec_ntoa(c, buf), ntoh16(p->onchan_chn_idx),
+			ntoh16(p->cur_chn_idx), ntoh16(p->priority));
+		flags = ntoh32(p->flags);
+		if (flags & WL_MSCH_ENTITY_FLAG_MULTI_INSTANCE)
+			MSCH_EVENTS_PRINTF(" : MULTI_INSTANCE\n");
+		else
+			MSCH_EVENTS_PRINTF("\n");
+		MSCH_EVENTS_SPPRINTF1(sn, "actual_start_time: %s, ",
+			wl_msch_display_time(p->actual_start_time_h, p->actual_start_time_l));
+		MSCH_EVENTS_PRINTF1("curts_fire_time: %s, ",
+			wl_msch_display_time(p->curts_fire_time_h, p->curts_fire_time_l));
+	} else {
+		MSCH_EVENTS_SPPRINTF2(sn, "channel: %s, priority %d, ", wf_chspec_ntoa(c, buf),
+			ntoh16(p->priority));
+	}
+	MSCH_EVENTS_PRINTF1("bf_last_serv_time: %s\n",
+		wl_msch_display_time(p->bf_last_serv_time_h, p->bf_last_serv_time_l));
+
+	wl_msch_req_timing_profiler_data(sn, ver, "current", data, p->cur_slot_ptr,
+		(p->cur_slot_ptr == 0));
+	wl_msch_req_timing_profiler_data(sn, ver, "pending", data, p->pend_slot_ptr,
+		(p->pend_slot_ptr == 0));
+
+	if (p->p_chan_ctxt && (p->chan_ctxt_ptr == 0))
+		MSCH_EVENTS_SPPRINTF1(sn, "<chan_ctxt>: 0x%08x\n", ntoh32(p->p_chan_ctxt));
+	else
+		wl_msch_chan_ctxt_profiler_data(sn, ver, data, p->chan_ctxt_ptr,
+			(p->chan_ctxt_ptr == 0));
+}
+
+static void
+wl_msch_req_handle_profiler_data(int sp, int ver, char *data, uint16 ptr, bool empty)
+{
+	int sn = sp + 4;
+	msch_req_handle_profiler_event_data_t *p =
+		(msch_req_handle_profiler_event_data_t *)(data + ntoh16(ptr));
+	uint32 flags;
+
+	MSCH_EVENTS_SPPRINTF(sp, "<req_handle>: ");
+	if (empty) {
+		MSCH_EVENTS_PRINTF(" null\n");
+		return;
+	}
+	else
+		MSCH_EVENTS_PRINTF3("0x%08x (prev 0x%08x, next 0x%08x)\n",
+			ntoh32(p->p_req_handle), ntoh32(p->p_prev), ntoh32(p->p_next));
+
+	wl_msch_elem_list(sn, "req_entity", data, p->req_entity_list_ptr, p->req_entity_list_cnt);
+	MSCH_EVENTS_SPPRINTF2(sn, "cb_func: [0x%08x], cb_func: [0x%08x]",
+		ntoh32(p->cb_func), ntoh32(p->cb_ctxt));
+	if (ver < 2) {
+		MSCH_EVENTS_PRINTF1(", chan_cnt: %d", ntoh16(p->chan_cnt));
+	}
+	flags = ntoh32(p->flags);
+	if (flags & WL_MSCH_REQ_HDL_FLAGS_NEW_REQ)
+		MSCH_EVENTS_PRINTF(", NEW_REQ");
+	MSCH_EVENTS_PRINTF("\n");
+
+	wl_msch_req_param_profiler_data(sn, ver, data, p->req_param_ptr);
+
+	if (ver >= 2) {
+		MSCH_EVENTS_SPPRINTF1(sn, "req_time: %s\n",
+			wl_msch_display_time(p->req_time_h, p->req_time_l));
+		MSCH_EVENTS_SPPRINTF3(sn, "chan_cnt: %d, chan idx %d, last chan idx %d\n",
+			ntoh16(p->chan_cnt), ntoh16(p->chan_idx), ntoh16(p->last_chan_idx));
+		if (p->chanspec_list && p->chanspec_cnt) {
+			wl_msch_chanspec_list(sn, data, p->chanspec_list, p->chanspec_cnt);
+		}
+	}
+}
+
+static void
+wl_msch_profiler_profiler_data(int sp, int ver, char *data, uint16 ptr)
+{
+	msch_profiler_profiler_event_data_t *p =
+		(msch_profiler_profiler_event_data_t *)(data + ntoh16(ptr));
+	uint32 flags;
+
+	MSCH_EVENTS_SPPRINTF4(sp, "free list: req_hdl 0x%08x, req_entity 0x%08x,"
+		" chan_ctxt 0x%08x, chanspec 0x%08x\n",
+		ntoh32(p->free_req_hdl_list), ntoh32(p->free_req_entity_list),
+		ntoh32(p->free_chan_ctxt_list), ntoh32(p->free_chanspec_list));
+
+	MSCH_EVENTS_SPPRINTF5(sp, "alloc count: chanspec %d, req_entity %d, req_hdl %d, "
+		"chan_ctxt %d, timeslot %d\n",
+		ntoh16(p->msch_chanspec_alloc_cnt), ntoh16(p->msch_req_entity_alloc_cnt),
+		ntoh16(p->msch_req_hdl_alloc_cnt), ntoh16(p->msch_chan_ctxt_alloc_cnt),
+		ntoh16(p->msch_timeslot_alloc_cnt));
+
+	wl_msch_elem_list(sp, "req_hdl", data, p->msch_req_hdl_list_ptr,
+		p->msch_req_hdl_list_cnt);
+	wl_msch_elem_list(sp, "chan_ctxt", data, p->msch_chan_ctxt_list_ptr,
+		p->msch_chan_ctxt_list_cnt);
+	wl_msch_elem_list(sp, "req_timing", data, p->msch_req_timing_list_ptr,
+		p->msch_req_timing_list_cnt);
+	wl_msch_elem_list(sp, "start_fixed", data, p->msch_start_fixed_list_ptr,
+		p->msch_start_fixed_list_cnt);
+	wl_msch_elem_list(sp, "both_flex_req_entity", data,
+		p->msch_both_flex_req_entity_list_ptr,
+		p->msch_both_flex_req_entity_list_cnt);
+	wl_msch_elem_list(sp, "start_flex", data, p->msch_start_flex_list_ptr,
+		p->msch_start_flex_list_cnt);
+	wl_msch_elem_list(sp, "both_flex", data, p->msch_both_flex_list_ptr,
+		p->msch_both_flex_list_cnt);
+
+	if (p->p_cur_msch_timeslot && (p->cur_msch_timeslot_ptr == 0))
+		MSCH_EVENTS_SPPRINTF1(sp, "<cur_msch timeslot>: 0x%08x\n",
+			ntoh32(p->p_cur_msch_timeslot));
+	else
+		wl_msch_timeslot_profiler_data(sp, ver, "cur_msch", data,
+			p->cur_msch_timeslot_ptr, (p->cur_msch_timeslot_ptr == 0));
+
+	if (p->p_next_timeslot && (p->next_timeslot_ptr == 0))
+		MSCH_EVENTS_SPPRINTF1(sp, "<next timeslot>: 0x%08x\n", ntoh32(p->p_next_timeslot));
+	else
+		wl_msch_timeslot_profiler_data(sp, ver, "next", data,
+			p->next_timeslot_ptr, (p->next_timeslot_ptr == 0));
+
+	MSCH_EVENTS_SPPRINTF1(sp, "ts_id: %d, ", ntoh32(p->ts_id));
+	flags = ntoh32(p->flags);
+	if (flags & WL_MSCH_STATE_IN_TIEMR_CTXT)
+		MSCH_EVENTS_PRINTF("IN_TIEMR_CTXT, ");
+	if (flags & WL_MSCH_STATE_SCHD_PENDING)
+		MSCH_EVENTS_PRINTF("SCHD_PENDING, ");
+	MSCH_EVENTS_PRINTF2("slotskip_flags: %d, cur_armed_timeslot: 0x%08x\n",
+		(ver >= 2)? ntoh32(p->slotskip_flag) : 0, ntoh32(p->cur_armed_timeslot));
+	MSCH_EVENTS_SPPRINTF3(sp, "flex_list_cnt: %d, service_interval: %d, "
+		"max_lo_prio_interval: %d\n",
+		ntoh16(p->flex_list_cnt), ntoh32(p->service_interval),
+		ntoh32(p->max_lo_prio_interval));
+}
+
+#define MAX_NO_OF_ARG	10
+#define FMTSTR_SIZE	132
+#define ROMSTR_SIZE	200
+#define SIZE_LOC_STR	50
+
+static bool
+check_valid_string_format(char *curr_ptr)
+{
+	char *next_ptr;
+	if ((next_ptr = bcmstrstr(curr_ptr, "s")) != NULL) {
+		/* Default %s format */
+		if (curr_ptr == next_ptr) {
+			return TRUE;
+		}
+
+		/* Verify each charater between '%' and 's' is a valid number */
+		while (curr_ptr < next_ptr) {
+			if (bcm_isdigit(*curr_ptr) == FALSE) {
+				return FALSE;
+			}
+			curr_ptr++;
+		}
+
+		return TRUE;
+	} else {
+		return FALSE;
+	}
+}
+
+static void
+wl_msch_profiler_event_log_data(int ver, event_log_hdr_t *hdr, uint32 *data)
+{
+	uint16 count;
+	char fmtstr_loc_buf[ROMSTR_SIZE] = { 0 };
+	char (*str_buf)[SIZE_LOC_STR] = NULL;
+	char *str_tmpptr = NULL;
+	uint32 addr = 0;
+	typedef union {
+		uint32 val;
+		char * addr;
+	} u_arg;
+	u_arg arg[MAX_NO_OF_ARG] = {{0}};
+	char *c_ptr = NULL;
+	int nbytes;
+
+	UNUSED_PARAMETER(ver);
+
+	/* print the message out in a logprint	*/
+	if (!(((raw_event.raw_sstr) || (raw_event.rom_raw_sstr)) &&
+		raw_event.fmts) || hdr->fmt_num == 0xffff) {
+		MSCH_EVENTS_PRINTF2("0.0 EL: %x %x",
+			hdr->tag & EVENT_LOG_TAG_FLAG_SET_MASK,
+			hdr->fmt_num);
+		for (count = 0; count < hdr->count; count++)
+			MSCH_EVENTS_PRINTF1(" %x", data[count]);
+		MSCH_EVENTS_PRINTF("\n");
+		return;
+	}
+
+	str_buf = malloc(MAX_NO_OF_ARG * SIZE_LOC_STR);
+	if (!str_buf) {
+		fprintf(stderr, "%s: malloc failed str_buf\n", __FUNCTION__);
+		return;
+	}
+
+	if ((hdr->fmt_num >> 2) < raw_event.num_fmts) {
+		snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "%s",
+				raw_event.fmts[hdr->fmt_num >> 2]);
+		c_ptr = fmtstr_loc_buf;
+	} else {
+		fprintf(stderr, "%s: fmt number out of range \n", __FUNCTION__);
+		goto exit;
+	}
+
+	for (count = 0; count < hdr->count; count++) {
+		if (c_ptr != NULL)
+			if ((c_ptr = bcmstrstr(c_ptr, "%")) != NULL)
+				c_ptr++;
+
+		if (c_ptr != NULL) {
+			if (check_valid_string_format(c_ptr)) {
+				if ((raw_event.raw_sstr) &&
+					((data[count] > raw_event.rodata_start) &&
+					(data[count] < raw_event.rodata_end))) {
+					/* ram static string */
+					addr = data[count] - raw_event.rodata_start;
+					str_tmpptr = raw_event.raw_sstr + addr;
+					memcpy(str_buf[count], str_tmpptr,
+						SIZE_LOC_STR);
+					str_buf[count][SIZE_LOC_STR-1] = '\0';
+					arg[count].addr = str_buf[count];
+				} else if ((raw_event.rom_raw_sstr) &&
+						((data[count] >
+						raw_event.rom_rodata_start) &&
+						(data[count] <
+						raw_event.rom_rodata_end))) {
+					/* rom static string */
+					addr = data[count] - raw_event.rom_rodata_start;
+					str_tmpptr = raw_event.rom_raw_sstr + addr;
+					memcpy(str_buf[count], str_tmpptr,
+						SIZE_LOC_STR);
+					str_buf[count][SIZE_LOC_STR-1] = '\0';
+					arg[count].addr = str_buf[count];
+				} else {
+					/*
+					 *  Dynamic string OR
+					 * No data for static string.
+					 * So store all string's address as string.
+					 */
+					snprintf(str_buf[count], SIZE_LOC_STR,
+						"(s)0x%x", data[count]);
+					arg[count].addr = str_buf[count];
+				}
+			} else {
+				/* Other than string */
+				arg[count].val = data[count];
+			}
+		}
+	}
+
+	nbytes = snprintf(mschbufp, WL_MSCH_PROFILER_BUFFER_SIZE, fmtstr_loc_buf,
+		arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7], arg[8], arg[9]);
+	MSCH_EVENTS_PRINT(nbytes);
+exit:
+	free(str_buf);
+}
+
+static uint64 solt_start_time[4], req_start_time[4], profiler_start_time[4];
+static uint32 solt_chanspec[4] = {0, }, req_start[4] = {0, };
+static bool lastMessages = FALSE;
+
+static void wl_msch_dump_data(char *data, int type)
+{
+	uint64 t = 0, tt = 0;
+	uint32 s = 0, ss = 0;
+	int wlc_index, ver;
+
+	ver = (type & WL_MSCH_PROFILER_VER_MASK) >> WL_MSCH_PROFILER_VER_SHIFT;
+	wlc_index = (type & WL_MSCH_PROFILER_WLINDEX_MASK) >> WL_MSCH_PROFILER_WLINDEX_SHIFT;
+	if (wlc_index >= 4)
+		return;
+
+	type &= WL_MSCH_PROFILER_TYPE_MASK;
+	if (type <= WL_MSCH_PROFILER_PROFILE_END || type == WL_MSCH_PROFILER_EVENT_LOG) {
+		msch_profiler_event_data_t *pevent = (msch_profiler_event_data_t *)data;
+		tt = ((uint64)(ntoh32(pevent->time_hi)) << 32) | ntoh32(pevent->time_lo);
+		s = (uint32)(tt / 1000000);
+		ss = (uint32)(tt % 1000000);
+	}
+
+	if (lastMessages && (type != WL_MSCH_PROFILER_MESSAGE) &&
+		(type != WL_MSCH_PROFILER_EVENT_LOG)) {
+		MSCH_EVENTS_PRINTF("\n");
+		lastMessages = FALSE;
+	}
+
+	switch (type) {
+	case WL_MSCH_PROFILER_START:
+		MSCH_EVENTS_PRINTF2("\n%06d.%06d START\n", s, ss);
+		break;
+
+	case WL_MSCH_PROFILER_EXIT:
+		MSCH_EVENTS_PRINTF2("\n%06d.%06d EXIT\n", s, ss);
+		break;
+
+	case WL_MSCH_PROFILER_REQ:
+	{
+		msch_req_profiler_event_data_t *p = (msch_req_profiler_event_data_t *)data;
+		MSCH_EVENTS_PRINTF("\n===============================\n");
+		MSCH_EVENTS_PRINTF3("%06d.%06d [wl%d] REGISTER:\n", s, ss, wlc_index);
+		wl_msch_req_param_profiler_data(4, ver, data, p->req_param_ptr);
+		wl_msch_chanspec_list(4, data, p->chanspec_ptr, p->chanspec_cnt);
+		MSCH_EVENTS_PRINTF("===============================\n\n");
+	}
+		break;
+
+	case WL_MSCH_PROFILER_CALLBACK:
+	{
+		msch_callback_profiler_event_data_t *p =
+			(msch_callback_profiler_event_data_t *)data;
+		char buf[CHANSPEC_STR_LEN];
+		uint16 cbtype;
+
+		MSCH_EVENTS_PRINTF3("%06d.%06d [wl%d] CALLBACK: ", s, ss, wlc_index);
+		ss = ntoh16(p->chanspec);
+		if (ver >= 2) {
+			MSCH_EVENTS_PRINTF2("req_hdl[0x%08x], channel %s --",
+				ntoh32(p->p_req_hdl), wf_chspec_ntoa(ss, buf));
+		} else {
+			MSCH_EVENTS_PRINTF1("channel %s --", wf_chspec_ntoa(ss, buf));
+		}
+		cbtype = ntoh16(p->type);
+		if (cbtype & WL_MSCH_CT_ON_CHAN)
+			MSCH_EVENTS_PRINTF(" ON_CHAN");
+		if (cbtype & WL_MSCH_CT_OFF_CHAN)
+			MSCH_EVENTS_PRINTF(" OFF_CHAN");
+		if (cbtype & WL_MSCH_CT_REQ_START)
+			MSCH_EVENTS_PRINTF(" REQ_START");
+		if (cbtype & WL_MSCH_CT_REQ_END)
+			MSCH_EVENTS_PRINTF(" REQ_END");
+		if (cbtype & WL_MSCH_CT_SLOT_START)
+			MSCH_EVENTS_PRINTF(" SLOT_START");
+		if (cbtype & WL_MSCH_CT_SLOT_SKIP)
+			MSCH_EVENTS_PRINTF(" SLOT_SKIP");
+		if (cbtype & WL_MSCH_CT_SLOT_END)
+			MSCH_EVENTS_PRINTF(" SLOT_END");
+		if (cbtype & WL_MSCH_CT_OFF_CHAN_DONE)
+			MSCH_EVENTS_PRINTF(" OFF_CHAN_DONE");
+		if (cbtype & WL_MSCH_CT_PARTIAL)
+			MSCH_EVENTS_PRINTF(" PARTIAL");
+		if (cbtype & WL_MSCH_CT_PRE_ONCHAN)
+			MSCH_EVENTS_PRINTF(" PRE_ONCHAN");
+		if (cbtype & WL_MSCH_CT_PRE_REQ_START)
+			MSCH_EVENTS_PRINTF(" PRE_REQ_START");
+
+		if (cbtype & (WL_MSCH_CT_ON_CHAN | WL_MSCH_CT_SLOT_SKIP)) {
+			MSCH_EVENTS_PRINTF("\n    ");
+			if (cbtype & WL_MSCH_CT_ON_CHAN) {
+				if (ver >= 2) {
+					MSCH_EVENTS_PRINTF3("ID %d onchan idx %d seq_start %s ",
+						ntoh32(p->timeslot_id), ntoh32(p->onchan_idx),
+						wl_msch_display_time(p->cur_chan_seq_start_time_h,
+						p->cur_chan_seq_start_time_l));
+				} else {
+					MSCH_EVENTS_PRINTF1("ID %d ", ntoh32(p->timeslot_id));
+				}
+			}
+			t = ((uint64)(ntoh32(p->start_time_h)) << 32) |
+				ntoh32(p->start_time_l);
+			MSCH_EVENTS_PRINTF1("start %s ",
+				wl_msch_display_time(p->start_time_h,
+				p->start_time_l));
+			tt = ((uint64)(ntoh32(p->end_time_h)) << 32) | ntoh32(p->end_time_l);
+			MSCH_EVENTS_PRINTF2("end %s duration %d",
+				wl_msch_display_time(p->end_time_h, p->end_time_l),
+				(p->end_time_h == 0xffffffff && p->end_time_l == 0xffffffff)?
+				-1 : (int)(tt - t));
+		}
+
+		if (cbtype & WL_MSCH_CT_REQ_START) {
+			req_start[wlc_index] = 1;
+			req_start_time[wlc_index] = tt;
+		} else if (cbtype & WL_MSCH_CT_REQ_END) {
+			if (req_start[wlc_index]) {
+				MSCH_EVENTS_PRINTF1(" : REQ duration %d",
+					(uint32)(tt - req_start_time[wlc_index]));
+				req_start[wlc_index] = 0;
+			}
+		}
+
+		if (cbtype & WL_MSCH_CT_SLOT_START) {
+			solt_chanspec[wlc_index] = p->chanspec;
+			solt_start_time[wlc_index] = tt;
+		} else if (cbtype & WL_MSCH_CT_SLOT_END) {
+			if (p->chanspec == solt_chanspec[wlc_index]) {
+				MSCH_EVENTS_PRINTF1(" : SLOT duration %d",
+					(uint32)(tt - solt_start_time[wlc_index]));
+				solt_chanspec[wlc_index] = 0;
+			}
+		}
+		MSCH_EVENTS_PRINTF("\n");
+	}
+		break;
+
+	case WL_MSCH_PROFILER_EVENT_LOG:
+	{
+		msch_event_log_profiler_event_data_t *p =
+			(msch_event_log_profiler_event_data_t *)data;
+		p->hdr.fmt_num = ntoh16(p->hdr.fmt_num);
+		MSCH_EVENTS_PRINTF3("%06d.%06d [wl%d]: ", s, ss, wlc_index);
+		wl_msch_profiler_event_log_data(ver, &p->hdr, p->data);
+		lastMessages = TRUE;
+		break;
+	}
+
+	case WL_MSCH_PROFILER_MESSAGE:
+	{
+		msch_message_profiler_event_data_t *p = (msch_message_profiler_event_data_t *)data;
+		MSCH_EVENTS_PRINTF4("%06d.%06d [wl%d]: %s", s, ss, wlc_index, p->message);
+		lastMessages = TRUE;
+		break;
+	}
+
+	case WL_MSCH_PROFILER_PROFILE_START:
+		profiler_start_time[wlc_index] = tt;
+		MSCH_EVENTS_PRINTF("-------------------------------\n");
+		MSCH_EVENTS_PRINTF3("%06d.%06d [wl%d] PROFILE DATA:\n", s, ss, wlc_index);
+		wl_msch_profiler_profiler_data(4, ver, data, 0);
+		break;
+
+	case WL_MSCH_PROFILER_PROFILE_END:
+		MSCH_EVENTS_PRINTF4("%06d.%06d [wl%d] PROFILE END: take time %d\n", s, ss,
+			wlc_index, (uint32)(tt - profiler_start_time[wlc_index]));
+		MSCH_EVENTS_PRINTF("-------------------------------\n\n");
+		break;
+
+	case WL_MSCH_PROFILER_REQ_HANDLE:
+		wl_msch_req_handle_profiler_data(4, ver, data, 0, FALSE);
+		break;
+
+	case WL_MSCH_PROFILER_REQ_ENTITY:
+		wl_msch_req_entity_profiler_data(4, ver, data, 0, FALSE);
+		break;
+
+	case WL_MSCH_PROFILER_CHAN_CTXT:
+		wl_msch_chan_ctxt_profiler_data(4, ver, data, 0, FALSE);
+		break;
+
+	case WL_MSCH_PROFILER_REQ_TIMING:
+		wl_msch_req_timing_profiler_data(4, ver, "msch", data, 0, FALSE);
+		break;
+
+	default:
+		fprintf(stderr, "[wl%d] ERROR: unsupported EVENT reason code:%d; ",
+			wlc_index, type);
+		break;
+	}
+}
+
+int wl_msch_dump(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int type;
+	char *data, *p, opt;
+	char *fname = NULL, *dir = NULL, *files = NULL;
+	int val, err, start = 1;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	while ((p = *++argv) != NULL) {
+		if (!strcmp(p, "--help") || !strcmp(p, "-h")) {
+			printf("%s", cmd->help);
+			return BCME_OK;
+		}
+
+		if (!strncmp(p, "-", 1)) {
+			opt = p[1];
+			if (strlen(p) > 2) {
+				fprintf(stderr, "wl_msch_dump: only single char options, "
+					"error on param \"%s\"\n", p);
+				return BCME_BADARG;
+			}
+
+			argv++;
+			if (*argv == NULL) {
+				fprintf(stderr, "wl_msch_dump: missing value parameter "
+					"after \"%s\"\n", p);
+				return BCME_USAGE_ERROR;
+			}
+
+			if (opt == 'D')
+				dir = *argv;
+			else if (opt == 'F')
+				files = *argv;
+			else {
+				fprintf(stderr, "error param: %s\n", p);
+				return BCME_BADARG;
+			}
+		} else if (!fname) {
+			fname = p;
+		} else {
+			fprintf(stderr, "error param: %s\n", p);
+			return BCME_BADARG;
+		}
+	}
+
+	if ((err = wlu_iovar_getint(wl, "msch_collect", &val)) < 0)
+		return err;
+
+	if (!(val & WL_MSCH_CMD_ENABLE_BIT))
+		return BCME_NOTREADY;
+
+	if (fname) {
+		if (!(mschfp = fopen(fname, "wb"))) {
+			perror(fname);
+			fprintf(stderr, "Cannot open file %s\n", fname);
+			return BCME_BADARG;
+		}
+	}
+
+	wl_init_frm_array(dir, files);
+
+	err = wlu_var_getbuf(wl, "msch_dump", &start, sizeof(int), &ptr);
+	while (err >= 0) {
+		msch_collect_tlv_t *ptlv = (msch_collect_tlv_t *)ptr;
+
+		type = dtoh16(ptlv->type);
+		data = ptlv->value;
+
+		wl_msch_dump_data(data, type);
+
+		err = wlu_var_getbuf(wl, "msch_dump", NULL, 0, &ptr);
+	}
+
+	if (mschfp) {
+		fflush(mschfp);
+		fclose(mschfp);
+		mschfp = NULL;
+	}
+
+	fflush(stdout);
+	return BCME_OK;
+}
+
+#if defined(linux)
+
+int wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len);
+
+int wl_msch_event_check(void *wl, cmd_t *cmd, char **argv)
+{
+	int fd, err, octets;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	char ifnames[IFNAMSIZ] = {"eth0"};
+	bcm_event_t *event;
+	char *data;
+	int event_type, reason;
+	uint8 event_inds_mask[WL_EVENTING_MASK_LEN];
+	char *p, *fname = NULL, *dir = NULL, *files = NULL;
+	int opt, val;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if (argv[1] == NULL) {
+		fprintf(stderr, "<ifname> param is missing\n");
+		return -1;
+	}
+
+	if (*++argv) {
+		if (!strcmp(*argv, "--help") || !strcmp(*argv, "-h")) {
+			printf("%s", cmd->help);
+			return BCME_OK;
+		}
+		strncpy(ifnames, *argv, (IFNAMSIZ - 1));
+	}
+
+	if ((err = wlu_iovar_getint(wl, "msch_event", &val)) < 0)
+		return err;
+
+	bzero(&ifr, sizeof(ifr));
+	strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		fprintf(stderr, "Cannot create socket %d\n", fd);
+		return -1;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		fprintf(stderr, "Cannot get iface:%s index \n", ifr.ifr_name);
+		goto exit;
+	}
+
+	bzero(&sll, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		fprintf(stderr, "Cannot bind %d\n", err);
+		goto exit;
+	}
+
+	while (*++argv) {
+		opt = 0;
+		p = *argv;
+		if (p[0] == '+') {
+			opt = 1;
+			p++;
+		}
+		else if (p[0] == '-') {
+			opt = 2;
+			p++;
+		}
+
+		if (opt == 0) {
+			fname = p;
+			if (mschfp == NULL) {
+				if (!(mschfp = fopen(fname, "wb"))) {
+					perror(fname);
+					fprintf(stderr, "Cannot open file %s\n", fname);
+					err = BCME_BADARG;
+					goto exit;
+				}
+			}
+			else {
+				err = BCME_BADARG;
+				fprintf(stderr, "error param: %s\n", p);
+				goto exit;
+			}
+		} else {
+			if (opt == 2 && (!strcmp(p, "all") || !strcmp(p, "a"))) {
+				val &= ~WL_MSCH_CMD_ALL_BITS;
+			} else if (!strcmp(p, "profiler") || !strcmp(p, "p")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_PROFILE_BIT;
+				else
+					val &= ~WL_MSCH_CMD_PROFILE_BIT;
+			}
+			else if (!strcmp(p, "callback") || !strcmp(p, "c")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_CALLBACK_BIT;
+				else
+					val &= ~WL_MSCH_CMD_CALLBACK_BIT;
+			}
+			else if (!strcmp(p, "register") || !strcmp(p, "r")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_REGISTER_BIT;
+				else
+					val &= ~WL_MSCH_CMD_REGISTER_BIT;
+			}
+			else if (!strcmp(p, "error") || !strcmp(p, "e")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_ERROR_BIT;
+				else
+					val &= ~WL_MSCH_CMD_ERROR_BIT;
+			}
+			else if (!strcmp(p, "debug") || !strcmp(p, "d")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_DEBUG_BIT;
+				else
+					val &= ~WL_MSCH_CMD_DEBUG_BIT;
+			}
+			else if (!strcmp(p, "info") || !strcmp(p, "i")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_INFOM_BIT;
+				else
+					val &= ~WL_MSCH_CMD_INFOM_BIT;
+			}
+			else if (!strcmp(p, "trace") || !strcmp(p, "t")) {
+				if (opt == 1)
+					val |= WL_MSCH_CMD_TRACE_BIT;
+				else
+					val &= ~WL_MSCH_CMD_TRACE_BIT;
+			}
+			else if (opt == 2 && !strcmp(p, "D") && *++argv) {
+				dir = *argv;
+				printf("dir: %s\n", dir);
+			}
+			else if (opt == 2 && !strcmp(p, "F") && *++argv) {
+				files = *argv;
+				printf("files: %s\n", files);
+			}
+			else {
+				err = BCME_EPERM;
+				goto exit;
+			}
+		}
+	}
+
+	data = &mschdata[sizeof(bcm_event_t)];
+
+	/*  read current mask state  */
+	if ((err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN))) {
+		fprintf(stderr, "couldn't read event_msgs\n");
+		goto exit;
+	}
+	event_inds_mask[WLC_E_MSCH / 8] |= (1 << (WLC_E_MSCH % 8));
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN))) {
+		fprintf(stderr, "couldn't write event_msgs\n");
+		goto exit;
+	}
+
+	val &= ~WL_MSCH_CMD_VER_MASK;
+	val |= (WL_MSCH_CMD_ENABLE_BIT | (WL_MSCH_PROFILER_VER << WL_MSCH_CMD_VER_SHIFT));
+	if ((err = wlu_iovar_setint(wl, "msch_event", val))) {
+		fprintf(stderr, "couldn't start msch event\n");
+		goto exit;
+	}
+
+	wl_init_frm_array(dir, files);
+
+	printf("wating for MSCH events :%s\n", ifr.ifr_name);
+
+	while (1) {
+		fflush(stdout);
+		octets = recv(fd, mschdata, WL_MSCH_PROFILER_BUFFER_SIZE, 0);
+
+		if (octets <= 0)  {
+			/* sigterm */
+			err = -1;
+			break;
+		}
+
+		event = (bcm_event_t *)mschdata;
+		event_type = ntoh32(event->event.event_type);
+		reason = ntoh32(event->event.reason);
+
+		if ((event_type != WLC_E_MSCH)) {
+			if (event_type == WLC_E_ESCAN_RESULT) {
+				wl_escan_result_t* escan_data = (wl_escan_result_t*)data;
+				uint16	i;
+				MSCH_EVENTS_PRINTF1("MACEVENT_%d: WLC_E_ESCAN_RESULT:", event_type);
+				for (i = 0; i < escan_data->bss_count; i++) {
+					wl_bss_info_t *bi = &escan_data->bss_info[i];
+					char ssidbuf[SSID_FMT_BUF_LEN];
+					char chspec_str[CHANSPEC_STR_LEN];
+					wl_format_ssid(ssidbuf, bi->SSID, bi->SSID_len);
+					MSCH_EVENTS_PRINTF2(" SSID: \"%s\", Channel: %s;",
+						ssidbuf, wf_chspec_ntoa(bi->chanspec, chspec_str));
+				}
+				MSCH_EVENTS_PRINTF("\n");
+			} else {
+				char *event_name;
+				switch (event_type) {
+				case WLC_E_JOIN:
+					event_name = "WLC_E_JOIN";
+					break;
+
+				case WLC_E_AUTH:
+					event_name = "WLC_E_AUTH";
+					break;
+
+				case WLC_E_ASSOC:
+					event_name = "WLC_E_ASSOC";
+					break;
+
+				case WLC_E_LINK:
+					event_name = "WLC_E_LINK";
+					break;
+
+				case WLC_E_ROAM:
+					event_name = "WLC_E_ROAM";
+					break;
+
+				case WLC_E_SCAN_COMPLETE:
+					event_name = "WLC_E_SCAN_COMPLETE";
+					break;
+
+				case WLC_E_SCAN_CONFIRM_IND:
+					event_name = "WLC_E_SCAN_CONFIRM_IND";
+					break;
+
+				case WLC_E_ASSOC_REQ_IE:
+					event_name = "WLC_E_ASSOC_REQ_IE";
+					break;
+
+				case WLC_E_ASSOC_RESP_IE:
+					event_name = "WLC_E_ASSOC_RESP_IE";
+					break;
+
+				case WLC_E_BSSID:
+					event_name = "WLC_E_BSSID";
+					break;
+
+				default:
+					event_name = "Unknown Event";
+				}
+				MSCH_EVENTS_PRINTF2("MACEVENT_%d: %s\n", event_type, event_name);
+			}
+			continue;
+		}
+
+		wl_msch_dump_data(data, reason);
+
+		if ((reason & WL_MSCH_PROFILER_TYPE_MASK) == WL_MSCH_PROFILER_EXIT)
+			goto exit;
+	}
+exit:
+	/* if we ever reach here */
+	close(fd);
+	if (mschfp) {
+		fflush(mschfp);
+		fclose(mschfp);
+		mschfp = NULL;
+	}
+
+	/* Read the event mask from driver and mask the event WLC_E_MSCH */
+	if (!(err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN))) {
+		event_inds_mask[WLC_E_MSCH / 8] &= (~(1 << (WLC_E_MSCH % 8)));
+		err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN);
+	}
+
+	fflush(stdout);
+	return (err);
+}
+#endif /* linux */
+
+typedef struct wl_msch_profiler_struct {
+	uint32	start_ptr;
+	uint32	write_ptr;
+	uint32	write_size;
+	uint32	read_ptr;
+	uint32	read_size;
+	uint32	total_size;
+	uint32  buffer;
+} wl_msch_profiler_struct_t;
+
+#define MSCH_MAGIC_1		0x4d534348
+#define MSCH_MAGIC_2		0x61676963
+
+#undef ROUNDUP
+#define	ROUNDUP(x)		(((x) + 3) & (~0x03))
+
+#define MAX_PROFILE_DATA_SIZE	4096
+
+int wl_msch_profiler(void *wl, cmd_t *cmd, char **argv)
+{
+	char *fname_r = NULL, *fname_w = NULL, *dir = NULL, *files = NULL;
+	char *buffer = NULL, *p, opt;
+	FILE *fp = NULL;
+	int err = BCME_OK;
+	uint32 magicdata;
+	uint32 rptr, rsize, wsize, tsize;
+	wl_msch_profiler_struct_t profiler;
+	bool found = FALSE;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	while ((p = *++argv) != NULL) {
+		if (!strcmp(p, "--help") || !strcmp(p, "-h")) {
+			printf("%s", cmd->help);
+			return BCME_OK;
+		}
+
+		if (!strncmp(p, "-", 1)) {
+			opt = p[1];
+			if (strlen(p) > 2) {
+				fprintf(stderr, "wl_msch_profiler: only single char options, "
+					"error on param \"%s\"\n", p);
+				return BCME_BADARG;
+			}
+
+			argv++;
+			if (*argv == NULL) {
+				fprintf(stderr, "wl_msch_profiler: missing value parameter "
+					"after \"%s\"\n", p);
+				return BCME_USAGE_ERROR;
+			}
+
+			if (opt == 'D')
+				dir = *argv;
+			else if (opt == 'F')
+				files = *argv;
+			else {
+				fprintf(stderr, "error param: %s\n", p);
+				return BCME_BADARG;
+			}
+		} else if (!fname_r) {
+			fname_r = p;
+		} else if (!fname_w) {
+			fname_w = p;
+		} else {
+			fprintf(stderr, "error param: %s\n", p);
+			return BCME_BADARG;
+		}
+	}
+
+	if (fname_r == NULL) {
+		fprintf(stderr, "<input filename> param is missing\n");
+		return -1;
+	}
+
+	if (!(fp = fopen(fname_r, "rb"))) {
+		perror(fname_r);
+		fprintf(stderr, "Cannot open input file %s\n", fname_r);
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	rptr = 0;
+	while ((rsize = fread(&magicdata, 1, sizeof(uint32), fp)) > 0) {
+		rptr += rsize;
+		magicdata = dtoh32(magicdata);
+		if (magicdata != MSCH_MAGIC_1)
+			continue;
+
+		if ((rsize = fread(&magicdata, 1, sizeof(uint32), fp)) > 0) {
+			rptr += rsize;
+			magicdata = dtoh32(magicdata);
+			if (magicdata != MSCH_MAGIC_2)
+				continue;
+		}
+
+		rsize = fread(&profiler, 1, sizeof(wl_msch_profiler_struct_t), fp);
+		rptr += rsize;
+		magicdata = dtoh32(profiler.buffer);
+
+		if (((rptr ^ magicdata) & 0xffff) == 0) {
+			found = TRUE;
+			break;
+		}
+	}
+
+	if (!found) {
+		fprintf(stderr, "Cannot find profiler data from file %s\n", fname_r);
+		err = BCME_NOTFOUND;
+		goto exit;
+	}
+
+	if (fname_w) {
+		if (!(mschfp = fopen(fname_w, "wb"))) {
+			perror(fname_w);
+			fprintf(stderr, "Cannot open file %s\n", fname_w);
+			err = BCME_BADARG;
+			goto exit;
+		}
+	}
+
+	tsize = dtoh32(profiler.total_size);
+	buffer = (char*)malloc(tsize + MAX_PROFILE_DATA_SIZE);
+	if (buffer == NULL) {
+		fprintf(stderr, "Cannot not allocate %d bytes for profiler buffer\n",
+			tsize);
+		err = BCME_NOMEM;
+		goto exit;
+	}
+
+	if ((rsize = fread(buffer, 1, tsize, fp)) != tsize) {
+		fprintf(stderr, "Cannot read profiler data from file %s, req %d, read %d\n",
+			fname_r, tsize, rsize);
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	wsize = dtoh32(profiler.write_size);
+	rptr = dtoh32(profiler.start_ptr);
+	rsize = 0;
+
+	wl_init_frm_array(dir, files);
+
+	while (rsize < wsize) {
+		msch_collect_tlv_t *ptlv = (msch_collect_tlv_t *)(buffer + rptr);
+		int type, size, remain;
+		char *data;
+
+		size = ROUNDUP(WL_MSCH_PROFILE_HEAD_SIZE + dtoh16(ptlv->size));
+
+		rsize += size;
+		if (rsize > wsize)
+			break;
+
+		remain = tsize - rptr;
+		if (remain >= size) {
+			rptr += size;
+			if (rptr == tsize)
+				rptr = 0;
+		} else {
+			remain = size - remain;
+			memcpy(buffer + tsize, buffer, remain);
+			rptr = remain;
+		}
+
+		type = dtoh16(ptlv->type);
+		data = ptlv->value;
+
+		wl_msch_dump_data(data, type);
+	}
+
+	err = BCME_OK;
+
+exit:
+	if (fp)
+		fclose(fp);
+
+	if (buffer)
+		free(buffer);
+
+	if (mschfp) {
+		fflush(mschfp);
+		fclose(mschfp);
+		mschfp = NULL;
+	}
+
+	fflush(stdout);
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_nan.c b/wl/src/wl/exe/wluc_nan.c
new file mode 100644
index 0000000..3211439
--- /dev/null
+++ b/wl/src/wl/exe/wluc_nan.c
@@ -0,0 +1,6288 @@
+/*
+ * wl nan command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_nan.c 458728 2014-02-27 18:15:25Z $
+ */
+#ifdef WL_NAN
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+#include "wlu_avail_utils.h"
+#include <bcmiov.h>
+
+#if defined(linux)
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* linux */
+
+#include <miniopt.h>
+
+#include <bcmcrypto/sha256.h>
+#include <proto/nan.h>
+#include <bcmbloom.h>
+#include <bcmtlv.h>
+
+#define MAX_MAC_BUF  20
+#define MAX_RSSI_BUF 128
+#define MAX_OOB_AF_LIFETIME	512
+static void
+print_peer_rssi(wl_nan_peer_rssi_data_t *prssi);
+
+static cmd_func_t wl_nan_control;
+
+#define WLU_AVAIL_MAX_SLOTS 32
+#define WL_NAN_INVALID_NDPID 0
+
+#define NAN_PARAMS_USAGE	\
+"\tUsage: wl nan [command] [cmd options] as follows:\n"	\
+"\t\twl nan enable [1/0] - enable disable nan functionality\n" \
+"\t\twl nan state [role] - sets or gets the nan role\n" \
+"\t\twl nan hop_count [value] - sets or gets the hop count value\n" \
+"\t\twl nan hop_limit [value] - sets or gets the hop count threshold "\
+"value\n" \
+"\t\twl nan warm_up_time [value] - sets or gets the warm-up time in"\
+"units of seconds\n" \
+"\t\twl nan rssi_threshold [band][close][mid] - set rssi threshold for a band\n"\
+"\t\twl nan status -  gets the status of NAN network \n" \
+"\t\twl nan OUI [value] - sets or gets the OUI value\n" \
+"\t\twl nan count - get counters\n" \
+"\t\twl nan clearcount - clears the counters\n" \
+"\t\twl nan chan [chan num] - sets the channel value\n" \
+"\t\twl nan band [value] - sets the band value(a/g/auto)\n" \
+"\t\twl nan host_enable [value] - enable/disable host election\n" \
+"\t\twl nan election_metrics [random_fact][master pref] - set random factor and preference\n" \
+"\t\twl nan election_metrics_state - get random fact and preference\n" \
+"\t\twl nan join [-start][cid] - joins/starts a nan network\n" \
+"\t\twl nan leave [cid]- leaves the network with cid mentioned\n" \
+"\t\twl nan merge [cid]- merges the network with cid mentioned\n" \
+"\t\twl nan stop [cid]-  stop participating in the network\n" \
+"\t\twl nan publish [instance] [service name] [options] - get/set\n" \
+"\t\twl nan publish_list [..]\n" \
+"\t\twl nan cancel_publish [..]\n" \
+"\t\twl nan subscribe [instance] [service name] [options]\n" \
+"\t\twl nan subscribe_list [..]\n" \
+"\t\twl nan cancel_subscribe [..]\n" \
+"\t\twl nan vendor_info [..]\n" \
+"\t\twl nan disc_stats [..]\n" \
+"\t\twl nan disc_transmit [..]\n" \
+"\t\twl nan followup_transmit [..]\n" \
+"\t\twl nan show - Shows the NAN status\n" \
+"\t\twl nan tsreserve [bitmap] [channel list]\n" \
+"\t\twl nan tsschedule [..]\n" \
+"\t\twl nan tsrelease [bitmap]\n" \
+"\t\twl nan disc_connection [..]\n" \
+"\t\twl nan scan_params -s [scantime] -h [hometime] -i "\
+"[merge_scan_interval] -d [merge_scan_duration] -c [6,44,149]\n"\
+"\t\twl nan scan\n" \
+"\t\twl nan scanresults\n" \
+"\t\twl nan event_msgs\n" \
+"\t\twl nan event_check\n" \
+"\t\twl nan dump\n" \
+"\t\twl nan clear\n" \
+"\t\twl nan rssi\n" \
+"\t\twl nan disc_results\n" \
+"\t\twl nan dp_show\n" \
+"\t\twl nan dp_stats\n" \
+"\t\twl nan dp_status <ndp_id> <reason_code>\n" \
+"\t\twl nan dp_schedupd <ndp_id>  \n" \
+"\t\twl nan dp_autoconn <val> - 0th bit for auto_dpresp, 1st bit for auto_dpconf \n" \
+"\t\twl nan dp_conf <ndp id> <status>\n" \
+"\t\twl nan dp_end <ndp id> <status>\n" \
+"\t\twl nan dp_req ucast/mcast pub_id <publisher id> peer_mac<peer mac address>" \
+" mcast_mac <if dest multicast addr exists> qos <tid, pkt_size, mean_data_rate, " \
+" max_service_interval> security <val> svc_spec_info <app specific info in hex>\n" \
+"\t\twl nan dp_resp ucast/mcast ndp_id <ndp id/ mc_id for unicast or multicast>" \
+" peer_mac<peer mac address> mcast_mac <if dest multicast addr exists>" \
+" qos <tid, pkt_size, mean_data_rate, max_service_interval> security <val>" \
+" svc_spec_info <app specific info in hex>\n" \
+"\tUsage: mutiple commands batching\n\n"\
+"\tA set of either SET or GET commands can be batched\n"\
+"\t\twl nan enable [1/0] + attr [MAC, ETC]\n" \
+"\t\tabove command issues SET enable and SET attr commands at a time\n"\
+"\t\twl nan enable + scanresults\n" \
+"\t\tabove command issues GET enable and GET scanresults commands at a time\n"
+
+typedef struct wl_nan_dp_sub_cmd wl_nan_dp_sub_cmd_t;
+typedef int (nan_dp_cmd_hdlr_t)(void *wl, const wl_nan_dp_sub_cmd_t *cmd, char **argv, int ndp_id);
+/* nan cmd list entry  */
+struct wl_nan_dp_sub_cmd {
+	char *name;                     /* cmd name */
+	uint8  version;                 /* cmd  version */
+	uint16 id;                      /* id for the dongle f/w switch/case  */
+	uint16 type;                    /* base type of argument */
+	nan_dp_cmd_hdlr_t *handler;    /* cmd handler */
+};
+
+#define NAN_DP_AVAIL_MAX_STR_LEN	32
+#define NAN_DP_AVAIL_ENTRIES		8
+
+typedef struct wl_nan_dp_avail_entry {
+	uint32 period;
+	char entry[NAN_DP_AVAIL_MAX_STR_LEN];
+} wl_nan_dp_avail_entry_t;
+
+static char *
+bcm_ether_ntoa(const struct ether_addr *ea, char *buf);
+
+static cmd_t wl_nan_cmds[] = {
+	{ "nan", wl_nan_control, WLC_GET_VAR, WLC_SET_VAR, ""},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_nan_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register nan commands */
+	wl_module_cmds_register(wl_nan_cmds);
+}
+
+uint8
+wl_nan_resolution_timeunit(uint8 dur)
+{
+	switch (dur) {
+		case NAN_AVAIL_RES_16_TU:
+			return 16;
+		break;
+		case NAN_AVAIL_RES_32_TU:
+			return 32;
+		break;
+		case NAN_AVAIL_RES_64_TU:
+			return 64;
+		break;
+		default:
+			return 255;
+	}
+}
+
+uint8
+wl_nan_resolution_string_to_num(const char *res)
+{
+	uint8 res_n = NAN_AVAIL_RES_INVALID;
+	if (!strcmp(res, "16tu")) {
+		res_n = NAN_AVAIL_RES_16_TU;
+	}
+	else if (!strcmp(res, "32tu")) {
+		res_n = NAN_AVAIL_RES_32_TU;
+	}
+	else if (!strcmp(res, "64tu")) {
+		res_n = NAN_AVAIL_RES_64_TU;
+	}
+	else {
+		// Invalid
+	}
+	return res_n;
+}
+
+static wl_nan_status_t
+wl_nan_is_instance_valid(int id)
+{
+	wl_nan_status_t ret = WL_NAN_E_OK;
+
+	if (id <= 0 || id > 255) {
+		ret = WL_NAN_E_BAD_INSTANCE;
+	}
+
+	return ret;
+}
+
+static int
+bcm_pack_xtlv_entry_from_hex_string(uint8 **tlv_buf, uint16 *buflen, uint16 type, char *hex);
+static int wl_nan_bloom_create(bcm_bloom_filter_t** bp, uint* idx, uint size);
+static void* wl_nan_bloom_alloc(void *ctx, uint size);
+static void wl_nan_bloom_free(void *ctx, void *buf, uint size);
+static uint wl_nan_hash(void* ctx, uint idx, const uint8 *input, uint input_len);
+static void wlu_nan_print_wl_avail_entry(uint8 avail_type, wl_avail_entry_t* entry);
+static int wl_nan_set_avail_entry_optional(char** argv, wl_avail_new_t* avail,
+	wl_avail_entry_t* entry, uint8 avail_type, uint8* num);
+
+/* ************************** wl NAN command & event handlers ********************** */
+#define NAN_ERROR(x) printf x
+#define WL_NAN_FUNC(suffix) wl_nan_subcmd_ ##suffix
+#define NAN_IOC_BUFSZ  256 /* some sufficient ioc buff size for our module */
+#define NAN_BLOOM_LENGTH_DEFAULT	240
+#define NAN_SRF_MAX_MAC	(NAN_BLOOM_LENGTH_DEFAULT / ETHER_ADDR_LEN)
+/* Mask for CRC32 output, used in hash function for NAN bloom filter */
+#define NAN_BLOOM_CRC32_MASK	0xFFFF
+
+struct tlv_info_list {
+	char *name;
+	enum wl_nan_sub_cmd_xtlv_id type;
+};
+
+/*  nan ioctl sub cmd handler functions  */
+static cmd_handler_t wl_nan_subcmd_cfg_enable;
+static cmd_handler_t wl_nan_subcmd_cfg_state;
+static cmd_handler_t wl_nan_subcmd_cfg_hop_count;
+static cmd_handler_t wl_nan_subcmd_cfg_hop_limit;
+static cmd_handler_t wl_nan_subcmd_cfg_warmup_time;
+static cmd_handler_t wl_nan_subcmd_cfg_rssi_threshold;
+static cmd_handler_t wl_nan_subcmd_cfg_status;
+static cmd_handler_t wl_nan_subcmd_cfg_oui;
+static cmd_handler_t wl_nan_subcmd_cfg_count;
+static cmd_handler_t wl_nan_subcmd_cfg_clearcount;
+static cmd_handler_t wl_nan_subcmd_cfg_channel;
+static cmd_handler_t wl_nan_subcmd_cfg_band;
+static cmd_handler_t wl_nan_subcmd_cfg_cid;
+static cmd_handler_t wl_nan_subcmd_cfg_if_addr;
+static cmd_handler_t wl_nan_subcmd_cfg_bcn_interval;
+static cmd_handler_t wl_nan_subcmd_cfg_sdf_txtime;
+static cmd_handler_t wl_nan_subcmd_cfg_stop_bcn_tx;
+static cmd_handler_t wl_nan_subcmd_cfg_sid_beacon;
+static cmd_handler_t wl_nan_subcmd_cfg_dw_len;
+static cmd_handler_t wl_nan_subcmd_cfg_awake_dw;
+static cmd_handler_t wl_nan_subcmd_cfg_wfa_testmode;
+static cmd_handler_t wl_nan_subcmd_election_host_enable;
+static cmd_handler_t wl_nan_subcmd_election_metrics_config;
+static cmd_handler_t wl_nan_subcmd_election_metrics_state;
+static cmd_handler_t wl_nan_subcmd_join;
+static cmd_handler_t wl_nan_subcmd_leave;
+static cmd_handler_t wl_nan_subcmd_merge;
+static cmd_handler_t wl_nan_subcmd_stop;
+static cmd_handler_t wl_nan_subcmd_publish;
+static cmd_handler_t wl_nan_subcmd_publish_list;
+static cmd_handler_t wl_nan_subcmd_cancel_publish;
+static cmd_handler_t wl_nan_subcmd_subscribe;
+static cmd_handler_t wl_nan_subcmd_subscribe_list;
+static cmd_handler_t wl_nan_subcmd_cancel_subscribe;
+static cmd_handler_t wl_nan_subcmd_sd_vendor_info;
+static cmd_handler_t wl_nan_subcmd_sd_statistics;
+static cmd_handler_t wl_nan_subcmd_sd_transmit;
+static cmd_handler_t wl_nan_subcmd_sd_connection;
+static cmd_handler_t wl_nan_subcmd_sd_show;
+static cmd_handler_t wl_nan_subcmd_sync_tsreserve;
+static cmd_handler_t wl_nan_subcmd_sync_tsschedule;
+static cmd_handler_t wl_nan_subcmd_sync_tsrelease;
+static cmd_handler_t wl_nan_subcmd_scan;
+static cmd_handler_t wl_nan_subcmd_scan_params;
+static cmd_handler_t wl_nan_subcmd_disc_results;
+static cmd_handler_t wl_nan_subcmd_dbg_scan_results;
+static cmd_handler_t wl_nan_subcmd_event_msgs;
+#if defined(linux)
+static cmd_handler_t wl_nan_subcmd_event_check;
+#endif
+static cmd_handler_t wl_nan_subcmd_dump;
+static cmd_handler_t wl_nan_subcmd_clear;
+static cmd_handler_t wl_nan_subcmd_dbg_rssi;
+static cmd_handler_t wl_nan_subcmd_dbg_level;
+/* nan 2.0 */
+static cmd_handler_t wl_nan_subcmd_dp_cap;
+static cmd_handler_t wl_nan_subcmd_dp_autoconn;
+static cmd_handler_t wl_nan_subcmd_dp_req;
+static cmd_handler_t wl_nan_subcmd_dp_resp;
+static cmd_handler_t wl_nan_subcmd_dp_conf;
+static cmd_handler_t wl_nan_subcmd_dp_dataend;
+static cmd_handler_t wl_nan_subcmd_dp_status;
+static cmd_handler_t wl_nan_subcmd_dp_stats;
+static cmd_handler_t wl_nan_subcmd_dp_show;
+static cmd_handler_t wl_nan_subcmd_dp_schedupd;
+static cmd_handler_t wl_nan_subcmd_cfg_avail;
+static cmd_handler_t wl_nan_subcmd_range_req;
+static cmd_handler_t wl_nan_subcmd_range_resp;
+static cmd_handler_t wl_nan_subcmd_range_cancel;
+static cmd_handler_t wl_nan_subcmd_range_auto;
+
+/* Mandatory parameters count for different commands */
+#define WL_NAN_CMD_CFG_OUI_ARGC				2
+#define WL_NAN_CMD_CFG_RSSI_THRESHOLD_ARGC		3
+#define WL_NAN_CMD_CFG_ELECTION_METRICS_ARGC		2
+#define WL_NAN_CMD_CFG_SID_BCN_ARGC			2
+
+static const wl_nan_sub_cmd_t nan_cmd_list[] = {
+	/* wl nan enable [0/1] or new: "wl nan [0/1]" */
+	{"enable", 0x01, WL_NAN_CMD_CFG_ENABLE,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_enable)
+	},
+	/* read write multiple nan attributes (obsolete) */
+	{"state", 0x01, WL_NAN_CMD_CFG_STATE,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_state),
+	},
+	/* -- var attributes (treated as cmds now) --  */
+	{"hop_count", 0x01, WL_NAN_CMD_CFG_HOP_CNT,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_hop_count),
+	},
+	{"hop_limit", 0x01, WL_NAN_CMD_CFG_HOP_LIMIT,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_hop_limit),
+	},
+	{"warm_up_time", 0x01, WL_NAN_CMD_CFG_WARMUP_TIME,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_warmup_time),
+	},
+	{"rssi_threshold", 0x01, WL_NAN_CMD_CFG_RSSI_THRESHOLD,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_rssi_threshold),
+	},
+	{"status", 0x01, WL_NAN_CMD_CFG_STATUS,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_status),
+	},
+	{"OUI", 0x01, WL_NAN_CMD_CFG_OUI,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_oui)
+	},
+	{"count", 0x01, WL_NAN_CMD_CFG_COUNT,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_count)
+	},
+	{"clearcount", 0x01, WL_NAN_CMD_CFG_CLEARCOUNT,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_clearcount)
+	},
+	{"chan", 0x01, WL_NAN_CMD_CFG_CHANNEL,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_channel)
+	},
+	{"band", 0x01, WL_NAN_CMD_CFG_BAND,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_band)
+	},
+	{"cluster_id", 0x01, WL_NAN_CMD_CFG_CID,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_cid)
+	},
+	{"if_addr", 0x01, WL_NAN_CMD_CFG_IF_ADDR,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_if_addr)
+	},
+	{"bcn_interval", 0x01, WL_NAN_CMD_CFG_BCN_INTERVAL,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_bcn_interval)
+	},
+	{"sdf_txtime", 0x01, WL_NAN_CMD_CFG_SDF_TXTIME,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_sdf_txtime)
+	},
+	{"stop_bcn_tx", 0x01, WL_NAN_CMD_CFG_STOP_BCN_TX,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_stop_bcn_tx)
+	},
+	{"sid_beacon", 0x01, WL_NAN_CMD_CFG_SID_BEACON,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_sid_beacon)
+	},
+	{"dw_len", 0x01, WL_NAN_CMD_CFG_DW_LEN,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_dw_len)
+	},
+	{"avail", 0x01, WL_NAN_CMD_CFG_AVAIL,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_avail)
+	},
+	{"awake_dw", 0x01, WL_NAN_CMD_CFG_AWAKE_DW,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_awake_dw)
+	},
+	{"wfa_testmode", 0x01, WL_NAN_CMD_CFG_WFA_TM,
+	IOVT_BUFFER, WL_NAN_FUNC(cfg_wfa_testmode)
+	},
+	/* ------- nan mac/disc engine commands ---- */
+	{"host_enable", 0x01, WL_NAN_CMD_ELECTION_HOST_ENABLE,
+	IOVT_BUFFER, WL_NAN_FUNC(election_host_enable)
+	},
+	{"election_metrics", 0x01, WL_NAN_CMD_ELECTION_METRICS_CONFIG,
+	IOVT_BUFFER, WL_NAN_FUNC(election_metrics_config)
+	},
+	{"election_metrics_state", 0x01, WL_NAN_CMD_ELECTION_METRICS_STATE,
+	IOVT_BUFFER, WL_NAN_FUNC(election_metrics_state)
+	},
+	{"join", 0x01, WL_NAN_CMD_ELECTION_JOIN,
+	IOVT_BUFFER, WL_NAN_FUNC(join)
+	},
+	{"leave", 0x01, WL_NAN_CMD_ELECTION_LEAVE,
+	IOVT_BUFFER, WL_NAN_FUNC(leave)
+	},
+	{"merge", 0x01, WL_NAN_CMD_ELECTION_MERGE,
+	IOVT_BUFFER, WL_NAN_FUNC(merge)
+	},
+	{"stop", 0x01, WL_NAN_CMD_ELECTION_STOP,
+	IOVT_BUFFER, WL_NAN_FUNC(stop)
+	},
+	{"publish", 0x01, WL_NAN_CMD_SD_PUBLISH,
+	IOVT_BUFFER, WL_NAN_FUNC(publish)
+	},
+	{"publish_list", 0x01, WL_NAN_CMD_SD_PUBLISH_LIST,
+	IOVT_BUFFER, WL_NAN_FUNC(publish_list)
+	},
+	{"cancel_publish", 0x01, WL_NAN_CMD_SD_CANCEL_PUBLISH,
+	IOVT_BUFFER, WL_NAN_FUNC(cancel_publish)
+	},
+	{"subscribe", 0x01, WL_NAN_CMD_SD_SUBSCRIBE,
+	IOVT_BUFFER, WL_NAN_FUNC(subscribe)
+	},
+	{"subscribe_list", 0x01, WL_NAN_CMD_SD_SUBSCRIBE_LIST,
+	IOVT_BUFFER, WL_NAN_FUNC(subscribe_list)
+	},
+	{"cancel_subscribe", 0x01, WL_NAN_CMD_SD_CANCEL_SUBSCRIBE,
+	IOVT_BUFFER, WL_NAN_FUNC(cancel_subscribe)
+	},
+	{"vendor_info", 0x01, WL_NAN_CMD_SD_VND_INFO,
+	IOVT_BUFFER, WL_NAN_FUNC(sd_vendor_info)
+	},
+	{"disc_stats", 0x01, WL_NAN_CMD_SD_STATS,
+	IOVT_BUFFER, WL_NAN_FUNC(sd_statistics)
+	},
+	{"disc_transmit", 0x01, WL_NAN_CMD_SD_TRANSMIT,
+	IOVT_BUFFER, WL_NAN_FUNC(sd_transmit)
+	},
+	{"followup_transmit", 0x01, WL_NAN_CMD_SD_FUP_TRANSMIT,
+	IOVT_BUFFER, WL_NAN_FUNC(sd_transmit)
+	},
+	{"disc_connection", 0x01, WL_NAN_CMD_SD_CONNECTION,
+	IOVT_BUFFER, WL_NAN_FUNC(sd_connection)
+	},
+	/* uses same cmd handler for as status */
+	{"show", 0x01, WL_NAN_CMD_SD_SHOW,
+	IOVT_BUFFER, WL_NAN_FUNC(sd_show)
+	},
+	/* time sync commands */
+	{"tsreserve", 0x01, WL_NAN_CMD_SYNC_TSRESERVE,
+	IOVT_BUFFER, WL_NAN_FUNC(sync_tsreserve)
+	},
+	{"tsschedule", 0x01, WL_NAN_CMD_SYNC_TSSCHEDULE,
+	IOVT_BUFFER, WL_NAN_FUNC(sync_tsschedule)
+	},
+	{"tsrelease", 0x01, WL_NAN_CMD_SYNC_TSRELEASE,
+	IOVT_BUFFER, WL_NAN_FUNC(sync_tsrelease)
+	},
+	/* nan debug commands */
+	{"scan_params", 0x01, WL_NAN_CMD_DBG_SCAN_PARAMS,
+	IOVT_BUFFER,  WL_NAN_FUNC(scan_params)
+	},
+	{"scan", 0x01, WL_NAN_CMD_DBG_SCAN,
+	IOVT_BUFFER, WL_NAN_FUNC(scan)
+	},
+	{"scanresults", 0x01, WL_NAN_CMD_DBG_SCAN_RESULTS,
+	IOVT_BUFFER, WL_NAN_FUNC(dbg_scan_results)
+	},
+	{"event_msgs", 0x01, WL_NAN_CMD_DBG_EVENT_MASK,
+	IOVT_BUFFER, WL_NAN_FUNC(event_msgs)
+	},
+	{"dbg", 0x01, WL_NAN_CMD_DBG_LEVEL,
+	IOVT_BUFFER, WL_NAN_FUNC(dbg_level)
+	},
+#if defined(linux)
+	{"event_check", 0x01, WL_NAN_CMD_DBG_EVENT_CHECK,
+	IOVT_BUFFER, WL_NAN_FUNC(event_check)
+	},
+#endif
+	{"dump", 0x01, WL_NAN_CMD_DBG_DUMP,
+	IOVT_BUFFER, WL_NAN_FUNC(dump),
+	},
+	{"clear", 0x01, WL_NAN_CMD_DBG_CLEAR,
+	IOVT_BUFFER, WL_NAN_FUNC(clear),
+	},
+	/* uses same cmd handler for as status */
+	{"rssi", 0x01, WL_NAN_CMD_DBG_RSSI,
+	IOVT_BUFFER, WL_NAN_FUNC(dbg_rssi)
+	},
+	{"disc_results", 0x01, WL_NAN_CMD_DBG_DISC_RESULTS,
+	IOVT_BUFFER, WL_NAN_FUNC(disc_results)
+	},
+	/* nan2.0 data iovars */
+	{"dp_cap", 0x01, WL_NAN_CMD_DATA_CAP,
+	IOVT_BUFFER, WL_NAN_FUNC(dp_cap)
+	},
+	{"dp_autoconn", 0x01, WL_NAN_CMD_DATA_AUTOCONN,
+	IOVT_BUFFER, WL_NAN_FUNC(dp_autoconn)
+	},
+	{"dp_req", 0x01, WL_NAN_CMD_DATA_DATAREQ,
+	IOVT_BUFFER, WL_NAN_FUNC(dp_req)
+	},
+	{"dp_resp", 0x01, WL_NAN_CMD_DATA_DATARESP,
+	IOVT_BUFFER, WL_NAN_FUNC(dp_resp)
+	},
+	{"dp_conf", 0x01, WL_NAN_CMD_DATA_DATACONF,
+	IOVT_BUFFER, WL_NAN_FUNC(dp_conf)
+	},
+	{"dp_end", 0x01, WL_NAN_CMD_DATA_DATAEND,
+	IOVT_BUFFER, WL_NAN_FUNC(dp_dataend)
+	},
+	{"dp_status", 0x01, WL_NAN_CMD_DATA_STATUS,
+	IOVT_BUFFER, WL_NAN_FUNC(dp_status)
+	},
+	{"dp_stats", 0x01, WL_NAN_CMD_DATA_STATS,
+	IOVT_BUFFER, WL_NAN_FUNC(dp_stats)
+	},
+	{"dp_schedupd", 0x01, WL_NAN_CMD_DATA_SCHEDUPD,
+	IOVT_BUFFER, WL_NAN_FUNC(dp_schedupd)
+	},
+	{"dp_show", 0x01, WL_NAN_CMD_DATA_NDP_SHOW,
+	IOVT_BUFFER, WL_NAN_FUNC(dp_show)
+	},
+	{"range_req", 0x01, WL_NAN_CMD_RANGE_REQUEST,
+	IOVT_BUFFER, WL_NAN_FUNC(range_req)
+	},
+	{"range_auto", 0x01, WL_NAN_CMD_RANGE_AUTO,
+	IOVT_BUFFER, WL_NAN_FUNC(range_auto)
+	},
+	{"range_resp", 0x01, WL_NAN_CMD_RANGE_RESPONSE,
+	IOVT_BUFFER, WL_NAN_FUNC(range_resp)
+	},
+	{"range_cncl", 0x01, WL_NAN_CMD_RANGE_CANCEL,
+	IOVT_BUFFER, WL_NAN_FUNC(range_cancel)
+	},
+	{NULL, 0, 0, 0, NULL}
+};
+
+#define NAN_HELP_ALL 0
+#define WL_NAN_HELP_FUNC(suffix) wl_nan_help_ ##suffix
+
+/*  nan ioctl sub cmd handler functions  */
+static cmd_help_handler_t wl_nan_help_cfg_enable;
+static cmd_help_handler_t wl_nan_help_sd_transmit;
+static cmd_help_handler_t wl_nan_help_sd_publish;
+static cmd_help_handler_t wl_nan_help_sd_cancel_publish;
+static cmd_help_handler_t wl_nan_help_sd_publish_list;
+static cmd_help_handler_t wl_nan_help_sd_subscribe;
+static cmd_help_handler_t wl_nan_help_sd_cancel_subscribe;
+static cmd_help_handler_t wl_nan_help_sd_subscribe_list;
+static cmd_help_handler_t wl_nan_help_cfg_avail;
+static cmd_help_handler_t wl_nan_help_dp_req;
+static cmd_help_handler_t wl_nan_help_dp_resp;
+static cmd_help_handler_t wl_nan_help_dp_conf;
+static cmd_help_handler_t wl_nan_help_dp_end;
+static cmd_help_handler_t wl_nan_help_cfg_wfa_testmode;
+
+static const wl_nan_cmd_help_t nan_cmd_help_list[] = {
+	/* wl nan enable [0/1] or new: "wl nan [0/1]" */
+	{WL_NAN_CMD_CFG_ENABLE, WL_NAN_HELP_FUNC(cfg_enable)},
+	{WL_NAN_CMD_SD_FUP_TRANSMIT, WL_NAN_HELP_FUNC(sd_transmit)},
+	{WL_NAN_CMD_SD_TRANSMIT, WL_NAN_HELP_FUNC(sd_transmit)},
+	{WL_NAN_CMD_SD_PUBLISH, WL_NAN_HELP_FUNC(sd_publish)},
+	{WL_NAN_CMD_SD_CANCEL_PUBLISH, WL_NAN_HELP_FUNC(sd_cancel_publish)},
+	{WL_NAN_CMD_SD_PUBLISH_LIST, WL_NAN_HELP_FUNC(sd_publish_list)},
+	{WL_NAN_CMD_SD_SUBSCRIBE, WL_NAN_HELP_FUNC(sd_subscribe)},
+	{WL_NAN_CMD_SD_CANCEL_SUBSCRIBE, WL_NAN_HELP_FUNC(sd_cancel_subscribe)},
+	{WL_NAN_CMD_SD_SUBSCRIBE_LIST, WL_NAN_HELP_FUNC(sd_subscribe_list)},
+	{WL_NAN_CMD_CFG_AVAIL, WL_NAN_HELP_FUNC(cfg_avail)},
+	{WL_NAN_CMD_DATA_DATAREQ, WL_NAN_HELP_FUNC(dp_req)},
+	{WL_NAN_CMD_DATA_DATARESP, WL_NAN_HELP_FUNC(dp_resp)},
+	{WL_NAN_CMD_DATA_DATACONF, WL_NAN_HELP_FUNC(dp_conf)},
+	{WL_NAN_CMD_DATA_DATAEND, WL_NAN_HELP_FUNC(dp_end)},
+	{WL_NAN_CMD_CFG_WFA_TM, WL_NAN_HELP_FUNC(cfg_wfa_testmode)},
+	{0, NULL}
+};
+
+void
+wl_nan_help_cfg_enable(void)
+{
+	printf("wl nan enable [<1|0>]\n");
+	printf("\t1: Enable\n\t0: Disable\n");
+}
+
+void
+wl_nan_help_sd_transmit(void)
+{
+	printf("wl nan followup_transmit lcl-inst <local-instance-id> "
+		"remote-inst <remote-instance-id> dest-mac <destination MAC>\n");
+}
+
+void
+wl_nan_help_sd_publish(void)
+{
+	printf("\t\twl nan publish [instance] [service name] [options] - get/set\n");
+}
+
+void
+wl_nan_help_sd_cancel_publish(void)
+{
+	printf("\t\twl nan cancel_publish [..]\n");
+}
+
+void
+wl_nan_help_sd_publish_list(void)
+{
+	printf("\t\twl nan publish_list [..]\n");
+}
+
+void
+wl_nan_help_sd_subscribe(void)
+{
+	printf("\t\twl nan subscribe [instance] [service name] [options]\n");
+}
+
+void
+wl_nan_help_sd_cancel_subscribe(void)
+{
+	printf("\t\twl nan cancel_subscribe [..]\n");
+}
+
+void
+wl_nan_help_sd_subscribe_list(void)
+{
+	printf("\t\twl nan subscribe_list [..]\n");
+}
+
+void
+wl_nan_help_cfg_avail(void)
+{
+	printf("\twl nan avail <avail type> entry <entry type> [bitmap | otahexmap <>] ");
+	printf("[optional params] [entry...]\n\n");
+	printf("\tMandatory params\n");
+	printf("\t\t<avail type> 1=local, 2=peer, 3=ndc base sched, 4=immutable, ");
+	printf("5=response, 6=counter, 7=ranging\n");
+	printf("\t\t<entry type> 1=committed, 2=potential, 4=conditional\n");
+	printf("\tOptional params\n");
+	printf("\t\t[bitdur <0=16TU(default), 1=32TU, 2=64TU, 3=128TU>]\n");
+	printf("\t\t[period <0=non-repeatable, 1=128TU, 2=256TU, 3=512TU(default), ");
+	printf("4=1024TU, 5=2048TU, 6=4096TU, 7=8192TU>]\n");
+	printf("\t\t[offset <0 - 511>] default = 0\n");
+	printf("\t\t[usage <0-3>] default = 3\n");
+	printf("\t\t[ndc <ether addr format>] default = AA:BB:CC:00:00:00, ");
+	printf("ndc id for ndc base sched avail\n");
+	printf("\t\t[chanspec | band <chanspec or band id>] default = 0, ");
+	printf("which means all bands/chanspec are supported\n");
+	printf("\t\t[peer <ether addr format>] default = 00:90:4c:AA:BB:CC, ");
+	printf("peer nmi address for peer avail\n");
+}
+
+void
+wl_nan_help_dp_req(void)
+{
+	printf("\twl nan dp_req ucast/mcast pub_id <publisher id> [confirm] peer_mac"
+		"<peer mac address> [mcast_mac <if dest multicast addr exists>] qos"
+		"<tid, pkt_size, mean_data_rate, max_service_interval> [security <val>]"
+		"[svc_spec_info <app specific info in hex>]\n");
+}
+
+void
+wl_nan_help_dp_resp(void)
+{
+	printf("\twl nan dp_resp ucast/mcast ndp_id <ndp id/ mc_id for unicast or multicast>"
+		"peer_mac<peer mac address> mcast_mac <if dest multicast addr exists>"
+		"qos <tid, pkt_size, mean_data_rate, max_service_interval> security <val>"
+		"svc_spec_info <app specific info in hex>\n");
+}
+
+void
+wl_nan_help_dp_conf(void)
+{
+	printf("\twl nan dp_conf <ndp id> <status>\n");
+}
+
+void
+wl_nan_help_dp_end(void)
+{
+	printf("\twl nan dp_end <ndp id> <status>\n");
+}
+
+void
+wl_nan_help_cfg_wfa_testmode(void)
+{
+	printf("\twl nan wfa_testmode [<flags>]\n");
+	printf("\t\t<flags> for wfa testmode operation\n");
+	printf("\t\t0x00000001 ignore NDP terminate AF\n");
+	printf("\t\t0x00000002 ignore rx'ed data frame outside NDL CRBs\n");
+	printf("\t\t0x00000004 allow tx data frame outside NDL CRBs\n");
+	printf("\t\t0x00000008 enforce NDL counter proposal\n");
+}
+
+static char *
+bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
+{
+	static const char hex[] =
+	  {
+		  '0', '1', '2', '3', '4', '5', '6', '7',
+		  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+	  };
+	const uint8 *octet = ea->octet;
+	char *p = buf;
+	int i;
+	for (i = 0; i < 6; i++, octet++) {
+		*p++ = hex[(*octet >> 4) & 0xf];
+		*p++ = hex[*octet & 0xf];
+		*p++ = ':';
+	}
+	*(p-1) = '\0';
+	return (buf);
+}
+void print_nan_role(uint32 role)
+{
+	const char *msg = "";
+	if (role == WL_NAN_ROLE_AUTO) {
+		msg = "auto";
+	} else
+	if (role == WL_NAN_ROLE_NON_MASTER_NON_SYNC) {
+		msg = "non-master-non-sync";
+	} else
+	if (role == WL_NAN_ROLE_NON_MASTER_SYNC) {
+		msg = "non-master-sync";
+	} else
+	if (role == WL_NAN_ROLE_MASTER) {
+		msg = "master";
+	} else
+	if (role == WL_NAN_ROLE_ANCHOR_MASTER) {
+		msg = "anchor-master";
+	} else {
+		msg = "undefined";
+	}
+	printf("> role %d: %s\n", role, msg);
+}
+
+static void
+get_nan_band(char *str, uint8 band)
+{
+	if (band == NAN_BAND_B)
+		memcpy(str, "b", sizeof("b"));
+	else if (band == NAN_BAND_A)
+		memcpy(str, "a", sizeof("a"));
+	else if (band == NAN_BAND_AUTO)
+		memcpy(str, "auto", WL_NAN_BAND_STR_SIZE);
+}
+
+static uint8
+set_nan_band(char *str)
+{
+	uint8 nan_band = NAN_BAND_INVALID;
+	if (!strcmp("a", str))
+		nan_band = NAN_BAND_A;
+	else if (!strcmp("b", str))
+		nan_band = NAN_BAND_B;
+	else if (!strcmp("auto", str))
+		nan_band = NAN_BAND_AUTO;
+
+	return nan_band;
+}
+
+static char *
+get_nan_cmd_name(uint16 cmd_id)
+{
+	const wl_nan_sub_cmd_t *nancmd = &nan_cmd_list[0];
+
+	while (nancmd->name != NULL) {
+		if (nancmd->id == cmd_id) {
+			return nancmd->name;
+		}
+		nancmd++;
+	}
+	return NULL;
+}
+
+static void
+wl_nan_print_status(wl_nan_cfg_status_t *nstatus)
+{
+	printf("> enabled:%d\n", nstatus->enabled);
+	printf("> inited:%d\n", nstatus->inited);
+	printf("> joined:%d\n", nstatus->joined);
+	bcm_ether_ntoa(&nstatus->cid, buf);
+	printf("> cluster_id: %s\n", buf);
+
+	nstatus->chspec[0] = dtoh16(nstatus->chspec[0]);
+	if (wf_chspec_valid(nstatus->chspec[0])) {
+		wf_chspec_ntoa(nstatus->chspec[0], buf);
+		printf("> chanspec[0]:%s 0x%x\n", buf,
+				nstatus->chspec[0]);
+	} else {
+		printf("> chanspec[0]: invalid  0x%x\n",
+				nstatus->chspec[0]);
+	}
+
+	nstatus->chspec[1] = dtoh16(nstatus->chspec[1]);
+	if (wf_chspec_valid(nstatus->chspec[1])) {
+		wf_chspec_ntoa(nstatus->chspec[1], buf);
+		printf("> chanspec[1]:%s 0x%x\n", buf,
+				nstatus->chspec[1]);
+	} else {
+		printf("> chanspec[1]: invalid  0x%x\n",
+				nstatus->chspec[1]);
+	}
+	print_nan_role(nstatus->role);
+	prhex("> master_rank:", nstatus->mr, NAN_MASTER_RANK_LEN);
+	prhex("> amr", nstatus->amr, NAN_MASTER_RANK_LEN);
+	printf("> hop_count:%d\n", nstatus->hop_count);
+	printf("> ambtt:%d\n", nstatus->ambtt);
+	printf("> cnt_pend_txfrm:%d\n",
+			dtoh32(nstatus->cnt_pend_txfrm));
+	printf("> cnt_bcn_tx:%d\n",
+			dtoh32(nstatus->cnt_bcn_tx));
+	printf("> cnt_bcn_rx:%d\n",
+			dtoh32(nstatus->cnt_bcn_rx));
+	printf("> cnt_svc_disc_tx:%d\n",
+			dtoh32(nstatus->cnt_svc_disc_tx));
+	printf("> cnt_svc_disc_rx:%d\n",
+			dtoh32(nstatus->cnt_svc_disc_rx));
+}
+
+static void
+wlu_nan_print_wl_avail_entry(uint8 avail_type, wl_avail_entry_t* entry)
+{
+	wl_avail_entry_t* e = entry;
+	uint16 eflags = (ltoh_ua(&e->flags));
+	int j, k;
+	uint8 tmp;
+
+	prhex("\n Entry", (uchar*)e, e->length);
+	if (avail_type < WL_AVAIL_NDC) {
+		printf("   Avail type (1=committed, 2=potential, 4=conditional): ");
+		printf("%d\n", eflags & (WL_AVAIL_ENTRY_COM | WL_AVAIL_ENTRY_POT |
+			WL_AVAIL_ENTRY_COND));
+		if (eflags & WL_AVAIL_ENTRY_BAND_PRESENT) {
+			printf("   Band: %d\n", ltoh_ua(&e->u.band));
+		} else if (eflags & WL_AVAIL_ENTRY_CHAN_PRESENT) {
+			printf("   Chanspec: 0x%x\n", ltoh_ua(&e->u.channel_info));
+		} else {
+			printf("   Support all bands and channels\n");
+		}
+		printf("   Flags: 0x%04x, Usage pref: %d \n", eflags,
+			WL_AVAIL_ENTRY_USAGE_VAL(eflags));
+	}
+	if (e->bitmap_len) {
+		printf("   Start offset: %d TU | Period: %d TU | Bit dur: %d TU\n",
+			16 * (ltoh_ua(&e->start_offset)),
+			(e->period ? 128 << (e->period - 1) : 0),
+			16 << (WL_AVAIL_ENTRY_BIT_DUR_VAL(ltoh_ua(&e->flags))));
+		printf("   Time bitmap (b0b1...): ");
+		for (j = 0; j < e->bitmap_len; j++) {
+			if ((uint8*)(e->bitmap + j)) {
+				tmp = *((uint8*)(e->bitmap + j));
+				for (k = 0; k < NBBY; k++) {
+					printf("%d", (tmp & 1) ? 1 : 0);
+					tmp >>= 1;
+				}
+			}
+		}
+		printf("\n");
+	} else {
+		printf("   No time bitmap: availabile on all time slots\n");
+	}
+}
+
+/*
+ *  a cbfn function, displays bcm_xtlv variables rcvd in get ioctl's xtlv buffer.
+ *  it can process GET result for all nan commands, provided that
+ *  XTLV types (AKA the explicit xtlv types) packed into the ioctl buff
+ *  are unique across all nan ioctl commands
+ */
+static int
+wlu_nan_set_vars_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
+{
+	int res = BCME_OK;
+	bcm_iov_batch_buf_t *b_resp = (bcm_iov_batch_buf_t *)ctx;
+	uint8	uv8;
+	int32 status;
+	uint16 cmd_rsp_len;
+	char *cmd_name;
+	char band_str[WL_NAN_BAND_STR_SIZE];
+
+	/*  cbfn params may be used in f/w */
+	if (len < sizeof(status)) {
+		return BCME_ERROR;
+	}
+
+	/* first 4 bytes consists status */
+	status = dtoh32(*(uint32 *)data);
+
+	data = data + sizeof(status);
+	cmd_rsp_len = len - sizeof(status);
+
+	if (b_resp->count == 0) {
+		/* No more tlvs to parse */
+		return BCME_OK;
+	}
+	/* If status is non zero */
+	if (status != BCME_OK) {
+		if ((cmd_name = get_nan_cmd_name(type)) == NULL) {
+			printf("Undefined command type %04x len %04x\n", type, len);
+		} else {
+			printf("%s failed, status: %04x\n", cmd_name, status);
+		}
+		return status;
+	}
+
+	/* Every response expects some data, return error if there is no data */
+	if (!cmd_rsp_len) {
+		return BCME_ERROR;
+	}
+
+	switch (type) {
+	case WL_NAN_CMD_CFG_ENABLE:
+	{
+		uv8 = *data;
+
+		printf("> nan: %s\n", uv8?"enabled":"disabled");
+		break;
+	}
+	case WL_NAN_CMD_DATA_DATAREQ:
+	{
+		wl_nan_dp_req_ret_t *dpreq_ret = (wl_nan_dp_req_ret_t *)data;
+
+		printf("> ndp_id: %d\n", (dpreq_ret->ndp_id));
+		bcm_ether_ntoa(&dpreq_ret->indi, buf);
+		printf("> ndi: %s\n", buf);
+		break;
+	}
+	case WL_NAN_CMD_DATA_DATARESP:
+	{
+		wl_nan_dp_resp_ret_t *dpresp_ret = (wl_nan_dp_resp_ret_t *)data;
+
+		printf("> nmsgid: %d\n", (dpresp_ret->nmsgid));
+		break;
+	}
+	case WL_NAN_CMD_RANGE_REQUEST:
+	{
+		wl_nan_range_id *range_id = (wl_nan_range_id *)data;
+		printf("> range_id %d\n", *range_id);
+		break;
+	}
+	case WL_NAN_CMD_ELECTION_MERGE:
+	{
+		uv8 = *data;
+
+		printf("> merge: %s\n", uv8?"enabled":"disabled");
+		break;
+	}
+	case WL_NAN_CMD_CFG_HOP_LIMIT:
+	{
+		uv8 = *data;
+
+		printf("> hop limit: %d\n", uv8);
+		break;
+	}
+	case WL_NAN_CMD_CFG_OUI:
+	{
+		wl_nan_oui_type_t *nan_oui_type = (wl_nan_oui_type_t *)data;
+
+		printf("> NAN OUI, type: \n");
+		printf("\tOUI %02X-%02X-%02X type %02X\n", nan_oui_type->nan_oui[0],
+				nan_oui_type->nan_oui[1], nan_oui_type->nan_oui[2],
+				nan_oui_type->type);
+		break;
+	}
+	case WL_NAN_CMD_CFG_CLEARCOUNT:
+	{
+		wl_nan_count_t *ncount = (wl_nan_count_t *)data;
+
+		printf("> NAN Counter:");
+		printf("\tnan_bcn_tx %d", dtoh32(ncount->cnt_bcn_tx));
+		printf("\tnan_bcn_rx %d", dtoh32(ncount->cnt_bcn_rx));
+		printf("\tnan_svc_disc_tx %d",
+				dtoh32(ncount->cnt_svc_disc_tx));
+		printf("\tnan_svc_disc_rx %d\n",
+				dtoh32(ncount->cnt_svc_disc_rx));
+		break;
+	}
+	case WL_NAN_CMD_CFG_RSSI_THRESHOLD:
+	{
+		wl_nan_rssi_threshold_t *rssi_threshold = (wl_nan_rssi_threshold_t *)data;
+
+		get_nan_band(band_str, *data);
+		printf("> nan band : %s\n", band_str);
+		printf("\trssi close : %d\n", rssi_threshold->rssi_close);
+		printf("\trssi mid : %d\n", rssi_threshold->rssi_mid);
+		break;
+	}
+	case WL_NAN_CMD_CFG_AWAKE_DW:
+	{
+		wl_nan_awake_dw_t *awake_dw = (wl_nan_awake_dw_t *)data;
+
+		get_nan_band(band_str, *data);
+		printf("> nan band : %s\n", band_str);
+		printf("\t DW Awake interval : %d\n", awake_dw->interval);
+		break;
+	}
+	case WL_NAN_CMD_ELECTION_METRICS_STATE:
+	{
+		wl_nan_election_metric_state_t *metric_state;
+		metric_state = (wl_nan_election_metric_state_t *)data;
+
+		printf("> Election metrics:\n");
+		printf("\tmaster preference:%d\n", metric_state->master_pref);
+		printf("\trandom factor:%d\n", metric_state->random_factor);
+		break;
+	}
+	case WL_NAN_CMD_DBG_DUMP:
+	{
+		wl_nan_dbg_dump_rsp_t *dump_rsp = (wl_nan_dbg_dump_rsp_t *)data;
+
+		if (dump_rsp->dump_type == WL_NAN_DBG_DT_STATS_DATA) {
+			wl_nan_stats_t *nan_stats = &dump_rsp->u.nan_stats;
+
+			printf("DWSlots: %u \t",
+					dtoh32(nan_stats->cnt_dw));
+			printf("DiscBcnSlots: %u\t",
+					dtoh32(nan_stats->cnt_disc_bcn_sch));
+			printf("AnchorMasterRecExp: %u\t",
+					dtoh32(nan_stats->cnt_amr_exp));
+			printf("BcnTpltUpd: %u\n",
+					dtoh32(nan_stats->cnt_bcn_upd));
+			printf("BcnTx: %u\t",
+					dtoh32(nan_stats->cnt_bcn_tx));
+			printf("SyncBcnTx: %u\t",
+					dtoh32(nan_stats->cnt_sync_bcn_tx));
+			printf("DiscBcnTx: %u\t",
+					dtoh32(nan_stats->cnt_disc_bcn_tx));
+			printf("BcnRx: %u\t",
+					dtoh32(nan_stats->cnt_bcn_rx));
+			printf("SyncBcnRx: %u\t",
+					dtoh32(nan_stats->cnt_sync_bcn_rx));
+			printf("DiscBcnRx: %u\n",
+					dtoh32(nan_stats->cnt_bcn_rx) -
+					dtoh32(nan_stats->cnt_sync_bcn_rx));
+			printf("SdfTx -> BcMc: %u  Ucast: %u UcFail: %u\t",
+					dtoh32(nan_stats->cnt_sdftx_bcmc),
+					dtoh32(nan_stats->cnt_sdftx_uc),
+					dtoh32(nan_stats->cnt_sdftx_fail));
+			printf("SDFRx: %u\n",
+					dtoh32(nan_stats->cnt_sdf_rx));
+			printf("Roles -> AnchorMaster: %u\t",
+					dtoh32(nan_stats->cnt_am));
+			printf("Master: %u\t",
+					dtoh32(nan_stats->cnt_master));
+			printf("NonMasterSync: %u\t",
+					dtoh32(nan_stats->cnt_nms));
+			printf("NonMasterNonSync: %u\n",
+					dtoh32(nan_stats->cnt_nmns));
+			printf("UnschTx: %u\t",
+					dtoh32(nan_stats->cnt_err_unsch_tx));
+			printf("BcnTxErr: %u\t",
+					dtoh32(nan_stats->cnt_err_bcn_tx));
+			printf("SyncBcnTxMiss: %u\t",
+					dtoh32(nan_stats->cnt_sync_bcn_tx_miss));
+			printf("SyncBcnTxtimeErr: %u\n",
+					dtoh32(nan_stats->cnt_err_txtime));
+			printf("MschRegErr: %u\t",
+					dtoh32(nan_stats->cnt_err_msch_reg));
+			printf("WrongChCB: %u\t",
+					dtoh32(nan_stats->cnt_err_wrong_ch_cb));
+			printf("DWEarlyCB: %u\t",
+					dtoh32(nan_stats->cnt_dw_start_early));
+			printf("DWLateCB: %u\t",
+					dtoh32(nan_stats->cnt_dw_start_late));
+			printf("DWSkips: %u\t", dtoh16(nan_stats->cnt_dw_skip));
+			printf("DiscBcnSkips: %u\n",
+					dtoh16(nan_stats->cnt_disc_skip));
+			printf("MrgScan: %u\t",
+					dtoh32(nan_stats->cnt_mrg_scan));
+			printf("MrgScanRej: %u\t",
+					dtoh32(nan_stats->cnt_err_ms_rej));
+			printf("JoinScanRej: %u\t",
+					dtoh32(nan_stats->cnt_join_scan_rej));
+			printf("NanScanAbort: %u\t",
+					dtoh32(nan_stats->cnt_nan_scan_abort));
+			printf("ScanRes: %u\t",
+					dtoh32(nan_stats->cnt_scan_results));
+			printf("NanEnab: %u\t",
+					dtoh32(nan_stats->cnt_nan_enab));
+			printf("NanDisab: %u\n",
+					dtoh32(nan_stats->cnt_nan_disab));
+		} else if (dump_rsp->dump_type == WL_NAN_DBG_DT_RSSI_DATA) {
+			wl_nan_peer_rssi_data_t *prssi = &dump_rsp->u.peer_rssi;
+
+			print_peer_rssi(prssi);
+		}
+	}
+	break;
+	case WL_NAN_CMD_ELECTION_HOST_ENABLE:
+	{
+		uv8 = *data;
+
+		printf("> nan host: %s\n", uv8?"enabled":"disabled");
+		break;
+	}
+	case WL_NAN_CMD_DBG_LEVEL:
+	{
+		wl_nan_dbg_level_t *dbg_level = (wl_nan_dbg_level_t *)data;
+
+		printf("> nan_err_level : 0x%x\n> nan_dbg_level : 0x%x\n> nan_info_level : 0x%x\n ",
+			dtoh32(dbg_level->nan_err_level), dtoh32(dbg_level->nan_dbg_level),
+			dtoh32(dbg_level->nan_info_level));
+		break;
+	}
+	case WL_NAN_CMD_CFG_STATE:
+	{
+		wl_nan_role_config_t* r = (wl_nan_role_config_t*)data;
+
+		printf("> nan role/state : %d\n", r->role);
+		bcm_ether_ntoa(&r->target_master, buf);
+		printf("> target master: %s\n", buf);
+		break;
+	}
+	case WL_NAN_CMD_CFG_HOP_CNT:
+	{
+		uv8 = *data;
+
+		printf("> nan hop_cnt : %d\n", uv8);
+		break;
+	}
+	case WL_NAN_CMD_CFG_WARMUP_TIME:
+	{
+		printf("> nan warm up time : %d\n", dtoh16(*(uint16*)data));
+		break;
+	}
+	case WL_NAN_CMD_CFG_COUNT:
+	{
+		wl_nan_count_t *ncount = (wl_nan_count_t *)data;
+
+		printf("> NAN Counter:");
+		printf("\tnan_bcn_tx %d", dtoh32(ncount->cnt_bcn_tx));
+		printf("\tnan_bcn_rx %d", dtoh32(ncount->cnt_bcn_rx));
+		printf("\tnan_svc_disc_tx %d",
+				dtoh32(ncount->cnt_svc_disc_tx));
+		printf("\tnan_svc_disc_rx %d\n",
+				dtoh32(ncount->cnt_svc_disc_rx));
+
+		break;
+	}
+	case WL_NAN_CMD_CFG_STATUS:
+	{
+		wl_nan_cfg_status_t *nstatus = (wl_nan_cfg_status_t *)data;
+
+		wl_nan_print_status(nstatus);
+		break;
+	}
+	case WL_NAN_CMD_SYNC_TSRESERVE:
+	{
+		wl_nan_timeslot_t *tsp = (wl_nan_timeslot_t *)data;
+		int i;
+
+		printf("Bitmap 0x%08x\n", dtoh32(tsp->abitmap));
+		for (i = 0; i < NAN_MAX_TIMESLOT; i++) {
+			if (dtoh32(tsp->abitmap) & (1 << i)) {
+				printf("Slot %d Chanspec %x\n",
+						i, dtoh32(tsp->chanlist[i]));
+			}
+		}
+	}
+	break;
+	case WL_NAN_CMD_CFG_CID:
+	{
+		wl_nan_cluster_id_t *clid = (wl_nan_cluster_id_t *)data;
+		prhex("> Cluster-id:", (uint8 *)clid, ETHER_ADDR_LEN);
+	}
+	break;
+	case WL_NAN_CMD_CFG_IF_ADDR:
+	{
+		struct ether_addr *ea;
+
+		ea = (struct ether_addr *)data;
+		bcm_ether_ntoa(ea, buf);
+		printf("> if_addr: %s\n", buf);
+	}
+	break;
+	case WL_NAN_CMD_CFG_BCN_INTERVAL:
+	{
+		wl_nan_disc_bcn_interval_t bcn_interval;
+		bcn_interval = dtoh16(*(uint16 *)data);
+		printf("BCN interval = %d\n", bcn_interval);
+	}
+	break;
+	case WL_NAN_CMD_CFG_SDF_TXTIME:
+	{
+		wl_nan_svc_disc_txtime_t sdf_txtime;
+		sdf_txtime = dtoh16(*(uint16 *)data);
+		printf("SDF TXTIME = %d\n", sdf_txtime);
+	}
+	break;
+	case WL_NAN_CMD_CFG_STOP_BCN_TX:
+	{
+		wl_nan_stop_bcn_tx_t stop_bcn_tx;
+		stop_bcn_tx = dtoh16(*(uint16*)data);
+		printf("Stop bcn tx = %d\n", stop_bcn_tx);
+	}
+	break;
+	case WL_NAN_CMD_CFG_SID_BEACON:
+	{
+		wl_nan_sid_beacon_control_t *sid_bcn;
+		sid_bcn = (wl_nan_sid_beacon_control_t *)data;
+
+		printf("> SID beacon ctrl info:\n");
+		printf("\tsid: %s", sid_bcn->sid_enable?"enabled":"disabled");
+		printf("\tsid limit count: %d\n", sid_bcn->sid_count);
+	}
+	break;
+	case WL_NAN_CMD_CFG_DW_LEN:
+	{
+		wl_nan_dw_len_t dw_len;
+
+		dw_len = dtoh16(*(uint16 *)data);
+		printf("DW_LEN = %d\n", dw_len);
+	}
+	break;
+	case WL_NAN_CMD_CFG_AVAIL:
+	{
+		wl_avail_new_t *a = (wl_avail_new_t*)data;
+		wl_avail_entry_t *e;
+		uint8* p = (uint8*)a->entry;
+		uint16 flags = dtoh16(a->flags);
+		int i;
+		if (!a->length) {
+			break;
+		}
+		printf("\nType (1=local, 2=peer, 3=ndc, 4=immutable, 5=response, "
+			"6=counter, 7=ranging): %d\n", flags);
+		if (flags == WL_AVAIL_NDC) {
+			prhex("ndc id", (uint8 *)&a->u.addr, ETHER_ADDR_LEN);
+		}
+		for (i = 0; i < a->num_entries; i++) {
+			e = (wl_avail_entry_t*)p;
+			wlu_nan_print_wl_avail_entry(flags & WL_AVAIL_TYPE_MASK, e);
+			p += e->length;
+		}
+		break;
+	}
+	case WL_NAN_CMD_CFG_WFA_TM:
+	{
+		wl_nan_wfa_testmode_t flags;
+
+		flags = dtoh32(*(uint32 *)data);
+		printf("flag: 0x%08x\n", flags);
+
+		if (flags & WL_NAN_WFA_TM_IGNORE_TERMINATE_NAF) {
+			printf("\t0x00000001 ignore NDP terminate AF\n");
+		}
+		if (flags & WL_NAN_WFA_TM_IGNORE_RX_DATA_OUTSIDE_CRB) {
+			printf("\t0x00000002 ignore rx'ed data frame outside NDL CRBs\n");
+		}
+		if (flags & WL_NAN_WFA_TM_ALLOW_TX_DATA_OUTSIDE_CRB) {
+			printf("\t0x00000004 allow tx data frame outside NDL CRBs\n");
+		}
+		if (flags & WL_NAN_WFA_TM_ENFORCE_NDL_COUNTER) {
+			printf("\t0x00000008 enforce NDL counter proposal\n");
+		}
+	}
+	break;
+	case WL_NAN_CMD_SD_PARAMS:
+	case WL_NAN_CMD_SD_PUBLISH:
+	case WL_NAN_CMD_SD_SUBSCRIBE:
+	{
+		wl_nan_sd_params_t *sd_params = (wl_nan_sd_params_t *)data;
+		uint16 flags;
+
+		printf(">Instance ID: %d\n", sd_params->instance_id);
+		printf(">Length: %d\n", dtoh16(sd_params->length));
+		prhex(">Service Hash:", sd_params->svc_hash,
+				WL_NAN_SVC_HASH_LEN);
+		flags = dtoh16(sd_params->flags);
+		printf(">Flags: 0x%04x\n", flags);
+		if (flags & WL_NAN_PUB_UNSOLICIT) {
+			printf(" unsolicited/active\n");
+		}
+		if (flags & WL_NAN_PUB_SOLICIT) {
+			printf(" solicited\n");
+		}
+		if (!(flags & WL_NAN_PUB_UNSOLICIT) &&
+				!(flags & WL_NAN_PUB_SOLICIT)) {
+			printf(" passive\n");
+		}
+		if (flags & WL_NAN_FOLLOWUP) {
+			printf(" follow-up\n");
+		}
+		printf("\n");
+		printf(">RSSI: %d\n", sd_params->proximity_rssi);
+		printf(">TTL: 0x%08x\n", dtoh32(sd_params->ttl));
+		printf(">Period: %d\n", sd_params->period);
+		break;
+	}
+	case WL_NAN_CMD_SD_PUBLISH_LIST:
+	case WL_NAN_CMD_SD_SUBSCRIBE_LIST:
+	{
+		wl_nan_service_list_t *svc_list = (wl_nan_service_list_t *)data;
+		wl_nan_service_info_t *svc_info = NULL;
+		int i = 0;
+
+		printf("%s\n",
+				(type == WL_NAN_CMD_SD_PUBLISH_LIST) ? ">Publish List" :
+				">Subscribe List");
+		printf(">Count: %d\n", svc_list->id_count);
+		for (i = 0; i < svc_list->id_count; i++) {
+			svc_info = &svc_list->list[i];
+			printf(">Instance ID: %d\n", svc_info->instance_id);
+			prhex(">Service Hash:", svc_info->service_hash,
+					WL_NAN_SVC_HASH_LEN);
+			printf("\n");
+		}
+		break;
+	}
+	case WL_NAN_CMD_DBG_EVENT_MASK:
+	{
+		wl_nan_event_mask_t mask;
+		mask = ltoh32_ua(data);
+		mask = dtoh32(mask);
+		printf("> event_mask: %x\n  %s:%d\n  %s:%d\n  %s:%d\n"
+				"  %s:%d\n  %s:%d\n  %s:%d\n  %s:%d\n  %s:%d\n"
+				"  %s:%d\n %s:%d\n  %s:%d\n %s:%d\n %s:%d\n",
+				mask,
+				"WL_NAN_EVENT_START",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_START),
+				"WL_NAN_EVENT_JOIN",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_JOIN),
+				"WL_NAN_EVENT_ROLE",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_ROLE),
+				"WL_NAN_EVENT_SCAN_COMPLETE",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_SCAN_COMPLETE),
+				"WL_NAN_EVENT_DISCOVERY_RESULT",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_DISCOVERY_RESULT),
+				"WL_NAN_EVENT_REPLIED",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_REPLIED),
+				"WL_NAN_EVENT_TERMINATED",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_TERMINATED),
+				"WL_NAN_EVENT_RECEIVE",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_RECEIVE),
+				"WL_NAN_EVENT_STATUS_CHG",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_STATUS_CHG),
+				"WL_NAN_EVENT_MERGE",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_MERGE),
+				"WL_NAN_EVENT_STOP",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_STOP),
+				"WL_NAN_EVENT_P2P",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_P2P),
+				"WL_NAN_EVENT_BCN_RX",
+				IS_NAN_EVT_ON(mask, WL_NAN_EVENT_BCN_RX));
+	}
+	break;
+	case WL_NAN_CMD_DBG_DISC_RESULTS:
+	{
+		wl_nan_disc_results_list_t *p;
+		int i;
+		char hash[WL_NAN_SVC_HASH_LEN+1];
+
+		p = (wl_nan_disc_results_list_t *)data;
+		printf(">Disc results: \n\n");
+		for (i = 0; i < WL_NAN_MAX_DISC_RESULTS; i++) {
+
+			memcpy(hash,
+					p->disc_result[i].svc_hash,
+					WL_NAN_SVC_HASH_LEN);
+
+			hash[WL_NAN_SVC_HASH_LEN] = '\0';
+
+			bcm_ether_ntoa(
+					(struct ether_addr *)
+					&p->disc_result[i].peer_mac,
+					buf);
+
+			printf(">Instance id: 0x%x \n"
+					">Peer instance id: 0x%x \n",
+					p->disc_result[i].instance_id,
+					p->disc_result[i].peer_instance_id);
+			prhex(">Service hash", (uchar *)hash,
+					WL_NAN_SVC_HASH_LEN);
+			printf(">Peer MAC: %s \n\n", buf);
+		}
+	}
+	break;
+	case WL_NAN_CMD_DBG_STATS:
+	{
+		wl_nan_stats_t *nan_stats =
+			(wl_nan_stats_t *)data;
+		printf("DWSlots: %u \t",
+				dtoh32(nan_stats->cnt_dw));
+		printf("DiscBcnSlots: %u\t",
+				dtoh32(nan_stats->cnt_disc_bcn_sch));
+		printf("AnchorMasterRecExp: %u\t",
+				dtoh32(nan_stats->cnt_amr_exp));
+		printf("BcnTpltUpd: %u\n",
+				dtoh32(nan_stats->cnt_bcn_upd));
+		printf("BcnTx: %u\t",
+				dtoh32(nan_stats->cnt_bcn_tx));
+		printf("SyncBcnTx: %u\t",
+				dtoh32(nan_stats->cnt_sync_bcn_tx));
+		printf("DiscBcnTx: %u\t",
+				dtoh32(nan_stats->cnt_disc_bcn_tx));
+		printf("BcnRx: %u\t",
+				dtoh32(nan_stats->cnt_bcn_rx));
+		printf("SyncBcnRx: %u\t",
+				dtoh32(nan_stats->cnt_sync_bcn_rx));
+		printf("DiscBcnRx: %u\n",
+				dtoh32(nan_stats->cnt_bcn_rx) -
+				dtoh32(nan_stats->cnt_sync_bcn_rx));
+		printf("SdfTx -> BcMc: %u  Ucast: %u UcFail: %u\t",
+				dtoh32(nan_stats->cnt_sdftx_bcmc),
+				dtoh32(nan_stats->cnt_sdftx_uc),
+				dtoh32(nan_stats->cnt_sdftx_fail));
+		printf("SDFRx: %u\n",
+				dtoh32(nan_stats->cnt_sdf_rx));
+		printf("Roles -> AnchorMaster: %u\t",
+				dtoh32(nan_stats->cnt_am));
+		printf("Master: %u\t",
+				dtoh32(nan_stats->cnt_master));
+		printf("NonMasterSync: %u\t",
+				dtoh32(nan_stats->cnt_nms));
+		printf("NonMasterNonSync: %u\n",
+				dtoh32(nan_stats->cnt_nmns));
+		printf("UnschTx: %u\t",
+				dtoh32(nan_stats->cnt_err_unsch_tx));
+		printf("BcnTxErr: %u\t",
+				dtoh32(nan_stats->cnt_err_bcn_tx));
+		printf("SyncBcnTxMiss: %u\t",
+				dtoh32(nan_stats->cnt_sync_bcn_tx_miss));
+		printf("SyncBcnTxtimeErr: %u\n",
+				dtoh32(nan_stats->cnt_err_txtime));
+		printf("MschRegErr: %u\t",
+				dtoh32(nan_stats->cnt_err_msch_reg));
+		printf("WrongChCB: %u\t",
+				dtoh32(nan_stats->cnt_err_wrong_ch_cb));
+		printf("DWEarlyCB: %u\t",
+				dtoh32(nan_stats->cnt_dw_start_early));
+		printf("DWLateCB: %u\t",
+				dtoh32(nan_stats->cnt_dw_start_late));
+		printf("DWSkips: %u\t", dtoh16(nan_stats->cnt_dw_skip));
+		printf("DiscBcnSkips: %u\n",
+				dtoh16(nan_stats->cnt_disc_skip));
+		printf("MrgScan: %u\t",
+				dtoh32(nan_stats->cnt_mrg_scan));
+		printf("MrgScanRej: %u\t",
+				dtoh32(nan_stats->cnt_err_ms_rej));
+		printf("JoinScanRej: %u\t",
+				dtoh32(nan_stats->cnt_join_scan_rej));
+		printf("NanScanAbort: %u\t",
+				dtoh32(nan_stats->cnt_nan_scan_abort));
+		printf("ScanRes: %u\t",
+				dtoh32(nan_stats->cnt_scan_results));
+		printf("NanEnab: %u\t",
+				dtoh32(nan_stats->cnt_nan_enab));
+		printf("NanDisab: %u\n",
+				dtoh32(nan_stats->cnt_nan_disab));
+	}
+	break;
+
+	case WL_NAN_CMD_DATA_NDP_SHOW:
+	{
+		int i = 0;
+		wl_nan_ndp_id_list_t *id_list;
+		id_list = (wl_nan_ndp_id_list_t *)data;
+
+		if (id_list == NULL) {
+			return BCME_ERROR;
+		}
+
+		for (; i < id_list->ndp_count; i++) {
+			printf("%d \t", id_list->lndp_id[i]);
+		}
+		printf("\n");
+	}
+	break;
+
+	case WL_NAN_CMD_DATA_CONFIG:
+	{
+		wl_nan_ndp_config_t *config = (wl_nan_ndp_config_t *)data;
+		int i = 0;
+		printf("ndp_id: %d\tpub_id: %d\ttid: %d\tpkt_size: %d\t"
+				"mean_rate: %d\tsvc_interval: %d\n",
+				config->ndp_id, config->pub_id,
+				config->qos.tid, config->qos.pkt_size,
+				config->qos.mean_rate,
+				config->qos.svc_interval);
+
+
+		bcm_ether_ntoa(&config->pub_addr, buf);
+		printf("pub_addr: %s\n", buf);
+
+		bcm_ether_ntoa(&config->data_addr, buf);
+		printf("data_addr: %s\n", buf);
+
+		for (; i < WL_NAN_DATA_SVC_SPEC_INFO_LEN; i++) {
+			putchar(config->svc_spec_info[i]);
+		}
+		printf("\n");
+
+	}
+	break;
+	case WL_NAN_CMD_DATA_AUTOCONN:
+	{
+		printf("autoconn: %d\n", *data);
+		if (*data & WL_NAN_AUTO_DPRESP) {
+			printf("auto_dpresp enabled \n");
+		} else {
+			printf("auto_dpresp disabled \n");
+		}
+		if (*data & WL_NAN_AUTO_DPCONF) {
+			printf("auto_dpconf enabled \n");
+		} else {
+			printf("auto_dpconf disabled \n");
+		}
+	}
+	break;
+	case WL_NAN_CMD_DATA_SCHEDUPD:
+	break;
+	case WL_NAN_CMD_DATA_CAP:
+	break;
+	case WL_NAN_CMD_DATA_STATUS:
+	{
+		wl_nan_ndp_status_t *status = (wl_nan_ndp_status_t *)data;
+
+		prhex("PEER_NMI", (uint8 *)&status->peer_nmi, ETHER_ADDR_LEN);
+		prhex("PEER_NDI", (uint8 *)&status->peer_ndi, ETHER_ADDR_LEN);
+		printf("lndp_id = %d\n", status->session.lndp_id);
+		printf("state = %d\n", status->session.state);
+		printf("pub_id = %d\n", status->session.pub_id);
+	}
+	break;
+	case WL_NAN_CMD_DATA_STATS:
+	break;
+
+	default:
+	res = BCME_ERROR;
+	break;
+	}
+
+	if (b_resp->count > 0) {
+		b_resp->count--;
+	} else {
+		printf("All subcmd resp tlvs are parsed\n");
+	}
+
+	return res;
+}
+
+/*
+* listens on bcm events on given interface and prints NAN_EVENT data
+* event data is a var size array of bcm_xtlv_t items
+*/
+#if defined(linux)
+static int
+wl_nan_print_event_data_tlvs(void *ctx, const uint8 *data, uint16 type, uint16 len)
+{
+	int err = BCME_OK;
+
+	UNUSED_PARAMETER(ctx);
+
+	switch (type) {
+	case WL_NAN_XTLV_SVC_INFO:
+	{
+		prhex("SVC info", (uint8 *)data, len);
+		break;
+	}
+	case WL_NAN_XTLV_SDF_RX:
+	{
+		prhex("SDF RX", (uint8 *)data, len);
+		break;
+	}
+	default:
+	{
+		printf("Unknown xtlv type received: %x\n", type);
+		err = BCME_ERROR;
+		break;
+	}
+	}
+
+	return err;
+}
+
+static int
+wl_nan_print_event_data(uint32 nan_evtnum, uint8 *event_data, uint16 data_len)
+{
+	uint16 tlvs_offset, opt_tlvs_len = 0;
+	uint8 *tlv_buf;
+	int err = BCME_OK;
+
+	switch (nan_evtnum) {
+	case WL_NAN_EVENT_START:
+		/* intentional fall through */
+	case WL_NAN_EVENT_JOIN:
+		/* intentional fall through */
+	case WL_NAN_EVENT_ROLE:
+		/* intentional fall through */
+	case WL_NAN_EVENT_SCAN_COMPLETE:
+		/* intentional fall through */
+	case WL_NAN_EVENT_MERGE:
+		/* intentional fall through */
+	case WL_NAN_EVENT_STOP:
+	{
+		wl_nan_cfg_status_t *nstatus = (wl_nan_cfg_status_t *)event_data;
+
+		wl_nan_print_status(nstatus);
+		break;
+	}
+	case WL_NAN_EVENT_DISCOVERY_RESULT:
+	{
+		wl_nan_ev_disc_result_t *ev_disc_result;
+		ev_disc_result = (wl_nan_ev_disc_result_t *)event_data;
+
+		printf("Publish ID: %d\n", ev_disc_result->pub_id);
+		printf("Subscribe ID: %d\n", ev_disc_result->sub_id);
+
+		bcm_ether_ntoa(&ev_disc_result->pub_mac, buf);
+		printf("Publish MAC addr: %s\n", buf);
+
+		tlvs_offset = OFFSETOF(wl_nan_ev_disc_result_t, opt_tlvs[0]);
+		opt_tlvs_len = data_len - tlvs_offset;
+		break;
+	}
+	case WL_NAN_EVENT_REPLIED:
+	{
+		bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
+		wl_nan_ev_replied_t *evr =
+			(wl_nan_ev_replied_t *)xtlv->data;
+		printf("Publish ID: %d\n", evr->pub_id);
+		bcm_ether_ntoa(&evr->sub_mac, buf);
+		printf("Subscriber MAC addr: %s\n", buf);
+		printf("Subscriber RSSI : %d\n", evr->sub_rssi);
+		printf("Subscriber ID : %d\n", evr->sub_id);
+		break;
+	}
+	case WL_NAN_EVENT_TERMINATED:
+	{
+		bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
+		wl_nan_ev_terminated_t *pev = (wl_nan_ev_terminated_t *)xtlv->data;
+		printf("Instance ID: %d\n", pev->instance_id);
+		printf("Reason: %d\n", pev->reason);
+		printf("Service Type: %d\n", pev->svctype);
+		break;
+	}
+	case WL_NAN_EVENT_RECEIVE:
+	{
+		bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
+		wl_nan_ev_receive_t *ev = (wl_nan_ev_receive_t *)xtlv->data;
+		printf("Local ID: %d\n", ev->local_id);
+		printf("Remote ID: %d\n", ev->remote_id);
+		bcm_ether_ntoa(&ev->remote_addr, buf);
+		printf("Peer MAC addr: %s\n", buf);
+		printf("Peer RSSI : %d\n", ev->fup_rssi);
+		break;
+	}
+	case WL_NAN_EVENT_STATUS_CHG:
+		break;
+	case WL_NAN_EVENT_P2P:
+	{
+		wl_nan_ev_p2p_avail_t *ev_p2p_avail;
+		chanspec_t chanspec;
+		ev_p2p_avail = (wl_nan_ev_p2p_avail_t *)event_data;
+
+		printf("Device Role: %d\n", ev_p2p_avail->dev_role);
+
+		bcm_ether_ntoa(&ev_p2p_avail->sender, buf);
+		printf("Sender MAC addr: %s\n", buf);
+
+		bcm_ether_ntoa(&ev_p2p_avail->p2p_dev_addr, buf);
+		printf("P2P dev addr: %s\n", buf);
+
+		printf("Repeat: %d\n", ev_p2p_avail->repeat);
+		printf("Resolution: %d\n", ev_p2p_avail->resolution);
+		chanspec = dtoh16(ev_p2p_avail->chanspec);
+		if (wf_chspec_valid(chanspec)) {
+			wf_chspec_ntoa(chanspec, buf);
+			printf("> Chanspec:%s 0x%x\n", buf, chanspec);
+		} else {
+			printf("> Chanspec: invalid  0x%x\n", chanspec);
+		}
+		printf("Avail bitmap: 0x%08x\n", dtoh32(ev_p2p_avail->avail_bmap));
+
+		break;
+	}
+	case WL_NAN_EVENT_PEER_DATAPATH_IND:
+	case WL_NAN_EVENT_PEER_DATAPATH_RESP:
+	case WL_NAN_EVENT_PEER_DATAPATH_CONF:
+	case WL_NAN_EVENT_DATAPATH_ESTB:
+	{
+		wl_nan_ev_datapath_cmn_t *event;
+
+		event = (wl_nan_ev_datapath_cmn_t *)event_data;
+		printf("Event type = %d\n", event->type);
+		printf("Status = %d\n", event->status);
+		printf("pub_id = %d\n", event->pub_id);
+		printf("security = %d\n", event->security);
+		if (event->type == NAN_DP_SESSION_UNICAST) {
+			printf("NDPID = %d\n", event->ndp_id);
+			prhex("INITIATOR_NDI", (uint8 *)&event->initiator_ndi,
+					ETHER_ADDR_LEN);
+			prhex("RESPONDOR_NDI", (uint8 *)&event->responder_ndi,
+					ETHER_ADDR_LEN);
+		} else {
+			printf("NDPID = %d\n", event->mc_id);
+			prhex("INITIATOR_NDI", (uint8 *)&event->initiator_ndi,
+					ETHER_ADDR_LEN);
+		}
+		tlvs_offset = OFFSETOF(wl_nan_ev_datapath_cmn_t, opt_tlvs);
+		opt_tlvs_len = data_len - tlvs_offset;
+
+	}
+	break;
+	case WL_NAN_EVENT_DATAPATH_END:
+		break;
+	case WL_NAN_EVENT_SDF_RX:
+	{
+		tlvs_offset = 0;
+		opt_tlvs_len = data_len;
+		break;
+	}
+	case WL_NAN_EVENT_BCN_RX:
+	{
+
+		bcm_xtlv_t *xtlv = (bcm_xtlv_t *)event_data;
+		int ctr = 0;
+		printf("Len	: %d\n", xtlv->len);
+		printf("Beacon Payload \n");
+		for (; ctr < xtlv->len; ctr++) {
+			printf("%02X ", xtlv->data[ctr]);
+			if ((ctr + 1) % 8  == 0)
+				printf("\n");
+		}
+
+	}
+	break;
+	default:
+	{
+		printf("WARNING: unimplemented NAN APP EVENT code:%d\n", nan_evtnum);
+		err = BCME_ERROR;
+	}
+	break;
+	}
+
+	if (opt_tlvs_len) {
+		tlv_buf = event_data + tlvs_offset;
+
+		/* Extract event data tlvs and print their resp in cb fn */
+		err = bcm_unpack_xtlv_buf((void *)&nan_evtnum,
+			(const uint8 *)tlv_buf,
+			opt_tlvs_len, BCM_IOV_CMD_OPT_ALIGN32,
+			wl_nan_print_event_data_tlvs);
+	}
+
+	return err;
+}
+
+static int
+wl_nan_subcmd_event_check(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int fd, err, octets;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	char ifnames[IFNAMSIZ] = {"eth0"};
+	bcm_event_t *event;
+	uint32 nan_evtnum, evt_status;
+	char* data;
+	int event_type;
+	void *nandata;
+
+	uint8 event_inds_mask[WL_EVENTING_MASK_LEN];	/* 128-bit mask */
+	UNUSED_PARAMETER(nandata);
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+	UNUSED_PARAMETER(argc);
+	if (argv[0] == NULL) {
+		printf("<ifname> param is missing\n");
+		return BCME_USAGE_ERROR;
+	}
+	strncpy(ifnames, *argv, (IFNAMSIZ - 1));
+	printf("ifname:%s\n", ifnames);
+	bzero(&ifr, sizeof(ifr));
+	strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+	if ((err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN))) {
+		printf("couldn't read event_msgs\n");
+		return (err);
+	}
+	event_inds_mask[WLC_E_NAN / 8] |= 1 << (WLC_E_NAN % 8);
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		return (err);
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		return -1;
+	}
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get iface:%s index \n", ifr.ifr_name);
+		goto exit1;
+	}
+	bzero(&sll, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		goto exit1;
+	}
+	data = (char*)malloc(NAN_EVENT_BUFFER_SIZE);
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			NAN_EVENT_BUFFER_SIZE);
+		goto exit1;
+	}
+	printf("wating for NAN events on iface:%s\n", ifr.ifr_name);
+	while (1) {
+		uint16 datalen;
+		fflush(stdout);
+		octets = recv(fd, data, NAN_EVENT_BUFFER_SIZE, 0);
+		if (octets <= 0)  {
+			err = -1;
+			printf(".");
+			continue;
+		}
+		event = (bcm_event_t *)data;
+		event_type = ntoh32(event->event.event_type);
+		evt_status = ntoh32(event->event.status);
+		nan_evtnum = ntoh32(event->event.reason);
+		datalen = ntoh32(event->event.datalen);
+		if ((event_type != WLC_E_NAN)) {
+				continue;
+		}
+
+		err = BCME_OK;
+		/*  set ptr to event data body */
+		nandata = &data[sizeof(bcm_event_t)];
+
+		/* printf("nan event_num:%d len :%d\n", nan_evtnum, datalen); */
+		switch (nan_evtnum) {
+		case WL_NAN_EVENT_START:
+			printf("WL_NAN_EVENT_START:\n");
+			break;
+		case WL_NAN_EVENT_JOIN:
+			printf("WL_NAN_EVENT_JOIN:\n");
+			break;
+		case WL_NAN_EVENT_ROLE:
+			printf("WL_NAN_EVENT_ROLE:\n");
+			break;
+		case WL_NAN_EVENT_SCAN_COMPLETE:
+			printf("WL_NAN_EVENT_SCAN_COMPLETE:\n");
+			break;
+		case WL_NAN_EVENT_DISCOVERY_RESULT:
+			printf("WL_NAN_EVENT_DISCOVERY_RESULT:\n");
+			break;
+		case WL_NAN_EVENT_REPLIED:
+			printf("WL_NAN_EVENT_REPLIED:\n");
+			break;
+		case WL_NAN_EVENT_TERMINATED:
+			printf("WL_NAN_EVENT_TERMINATED:\n");
+			break;
+		case WL_NAN_EVENT_RECEIVE:
+			printf("WL_NAN_EVENT_RECEIVE:\n");
+			break;
+		case WL_NAN_EVENT_STATUS_CHG:
+			printf("WL_NAN_EVENT_STATUS_CHG:\n");
+			break;
+		case WL_NAN_EVENT_MERGE:
+			printf("WL_NAN_EVENT_MERGE:\n");
+			break;
+		case WL_NAN_EVENT_STOP:
+			printf("WL_NAN_EVENT_STOP:\n");
+			break;
+		case WL_NAN_EVENT_P2P:
+			printf("WL_NAN_EVENT_P2P:\n");
+			break;
+		case WL_NAN_EVENT_PEER_DATAPATH_IND:
+			printf("WL_NAN_EVENT_PEER_DATAPATH_IND:\n");
+			break;
+		case WL_NAN_EVENT_PEER_DATAPATH_RESP:
+			printf("WL_NAN_EVENT_PEER_DATAPATH_RESP:\n");
+			break;
+		case WL_NAN_EVENT_PEER_DATAPATH_CONF:
+			printf("WL_NAN_EVENT_PEER_DATAPATH_CONF:\n");
+			break;
+		case WL_NAN_EVENT_DATAPATH_ESTB:
+			printf("WL_NAN_EVENT_DATAPATH_ESTB:\n");
+			break;
+		case WL_NAN_EVENT_DATAPATH_END:
+			printf("WL_NAN_EVENT_DATAPATH_END:\n");
+			break;
+		case WL_NAN_EVENT_SDF_RX:
+			printf("WL_NAN_EVENT_SDF_RX:\n");
+			break;
+		case WL_NAN_EVENT_BCN_RX:
+			printf("WL_NAN_EVENT_BCN_RX:\n");
+			break;
+		default:
+			printf("WARNING: unimplemented NAN APP EVENT code:%d\n", nan_evtnum);
+			err = BCME_ERROR;
+			break;
+		}
+		if (evt_status)
+			printf("Event status:-%u\n", evt_status);
+
+		if (err == BCME_OK) {
+			err = wl_nan_print_event_data(nan_evtnum, (uint8 *)nandata, datalen);
+		}
+	}
+	free(data);
+exit1:
+	close(fd);
+	if (!(err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN))) {
+		event_inds_mask[WLC_E_NAN / 8] &= (~(1 << (WLC_E_NAN % 8)));
+		err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN);
+	}
+	fflush(stdout);
+	return (err);
+}
+#endif /* linux */
+
+static int
+process_get_resp_buf(void *iov_resp)
+{
+	int res = BCME_OK;
+	uint16 version;
+	uint16 tlvs_len;
+
+	/* Check for version */
+	version = dtoh16(*(uint16 *)iov_resp);
+
+	if (version & BCM_IOV_BATCH_MASK) {
+		bcm_iov_batch_buf_t *p_resp = (bcm_iov_batch_buf_t *)iov_resp;
+
+		/* number of tlvs count */
+		tlvs_len = WLC_IOCTL_MAXLEN - OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
+
+		/* Extract the tlvs and print their resp in cb fn */
+		if ((res = bcm_unpack_xtlv_buf((void *)p_resp,
+			(const uint8 *)&p_resp->cmds[0],
+			tlvs_len, BCM_IOV_CMD_OPT_ALIGN32,
+			wlu_nan_set_vars_cbfn)) != BCME_OK) {
+			if (p_resp->count == 0) {
+				res = BCME_OK;
+			}
+		}
+	} else {
+		res = BCME_UNSUPPORTED;
+	}
+
+	return res;
+}
+
+/*
+ *   --- common for all nan get commands ----
+ */
+int
+wl_nan_do_get_ioctl(void *wl, void *nanioc, uint16 iocsz)
+{
+	/* for gets we only need to pass ioc header */
+	uint8 *iocresp = NULL;
+	int res;
+
+	if ((iocresp = malloc(WLC_IOCTL_MAXLEN)) == NULL) {
+		printf("Failed to malloc %d bytes \n",
+				WLC_IOCTL_MAXLEN);
+		return BCME_NOMEM;
+	}
+
+	/*  send getbuf nan iovar */
+	res = wlu_iovar_getbuf(wl, "nan", nanioc, iocsz, iocresp, WLC_IOCTL_MAXLEN);
+
+	/*  check the response buff  */
+	if ((res == BCME_OK) && (iocresp != NULL)) {
+		res = process_get_resp_buf(iocresp);
+	}
+
+	free(iocresp);
+	return res;
+}
+
+
+/* nan event_msgs:  enable/disable nan events  */
+static int
+wl_nan_subcmd_event_msgs(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	/* bit num = event enum -1 */
+	const char usage[] = "nan event_msgs [bit] [0/1]\n"
+		"	bit 0	- WL_NAN_EVENT_START\n"
+		"	bit 1	- WL_NAN_EVENT_JOIN\n"
+		"	bit 2	- WL_NAN_EVENT_ROLE\n"
+		"	bit 3	- WL_NAN_EVENT_SCAN_COMPLETE\n"
+		"	bit 4	- WL_NAN_EVENT_DISCOVERY_RESULT\n"
+		"	bit 5	- WL_NAN_EVENT_REPLIED\n"
+		"	bit 6	- WL_NAN_EVENT_TERMINATED\n"
+		"	bit 7	- WL_NAN_EVENT_RECEIVE\n"
+		"	bit 8	- WL_NAN_EVENT_STATUS_CHG\n"
+		"	bit 9	- WL_NAN_EVENT_MERGE\n"
+		"	bit 10 - WL_NAN_EVENT_STOP\n"
+		"	bit 11 - WL_NAN_EVENT_P2P\n"
+		"	bit 16 - WL_NAN_EVENT_POST_DISC\n"
+		"	bit 17 - WL_NAN_EVENT_DATA_IF_ADD\n"
+		"	bit 18 - WL_NAN_EVENT_DATA_PEER_ADD\n"
+		"	bit 19 - WL_NAN_EVENT_DATA_IND\n"
+		"	bit 20 - WL_NAN_EVENT_DATA_CONF\n"
+		"	bit 21 - WL_NAN_EVENT_DATA_SDF_RX\n"
+		"	bit 22 - WL_NAN_EVENT_DATA_END\n"
+		"	bit 23 - WL_NAN_EVENT_BCN_RX\n"
+		"	bit 24 ..30 - unused\n"
+		"	bit 31 -  set/clr all eventmask bits\n";
+
+	if (*argv == NULL) {
+		/* get: handled by cbfn */
+		*is_set = FALSE;
+		goto exit;
+	} else {
+		/*  args are present, do set ioctl  */
+		uint8 bit = 32, val = 3;
+		uint8 *pxtlv = iov_data;
+		uint32 eventmask;
+
+		bit = atoi(argv[0]);
+
+		if ((argv[0][0] == '-')) {
+			fprintf(stderr,
+				"%s\n", usage);
+			res = BCME_BADARG;
+			goto exit;
+		}
+
+		if (bit > 31) {
+			fprintf(stderr, "1st param should be [0..31]\n");
+			fprintf(stderr, "%s\n", usage);
+			res = BCME_BADARG;
+			goto exit;
+		}
+
+		if (argv[1])
+			val = atoi(argv[1]);
+
+		if (val > 1) {
+			fprintf(stderr, "2nd param should be [0|1]\n");
+			fprintf(stderr, "%s\n", usage);
+			res = BCME_BADARG;
+			goto exit;
+		}
+
+		if (bit == 31)	{
+			/*  set all bits */
+			eventmask = 0x7fffffff;
+		} else {
+			/* set/reset one bit */
+			eventmask = 1 << bit;
+		}
+		if (val == 0) {
+			/* and mask to rst bit */
+			eventmask = ~eventmask;
+		}
+
+		eventmask = htod32(eventmask);
+
+		memcpy(pxtlv, &eventmask, sizeof(eventmask));
+		*avail_len -= sizeof(eventmask);
+
+	}
+
+exit:
+	return res;
+}
+
+/*
+*  ********  various debug features, for internal use only ********
+*/
+
+/*
+*  ********  get NAN status info ********
+*/
+static int
+wl_nan_subcmd_scan_params(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	int opt_err;
+	miniopt_t to;
+	const char* fn_name = "scan_params";
+	int nchan = 0;
+
+	/* nan scan params inited to dflt */
+	wl_nan_scan_params_t scan_params = {
+		.scan_time = 0,
+		.home_time = 0,
+		.ms_intvl = 0,
+		.ms_dur = 0,
+		.chspec_num = 0,
+		.chspec_list = {0x1006, 0xd02c, 0xd095} /* ch 6/20, ch 44/20 , ch 149/20 */
+	};
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(avail_len);
+	UNUSED_PARAMETER(argc);
+
+	if (*argv == NULL) {
+		/* get: handled by cbfn */
+		*is_set = FALSE;
+		goto exit;
+	} else {
+		/*  args are present, do set ioctl  */
+		int ok_params_cnt = 0;
+		int i;
+		uint8 *pxtlv = iov_data;
+
+		miniopt_init(&to, fn_name, NULL, FALSE);
+
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+
+			if (opt_err == 1) {
+				res = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 's') {
+				if (!to.good_int) {
+					fprintf(stderr,
+					        "%s: option value %s\" is not an integer\n",
+					        fn_name, to.valstr);
+					res = BCME_BADARG;
+					goto exit;
+				}
+				scan_params.scan_time = to.uval;
+				ok_params_cnt++;
+			}
+
+			if (to.opt == 'h') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: option value %s\" is not an integer\n",
+						fn_name, to.valstr);
+					res = BCME_BADARG;
+					goto exit;
+				}
+
+				scan_params.home_time = to.uval;
+				ok_params_cnt++;
+			}
+
+			if (to.opt == 'i') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: option value %s\" is not an integer\n",
+						fn_name, to.valstr);
+					res = BCME_BADARG;
+					goto exit;
+				}
+				scan_params.ms_intvl = to.uval;
+				ok_params_cnt++;
+			}
+
+			if (to.opt == 'd') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: option value %s\" is not an integer\n",
+						fn_name, to.valstr);
+					res = BCME_BADARG;
+					goto exit;
+				}
+				scan_params.ms_dur = to.uval;
+				ok_params_cnt++;
+			}
+
+			if (to.opt == 'c') {
+				nchan =  wl_parse_chanspec_list(to.valstr,
+					scan_params.chspec_list, 8);
+
+				if ((nchan == -1) | (nchan >= 8)) {
+					fprintf(stderr, "error parsing channel list arg\n");
+					res = BCME_BADARG;
+					goto exit;
+				}
+
+				/* convert to dongle endianness */
+				for (i = 0; i < nchan; i++) {
+					scan_params.chspec_list[i] =
+						htodchanspec(scan_params.chspec_list[i]);
+				}
+				scan_params.chspec_num = nchan;
+				ok_params_cnt++;
+			} /* if chan list */
+
+
+		} /*  while options proc loop  */
+
+		if (ok_params_cnt == 0) {
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		/* convert to dongle indianness */
+		scan_params.scan_time = htod16(scan_params.scan_time);
+		scan_params.home_time = htod16(scan_params.home_time);
+		scan_params.ms_intvl = htod16(scan_params.ms_intvl);
+		scan_params.ms_dur = htod16(scan_params.ms_dur);
+
+		memcpy(&pxtlv, (uint8 *)&scan_params, sizeof(scan_params));
+
+	}
+
+exit:
+	return res;
+}
+
+/*
+*  ********  get nan discovery results ********
+*/
+static int
+wl_nan_subcmd_disc_results(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	if (*argv == NULL || argc == 0) {
+		*is_set = FALSE;
+	} else if (!*argv) {
+		res = BCME_USAGE_ERROR;
+	}
+
+	return res;
+}
+/*
+* ********  nan scan for clusters  ********
+*/
+static int
+wl_nan_subcmd_scan(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint8 *pxtlv = iov_data;
+	struct ether_addr cid;
+
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(argc);
+
+	/*  nan scan is a SET only ioctl no params passes NULL ether addr */
+	if (*argv) {
+		if (!wl_ether_atoe(*argv, &cid)) {
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+	} else {
+		/* bcast mac: scan for all nan clusters */
+		bcopy(&ether_null, &cid, ETHER_ADDR_LEN);
+	}
+
+	memcpy(pxtlv, (uint8 *)&cid, ETHER_ADDR_LEN);
+	*avail_len -= ETHER_ADDR_LEN;
+
+exit:
+	return res;
+}
+
+static int
+wl_nan_subcmd_dbg_scan_results(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_USAGE_ERROR;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_dbg_rssi(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_USAGE_ERROR;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+	UNUSED_PARAMETER(argc);
+
+	return res;
+}
+
+static void
+wl_nan_help_usage()
+{
+	printf("%s\n", NAN_PARAMS_USAGE);
+}
+
+static void
+wl_nan_help(uint16 type)
+{
+	int i;
+	const wl_nan_cmd_help_t *p_help_info = &nan_cmd_help_list[0];
+
+	if (type == NAN_HELP_ALL) {
+		wl_nan_help_usage();
+		return;
+	}
+
+	for (i = 0; i < (int) ARRAYSIZE(nan_cmd_help_list); i++) {
+		if (p_help_info->type == type) {
+			if (p_help_info->help_handler) {
+				(p_help_info->help_handler)();
+				break;
+			}
+		}
+		p_help_info++;
+	}
+
+	return;
+}
+
+/*  ********  enable/disable feature  ************** */
+static int
+wl_nan_subcmd_cfg_enable(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+
+	int res = BCME_OK;
+	uint8 enable = 0;
+	uint16 len;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(enable);
+
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		enable = (uint8)atoi(*argv);
+		memcpy(iov_data, &enable, sizeof(enable));
+	}
+
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_state(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_role_t role;
+	wl_nan_role_config_t *rcfg;
+	struct ether_addr master = ether_null;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(*rcfg);
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			res = BCME_BUFTOOSHORT;
+			goto exit;
+		}
+		role = atoi(*argv++);
+		if (role > WL_NAN_ROLE_ANCHOR_MASTER) {
+			printf("%s : Invalid role\n", __FUNCTION__);
+			res = BCME_BADOPTION;
+			goto exit;
+		}
+
+		if (!*argv) {
+			if (role != WL_NAN_ROLE_AUTO && role != WL_NAN_ROLE_ANCHOR_MASTER) {
+				printf("%s : Missing target master address.\n", __FUNCTION__);
+				res = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		} else {
+			if (!wl_ether_atoe(*argv, &master)) {
+				printf("%s: Invalid ether addr provided\n", __FUNCTION__);
+				res = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+
+		rcfg = (wl_nan_role_config_t *)iov_data;
+		rcfg->role = role;
+		memcpy(&rcfg->target_master, &master, ETHER_ADDR_LEN);
+
+	}
+	*avail_len -= len;
+
+exit:
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_hop_count(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_hop_count_t hop_cnt;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(is_set);
+
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(hop_cnt);
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+		hop_cnt = (uint8)atoi(*argv);
+		memcpy(iov_data, (uint8 *)&hop_cnt, sizeof(hop_cnt));
+	}
+
+	*avail_len -= len;
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_hop_limit(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	wl_nan_hop_count_t hop_limit;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(hop_limit);
+
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		hop_limit = (uint8)atoi(*argv);
+		memcpy(iov_data, &hop_limit, sizeof(hop_limit));
+	}
+
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_warmup_time(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_warmup_time_ticks_t wup_ticks;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(is_set);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(wup_ticks);
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+		wup_ticks = (uint32)atoi(*argv);
+		memcpy(iov_data, (uint8 *)&wup_ticks, sizeof(wup_ticks));
+	}
+
+	*avail_len -= len;
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_rssi_threshold(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	wl_nan_rssi_threshold_t *rssi_threshold;
+	wl_nan_band_t nan_band;
+	uint16 len;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* For GET, band is the input argument and for SET, band and rssi_info are input params */
+	if ((*argv == NULL) || argc == 0) {
+		printf("rssi_threshold expects at least one argument i.e band\n");
+		return BCME_USAGE_ERROR;
+	} else {
+		nan_band = set_nan_band(argv[0]);
+		if ((nan_band != NAN_BAND_A) && (nan_band != NAN_BAND_B)) {
+			return BCME_USAGE_ERROR;
+		}
+		/* advance to the next param */
+		argv++;
+		argc -= 1;
+		if ((*argv == NULL) || argc == 0) {
+			*is_set = FALSE;
+			len = sizeof(nan_band);
+			if (len > *avail_len) {
+				printf("Buf short, requested:%d, available:%d\n",
+						len, *avail_len);
+				return BCME_BUFTOOSHORT;
+			}
+			*iov_data = nan_band;
+		} else {
+			/* band arument is already passed above, so -1 from ARGC */
+			if (ARGCNT(argv) < (WL_NAN_CMD_CFG_RSSI_THRESHOLD_ARGC - 1)) {
+				return BCME_USAGE_ERROR;
+			}
+
+			*is_set = TRUE;
+			len = sizeof(*rssi_threshold);
+
+			if (len > *avail_len) {
+				printf("Buf short, requested:%d, available:%d\n",
+						len, *avail_len);
+				return BCME_BUFTOOSHORT;
+			}
+
+			rssi_threshold = (wl_nan_rssi_threshold_t *)iov_data;
+
+			rssi_threshold->band = nan_band;
+
+			rssi_threshold->rssi_close = (int8)strtol(*argv, NULL, 0);
+
+			/* advance to the next param */
+			argv++;
+
+			rssi_threshold->rssi_mid = (int8)strtol(*argv, NULL, 0);
+		}
+	}
+
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_count(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+	} else {
+		printf("config_count doesn't expect any parameters\n");
+		return BCME_ERROR;
+	}
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_clearcount(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	/* Its Set only */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = TRUE;
+	} else {
+		printf("clearcount cmd doesn't accept any parameters\n");
+		res = BCME_USAGE_ERROR;
+	}
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_channel(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	chanspec_t chspec;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	*is_set = TRUE;
+	len = sizeof(chspec);
+	if (len > *avail_len) {
+		printf("Buf short, requested:%d, available:%d\n",
+				len, *avail_len);
+		return BCME_BUFTOOSHORT;
+	}
+
+	if (*argv) {
+		chspec = wf_chspec_aton(*argv);
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+
+	if (chspec != 0) {
+		memcpy(iov_data, (uint8 *)&chspec, sizeof(chspec));
+	}
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_band(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	wl_nan_band_t nan_band;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	*is_set = TRUE;
+	len = sizeof(nan_band);
+	if (len > *avail_len) {
+		printf("Buf short, requested:%d, available:%d\n",
+				len, *avail_len);
+		return BCME_BUFTOOSHORT;
+	}
+
+	if (*argv) {
+		nan_band = set_nan_band(*argv);
+		if (nan_band == NAN_BAND_INVALID) {
+			return BCME_USAGE_ERROR;
+		}
+
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+
+	memcpy(iov_data, (uint8*)&nan_band, sizeof(nan_band));
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_cid(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	wl_nan_cluster_id_t cid;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(cid);
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		if (!wl_ether_atoe(*argv, &cid)) {
+			printf("Malformed MAC address parameter\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		memcpy(iov_data, (uint8*)&cid, sizeof(cid));
+	}
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_if_addr(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	struct ether_addr if_addr;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if ((*argv == NULL) || (!strcmp(*argv, WL_IOV_BATCH_DELIMITER))) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(if_addr);
+		if (len > *avail_len) {
+			printf("%s: Buf short, requested:%d, available:%d\n",
+					__FUNCTION__, len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		if (!wl_ether_atoe(*argv, &if_addr)) {
+			printf("Malformed MAC address parameter\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		memcpy(iov_data, (uint8*)&if_addr, sizeof(if_addr));
+	}
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_bcn_interval(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_disc_bcn_interval_t bcn_intvl;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if ((*argv == NULL) || (!strcmp(*argv, WL_IOV_BATCH_DELIMITER))) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(bcn_intvl);
+		bcn_intvl = htod16(atoi(*argv));
+		if (len > *avail_len) {
+			printf("%s: Buf short, requested:%d, available:%d\n",
+					__FUNCTION__, len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		memcpy(iov_data, (uint8*)&bcn_intvl, sizeof(bcn_intvl));
+	}
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_sdf_txtime(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_svc_disc_txtime_t sdf_txtime;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if ((*argv == NULL) || (!strcmp(*argv, WL_IOV_BATCH_DELIMITER))) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(sdf_txtime);
+		sdf_txtime = htod16(atoi(*argv));
+		if (len > *avail_len) {
+			printf("%s: Buf short, requested:%d, available:%d\n",
+					__FUNCTION__, len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		memcpy(iov_data, (uint8*)&sdf_txtime, sizeof(sdf_txtime));
+	}
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_stop_bcn_tx(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_stop_bcn_tx_t stop_bcn_tx;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if ((*argv == NULL) || (!strcmp(*argv, WL_IOV_BATCH_DELIMITER))) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(stop_bcn_tx);
+		stop_bcn_tx = htod16(atoi(*argv));
+		if (len > *avail_len) {
+			printf("%s: Buf short, requested:%d, available:%d\n",
+					__FUNCTION__, len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		memcpy(iov_data, (uint8*)&stop_bcn_tx, sizeof(stop_bcn_tx));
+	}
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_sid_beacon(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_sid_beacon_control_t *sid_beacon;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if ((*argv == NULL) || (!strcmp(*argv, WL_IOV_BATCH_DELIMITER))) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		if (ARGCNT(argv) < WL_NAN_CMD_CFG_SID_BCN_ARGC) {
+			printf(" Must mention sid_enable and sid_count\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		*is_set = TRUE;
+		len = sizeof(*sid_beacon);
+
+		sid_beacon = (wl_nan_sid_beacon_control_t *)iov_data;
+		sid_beacon->sid_enable = atoi(*argv);
+		argv++;
+		sid_beacon->sid_count = atoi(*argv);
+
+		*avail_len -= len;
+	}
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_dw_len(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_dw_len_t dw_len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if ((*argv == NULL) || (!strcmp(*argv, WL_IOV_BATCH_DELIMITER))) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(dw_len);
+		dw_len = htod16((uint16)atoi(*argv));
+		if (len > *avail_len) {
+			printf("%s: Buf short, requested:%d, available:%d\n",
+					__FUNCTION__, len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		memcpy(iov_data, (uint8*)&dw_len, sizeof(dw_len));
+	}
+	*avail_len -= len;
+
+	return res;
+}
+
+#define AWAKE_DW_BANDOPTION_LEN		4
+enum {
+	NAN_AWAKE_DW_INTERVAL = 1,
+	NAN_AWAKE_DW_BAND = 2
+};
+
+typedef struct nan_awake_dw_config_param {
+	char *name;	/* <param-name> string to identify the config item */
+	uint16 id;
+	uint16 len; /* len in bytes */
+	char *help_msg; /* Help message */
+} nan_awake_dw_config_param_t;
+
+static const nan_awake_dw_config_param_t nan_awake_dw_param[] = {
+	/* param-name	param_id				len		help message */
+	{ "band", NAN_AWAKE_DW_BAND, AWAKE_DW_BANDOPTION_LEN,
+	"Band value can be either 'a', or 'b' " },
+	{ "interval", NAN_AWAKE_DW_INTERVAL, sizeof(uint8),
+	"DW interval assumes 1,2,4,8,16 values" },
+};
+
+const nan_awake_dw_config_param_t *
+nan_lookup_awake_dw_config_param(char *param_name)
+{
+	int i = 0;
+	const nan_awake_dw_config_param_t *param_p = &nan_awake_dw_param[0];
+
+	for (i = 0; i < (int)ARRAYSIZE(nan_awake_dw_param); i++) {
+		if (stricmp(param_p->name, param_name) == 0) {
+			return param_p;
+		}
+		param_p++;
+	}
+
+	return NULL;
+}
+static int
+wl_nan_subcmd_cfg_awake_dw(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_awake_dw_t *awake_dw;
+	const nan_awake_dw_config_param_t *param_p = NULL;
+	wl_nan_band_t nan_band;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	/* For GET, band is the input argument and for SET, band and interval are input params */
+	if ((*argv == NULL) || argc == 0) {
+		printf("awake_dw expects at least one argument i.e band\n");
+		return BCME_USAGE_ERROR;
+	} else {
+		len = sizeof(wl_nan_awake_dw_t);
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		awake_dw = (wl_nan_awake_dw_t *)iov_data;
+		while (*argv != NULL) {
+			if ((param_p = nan_lookup_awake_dw_config_param(*argv)) == NULL) {
+				res = BCME_USAGE_ERROR;
+				break;
+			}
+			/*
+			 * Skip param name
+			 */
+			argv++;
+			switch (param_p->id) {
+			case NAN_AWAKE_DW_INTERVAL:
+				awake_dw->interval = (uint8)atoi(*argv);
+				*is_set = TRUE;
+				if (awake_dw->interval != 1 && awake_dw->interval != 2 &&
+					awake_dw->interval != 4 && awake_dw->interval != 8 &&
+					awake_dw->interval != 16) {
+					printf("%s\n", param_p->help_msg);
+					res = BCME_USAGE_ERROR;
+				}
+				break;
+			case NAN_AWAKE_DW_BAND:
+				nan_band = set_nan_band(argv[0]);
+
+				if ((nan_band != NAN_BAND_A) && (nan_band != NAN_BAND_B)) {
+					printf("%s\n", param_p->help_msg);
+					res = BCME_USAGE_ERROR;
+				}
+				*is_set = FALSE;
+				awake_dw->band = nan_band;
+
+				break;
+			default:
+				res = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			argv++;
+		}
+	}
+
+	*avail_len -= len;
+fail:
+	return res;
+}
+
+/*
+*  ********  get NAN election commands ********
+*/
+static int
+wl_nan_subcmd_election_host_enable(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	wl_nan_host_enable_t enable;
+	uint16 len;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(enable);
+
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		enable = (uint8)atoi(*argv);
+		memcpy(iov_data, (uint8 *)&enable, sizeof(enable));
+		/* advance to the next param */
+	}
+
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_election_metrics_config(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_election_metric_config_t *metrics;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	*is_set = TRUE;
+	if (*argv == NULL) {
+		printf(" Must mention random factor and master pref\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (ARGCNT(argv) < WL_NAN_CMD_CFG_ELECTION_METRICS_ARGC) {
+		return BCME_USAGE_ERROR;
+	}
+
+	len = sizeof(wl_nan_election_metric_config_t);
+	if (len > *avail_len) {
+		printf("Buf short, requested:%d, available:%d\n",
+				len, *avail_len);
+		return BCME_BUFTOOSHORT;
+	}
+
+	metrics = (wl_nan_election_metric_config_t *)iov_data;
+	metrics->random_factor = (uint8)atoi(*argv);
+	argv++;
+	metrics->master_pref = (uint8)atoi(*argv);
+
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_election_metrics_state(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+	} else {
+		printf("metrics state doesn't expect any parameters\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	return res;
+}
+
+/*
+*  ********  get NAN status info ********
+*/
+static int
+wl_nan_subcmd_cfg_status(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+	} else {
+		printf("config_status doesn't expect any parameters\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	return res;
+}
+
+/*
+*  ********  get NAN status info ********
+*/
+static int
+wl_nan_subcmd_stop(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	wl_nan_cluster_id_t cid;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	*is_set = TRUE;
+	len = sizeof(cid);
+	if (len > *avail_len) {
+		printf("Buf short, requested:%d, available:%d\n",
+				len, *avail_len);
+		return BCME_BUFTOOSHORT;
+	}
+
+	/* For stop, only parameter cluster ID is an optional param */
+	if ((*argv == NULL) || argc == 0) {
+		/* Send null ether address as cid */
+		memcpy(&cid, &ether_null, len);
+	} else {
+		if (!wl_ether_atoe(*argv, &cid)) {
+			printf("Malformed MAC address parameter\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	memcpy(iov_data, &cid, len);
+
+	*avail_len -= len;
+
+	return res;
+}
+
+
+/*  nan join cluter or start a new one  */
+static int
+wl_nan_subcmd_join(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	wl_nan_join_t *join_req;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	*is_set = TRUE;
+	len = sizeof(*join_req);
+	if (len > *avail_len) {
+		printf("Buf short, requested:%d, available:%d\n",
+				len, *avail_len);
+		return BCME_BUFTOOSHORT;
+	}
+
+	join_req = (wl_nan_join_t *)iov_data;
+
+	memset(join_req, 0, len);
+
+	/* -start from wl join command is optional */
+	/* Join command can expect optional params cid and -start */
+	while (*argv && (argc > 0)) {
+		if (!stricmp(*argv, "-start")) {
+			join_req->start_cluster = TRUE;
+		} else if (!wl_ether_atoe(*argv, &join_req->cluster_id)) {
+			printf("Malformed MAC address parameter\n");
+			return BCME_USAGE_ERROR;
+		}
+		argv++;
+		argc--;
+	}
+
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_leave(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	wl_nan_cluster_id_t cid;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	*is_set = TRUE;
+	len = sizeof(cid);
+	if (len > *avail_len) {
+		printf("Buf short, requested:%d, available:%d\n",
+				len, *avail_len);
+		return BCME_BUFTOOSHORT;
+	}
+
+	/* For stop, only parameter cluster ID is an optional param */
+	if ((*argv == NULL) || argc == 0) {
+		/* Send null ether address as cid */
+		memcpy(&cid, &ether_null, len);
+	} else {
+		if (!wl_ether_atoe(*argv, &cid)) {
+			printf("Malformed MAC address parameter\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	memcpy(iov_data, &cid, len);
+
+	*avail_len -= len;
+
+	return res;
+}
+enum {
+	NAN_SD_PARAM_LENGTH = 0x0000,
+	NAN_SD_PARAM_FLAGS = 0x0001,
+	NAN_SD_PARAM_SVC_HASH = 0x0002,
+	NAN_SD_PARAM_INST_ID = 0x0003,
+	NAN_SD_PARAM_RSSI = 0x0004,
+	NAN_SD_PARAM_PERIOD = 0x0005,
+	NAN_SD_PARAM_TTL = 0x0006,
+	NAN_SD_PARAM_OPTIONS = 0x0007,
+	NAN_SD_PARAM_LCL_SVC_ID = 0x0008,
+	NAN_SD_PARAM_REQ_SVC_ID = 0x0009,
+	NAN_SD_PARAM_PRIORITY = 0x000A,
+	NAN_SD_PARAM_MAC_INCLUDE = 0x000B,
+	NAN_SD_PARAM_TOKEN = 0x000C,
+	NAN_SD_PARAM_SVC_INFO_LEN = 0x000D,
+	NAN_SD_PARAM_SVC_INFO = 0x000E,
+	NAN_SD_PARAM_SVC_BLOOM = 0x000F,
+	NAN_SD_PARAM_SVC_MATCH_TX = 0x0010,
+	NAN_SD_PARAM_SVC_MATCH_RX = 0x0011,
+	NAN_SD_PARAM_SVC_SRF_RAW = 0x0012,
+	NAN_SD_PARAM_SVC_NAME = 0x0013,
+	NAN_SD_PARAM_SVC_MATCH_BOTH = 0x0014,
+	NAN_SD_PARAM_MAC_EXCLUDE = 0x0015,
+	NAN_SD_PARAM_SVC_BLOOM_IDX = 0x0016,
+	NAN_SD_PARAM_SVC_MATCH_RAW = 0x0017,
+	NAN_SD_PARAM_SVC_FOLLOWUP = 0x0018,
+	NAN_SD_PARAM_SVC_MATCH_RX_RAW = 0x0019,
+	NAN_SD_PARAM_DEST_INST_ID = 0x001A,
+	NAN_SD_PARAM_DEST_MAC = 0x001B,
+	NAN_SD_PARAM_SDE_CONTROL = 0x001C,
+	NAN_SD_PARAM_SDE_RANGE_LIMIT = 0x001D
+};
+
+typedef struct nan_sd_config_param_info {
+	char *name;	/* <param-name> string to identify the config item */
+	uint16 id;
+	uint16 len; /* len in bytes */
+	char *help_msg; /* Help message */
+} nan_sd_config_param_info_t;
+/*
+ * Parameter name and size for service discovery IOVARs
+ */
+static const nan_sd_config_param_info_t nan_sd_config_param_info[] = {
+	/* param-name	param_id				len		help message */
+	{ "length",		NAN_SD_PARAM_LENGTH,	sizeof(uint16),
+	"Length of SD including options" },
+	{ "flags",		NAN_SD_PARAM_FLAGS,		sizeof(uint16),
+	"Bitmap representing optional flags" },
+	{ "svc-hash",	NAN_SD_PARAM_SVC_HASH,	WL_NAN_SVC_HASH_LEN,
+	"6 bytes service hash" },
+	{ "id",			NAN_SD_PARAM_INST_ID,	sizeof(uint8),
+	"Instance of current service" },
+	{ "rssi",		NAN_SD_PARAM_RSSI,		sizeof(int8),
+	"RSSI limit to Rx subscribe or pub SDF, 0 no effect" },
+	{ "period",		NAN_SD_PARAM_PERIOD,	sizeof(uint8),
+	"period of unsolicited SDF xmission in DWs" },
+	{ "ttl",		NAN_SD_PARAM_TTL,		sizeof(int32),
+	"TTL for this instance or - 1 till cancelled" },
+	{ "options",	NAN_SD_PARAM_OPTIONS,	sizeof(uint8),
+	"Optional fileds in SDF as appropriate" },
+	{ "lcl-svc-id",	NAN_SD_PARAM_LCL_SVC_ID, sizeof(uint8),
+	"Sender Service ID" },
+	{ "req-svc-id",	NAN_SD_PARAM_REQ_SVC_ID, sizeof(uint8),
+	"Destination Service ID" },
+	{ "priority",	NAN_SD_PARAM_PRIORITY,	sizeof(uint8),
+	"requested relative priority" },
+	{ "mac-incl",	NAN_SD_PARAM_MAC_INCLUDE,	ETHER_ADDR_LEN,
+	"Adds MAC addr to SRF and sets include bit" },
+	{ "token",		NAN_SD_PARAM_TOKEN,		sizeof(uint16),
+	"follow_up_token when a follow-up msg is queued successfully" },
+	{ "svc-info-len", NAN_SD_PARAM_SVC_INFO_LEN,	sizeof(uint8),
+	"size in bytes of the service info payload" },
+	{ "svc-info",	NAN_SD_PARAM_SVC_INFO,	sizeof(uint8),	"Service Info payload" },
+	{ "bloom", NAN_SD_PARAM_SVC_BLOOM, NAN_BLOOM_LENGTH_DEFAULT,
+	"Encode the Service Response Filter using a bloom filter rather than a mac list" },
+	{ "match-tx", NAN_SD_PARAM_SVC_MATCH_TX, WL_NAN_MAX_SVC_MATCH_FILTER_LEN,
+	"Match filter (hex bytes) to transmit" },
+	{ "match-rx", NAN_SD_PARAM_SVC_MATCH_RX, WL_NAN_MAX_SVC_MATCH_FILTER_LEN,
+	"Match filter (hex bytes) for receive" },
+	{ "match-both", NAN_SD_PARAM_SVC_MATCH_BOTH, WL_NAN_MAX_SVC_MATCH_FILTER_LEN,
+	"Match filter (hex bytes) to transmit" },
+	{ "srfraw", NAN_SD_PARAM_SVC_SRF_RAW, WL_NAN_MAX_SVC_MATCH_FILTER_LEN,
+	"SRF control byte + SRF data" },
+	{ "name", NAN_SD_PARAM_SVC_NAME, WL_NAN_MAX_SVC_NAME_LEN, "Service name" },
+	{ "mac-excl",	NAN_SD_PARAM_MAC_EXCLUDE,	ETHER_ADDR_LEN,
+	"Adds MAC addr to SRF and clears include bit" },
+	{ "bloom-idx", NAN_SD_PARAM_SVC_BLOOM_IDX, sizeof(uint8),
+	"Bloom hash index used for bloom filter creation" },
+	{ "match-raw", NAN_SD_PARAM_SVC_MATCH_RAW, WL_NAN_MAX_SVC_MATCH_FILTER_LEN,
+	"Match filter (raw hex bytes) to transmit" },
+	{ "followup", NAN_SD_PARAM_SVC_FOLLOWUP, 0, "Follow up" },
+	{ "match-rx-raw", NAN_SD_PARAM_SVC_MATCH_RX_RAW, WL_NAN_MAX_SVC_MATCH_FILTER_LEN,
+	"Match Rx filter (raw hex bytes) to receive" },
+	{ "dest-inst-id", NAN_SD_PARAM_DEST_INST_ID, sizeof(uint8),
+	"Destination Instance ID" },
+	{ "dest-mac", NAN_SD_PARAM_DEST_MAC, ETHER_ADDR_LEN,
+	"Destination MAC address" },
+	{ "sde-ctrl", NAN_SD_PARAM_SDE_CONTROL, sizeof(uint16),
+	"Service descriptor extension attribute control" },
+	{ "sde-range", NAN_SD_PARAM_SDE_RANGE_LIMIT, sizeof(uint32),
+	"Service descriptor extension attribute range limit" },
+};
+
+const nan_sd_config_param_info_t *
+nan_lookup_sd_config_param(char *param_name)
+{
+	int i = 0;
+	const nan_sd_config_param_info_t *param_p = &nan_sd_config_param_info[0];
+
+	for (i = 0; i < (int)ARRAYSIZE(nan_sd_config_param_info); i++) {
+		if (stricmp(param_p->name, param_name) == 0) {
+			return param_p;
+		}
+		param_p++;
+	}
+
+	return NULL;
+}
+static int
+wl_nan_subcmd_svc(void *wl, const wl_nan_sub_cmd_t *cmd, int instance_id, int argc, char **argv,
+	uint8 *iov_data, uint16 *avail_len, uint32 default_flags)
+{
+	int ret = BCME_OK;
+	wl_nan_sd_params_t *params = (wl_nan_sd_params_t *)iov_data;
+	char *val_p, *endptr, *svc_info = NULL;
+	char *followup = NULL;
+	uint32 val = 0;
+	uint8 *pxtlv = (uint8 *)&params->optional[0];
+	uint16 buflen, buflen_at_start;
+	char *hash = NULL, *hash_raw = NULL;
+
+	/* Matching filter variables */
+	char *match_raw = NULL, *match_rx_raw = NULL;
+	uint8 *match = NULL, *matchtmp = NULL;
+	uint8 *match_rx = NULL, *match_rxtmp = NULL;
+	uint8 m_len;
+
+	/* SRF variables */
+	uint8 *srf = NULL, *srftmp = NULL, *mac_list = NULL;
+	bool srfraw_started = FALSE;
+	bool srf_started = FALSE;
+	/* Bloom length default, indicates use mac filter not bloom */
+	uint bloom_len = 0;
+	struct ether_addr srf_mac;
+	bcm_bloom_filter_t *bp = NULL;
+	/* Bloom filter index default, indicates it has not been set */
+	uint bloom_idx = 0xFFFFFFFF;
+	uint mac_num = 0;
+	char *srf_raw = NULL;
+	uint16 srf_include = 0;
+	const nan_sd_config_param_info_t *param_p;
+	bool zero_lv_pair = FALSE;
+
+	/* Service discovery extension variables */
+	int16 sde_control = -1;
+	int32 sde_range_limit = -1;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(argc);
+
+	/* Default options */
+	params->period = 1;
+	params->ttl = WL_NAN_TTL_UNTIL_CANCEL;
+	params->flags = default_flags;
+
+	/* Copy mandatory parameters from command line. */
+	if (!*argv) {
+		printf("Missing parameters.\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	params->instance_id = instance_id;
+
+	/*
+	 * wl nan [publish|subscribe] <instance-id> name <service-name>
+	 */
+	if (!*argv || (stricmp(*argv, "name") != 0)) {
+		printf("Missing service name parameter.\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	argv++;
+	hash = *argv;
+	argv++;
+	buflen = *avail_len;
+	buflen_at_start = buflen;
+	buflen -= OFFSETOF(wl_nan_sd_params_t, optional[0]);
+
+	/* Parse optional args. Validity is checked by discovery engine */
+	while (*argv != NULL) {
+		if ((param_p = nan_lookup_sd_config_param(*argv)) == NULL) {
+			break;
+		}
+		/*
+		 * Skip param name
+		 */
+		argv++;
+		switch (param_p->id) {
+		case NAN_SD_PARAM_SVC_BLOOM:
+			if (srfraw_started) {
+				printf("Cannot use -bloom-idx with -srfraw\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			srf_started = TRUE;
+
+			if (bloom_len) {
+				printf("-bloom can only be set once\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			/* Value is optional */
+			if (!*argv) {
+				bloom_len = NAN_BLOOM_LENGTH_DEFAULT;
+			} else {
+				val = strtoul(*argv, &endptr, 0);
+
+				if (*endptr != '\0' || val < 1 || val > 254) {
+					printf("Invalid bloom length.\n");
+					ret = BCME_USAGE_ERROR;
+					goto exit;
+				}
+			}
+			bloom_len = val;
+			break;
+		case NAN_SD_PARAM_SVC_MATCH_BOTH:
+			if (match_raw) {
+				printf("-match has already been used, cannot use -m \n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+
+			/* Allocate and initalize matching filter buffer */
+			if (!match) {
+				if ((match = malloc(WLC_IOCTL_MEDLEN)) == NULL) {
+					printf("Failed to malloc %d bytes \n",
+						WLC_IOCTL_MEDLEN);
+					ret = BCME_NOMEM;
+					goto exit;
+				}
+				matchtmp = match;
+			}
+
+			/* If no value is given, then it is a zero length LV pair.
+			 * So, checking for arg NULL OR
+			 * calling nan_lookup_sd_config_param() which return non-NULL
+			 * incase the argument is the next config param.
+			 */
+			if (!*argv || nan_lookup_sd_config_param(*argv)) {
+				zero_lv_pair = TRUE;
+				*matchtmp++ = 0;
+			} else {
+				/* Add LV pair to temporary buffer */
+				val_p = *argv;
+				m_len = strlen(val_p);
+				*matchtmp++ = m_len;
+				strncpy((char*)matchtmp, val_p, m_len);
+				matchtmp += m_len;
+			}
+			break;
+		case NAN_SD_PARAM_SVC_MATCH_RX:
+			if (match_rx_raw) {
+				printf("match-rx-raw has already been used, cannot use match-rx\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+
+			/* Allocate and initalize matching filter buffer */
+			if (!match_rx) {
+				if ((match_rx = malloc(WLC_IOCTL_MEDLEN)) == NULL) {
+					printf("Failed to malloc %d bytes \n",
+						WLC_IOCTL_MEDLEN);
+					ret = BCME_NOMEM;
+					goto exit;
+				}
+				match_rxtmp = match_rx;
+			}
+			/* If no value is given, then it is a zero length LV pair.
+			 * So, checking for arg NULL OR
+			 * calling nan_lookup_sd_config_param() which return non-NULL
+			 * incase the argument is the next config param.
+			 */
+			if (!*argv || nan_lookup_sd_config_param(*argv)) {
+				zero_lv_pair = TRUE;
+				*match_rxtmp++ = 0;
+			} else {
+				/* Add LV pair to temporary buffer */
+				val_p = *argv;
+				m_len = strlen(val_p);
+				*match_rxtmp++ = m_len;
+				strncpy((char*)match_rxtmp, val_p, m_len);
+				match_rxtmp += m_len;
+			}
+			break;
+		case NAN_SD_PARAM_SVC_MATCH_TX:
+			if (match_raw) {
+				printf("match-raw has already been used, cannot use match-tx \n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+
+			/* Allocate and initalize matching filter buffer */
+			if (!match) {
+				if ((match = malloc(WLC_IOCTL_MEDLEN)) == NULL) {
+					printf("Failed to malloc %d bytes \n",
+						WLC_IOCTL_MEDLEN);
+					ret = BCME_NOMEM;
+					goto exit;
+				}
+				matchtmp = match;
+			}
+			/* If no value is given, then it is a zero length LV pair.
+			 * So, checking for arg NULL OR
+			 * calling nan_lookup_sd_config_param() which return non-NULL
+			 * incase the argument is the next config param.
+			 */
+			if (!*argv || nan_lookup_sd_config_param(*argv)) {
+				zero_lv_pair = TRUE;
+				*matchtmp++ = 0;
+			} else {
+				/* Add LV pair to temporary buffer */
+				val_p = *argv;
+				m_len = strlen(val_p);
+				*matchtmp++ = m_len;
+				strncpy((char*)matchtmp, val_p, m_len);
+				matchtmp += m_len;
+			}
+			break;
+		case NAN_SD_PARAM_MAC_INCLUDE:
+		case NAN_SD_PARAM_MAC_EXCLUDE:
+			if (srfraw_started) {
+				printf("Cannot use -i or -x with -srfraw\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			srf_started = TRUE;
+
+			if (!srf_include) {
+				/* mac include or exclude param ID */
+				srf_include = param_p->id;
+			} else if (srf_include != param_p->id) {
+				printf("Cannot use mac-incl or mac-excl together\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			/* Allocate and initalize SRF buffer */
+			if (!srftmp) {
+				if ((mac_list = malloc(WLC_IOCTL_MEDLEN)) == NULL) {
+					printf("Failed to malloc %d bytes \n",
+							WLC_IOCTL_MEDLEN);
+					ret = BCME_NOMEM;
+					goto exit;
+				}
+				srftmp = mac_list;
+			}
+			val_p = *argv;
+			/* Add MAC address to temporary buffer */
+			if (!wl_ether_atoe(val_p, &srf_mac)) {
+				printf("Invalid ether addr\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			memcpy(srftmp, &srf_mac, ETHER_ADDR_LEN);
+			srftmp += ETHER_ADDR_LEN;
+			mac_num++;
+			break;
+		case NAN_SD_PARAM_SVC_BLOOM_IDX:
+			if (srfraw_started) {
+				printf("Cannot use -bloom-idx with -srfraw\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			srf_started = TRUE;
+
+			if (bloom_idx != 0xFFFFFFFF) {
+				printf("-bloom-idx can only be set once\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			/* Set bloom index */
+			bloom_idx = atoi(*argv);
+			if (bloom_idx > 3) {
+				printf("Invalid -bloom-idx value\n");
+			}
+			break;
+		case NAN_SD_PARAM_SVC_SRF_RAW:
+			/* Send raw hex bytes of SRF control and SRF to firmware */
+			/* Temporarily store SRF */
+			if (srf_started) {
+				printf("srfraw is used without other srf options\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			srf_raw = *argv;
+			srfraw_started = TRUE;
+			break;
+		case NAN_SD_PARAM_SVC_INFO:
+			/* Temporarily store service info */
+			svc_info = *argv;
+			break;
+		case NAN_SD_PARAM_SVC_MATCH_RAW:
+			/* Send raw hex bytes of matching filter to firmware */
+			if (match) {
+				printf("-m has already been used, cannot use -match \n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			/* Temporarily store matching filter */
+			match_raw = *argv;
+			break;
+		case NAN_SD_PARAM_SVC_MATCH_RX_RAW:
+			/* Send raw hex bytes of matching filter rx to firmware */
+			if (match_rx) {
+				printf("-m-rx has already been used, cannot use"
+				 "-match_rx\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			/* Temporarily store matching filter rx */
+			match_rx_raw = *argv;
+			break;
+		case NAN_SD_PARAM_SVC_FOLLOWUP:
+			/* Temporarily store service info for Follow-Up */
+			followup = *argv;
+			break;
+		case NAN_SD_PARAM_SVC_HASH:
+			/* Temporarily store raw service ID hash */
+			hash_raw = *argv;
+			break;
+		case NAN_SD_PARAM_FLAGS:
+			val_p = *argv;
+			val = strtoul(val_p, &endptr, 0);
+			if (*endptr != '\0') {
+				printf("Value is not uint or hex %s\n",
+					val_p);
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+
+			params->flags = val;
+			break;
+		case NAN_SD_PARAM_PERIOD:
+			val_p = *argv;
+			val = strtoul(val_p, &endptr, 0);
+			if (*endptr != '\0') {
+				printf("Value is not uint or hex %s\n",
+					val_p);
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			params->period = val;
+			break;
+		case NAN_SD_PARAM_TTL:
+			val_p = *argv;
+			val = strtoul(val_p, &endptr, 0);
+			if (*endptr != '\0') {
+				printf("Value is not uint or hex %s\n",
+					val_p);
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			params->ttl = val;
+			break;
+		case NAN_SD_PARAM_RSSI:
+			params->proximity_rssi = atoi(*argv);
+			break;
+		case NAN_SD_PARAM_LENGTH:
+			params->length = atoi(*argv);
+			break;
+		case NAN_SD_PARAM_SDE_CONTROL:
+			if (cmd->id != WL_NAN_CMD_SD_PUBLISH) {
+				printf("SDE options are for publish only\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			sde_control = atoi(*argv);
+			break;
+		case NAN_SD_PARAM_SDE_RANGE_LIMIT:
+			if (cmd->id != WL_NAN_CMD_SD_PUBLISH) {
+				printf("SDE options are for publish only\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			sde_range_limit = atoi(*argv);
+			break;
+		default:
+			printf("Unrecognized parameter %s\n",
+				param_p->name);
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+			/* TODO add matching filters, service specific info */
+		}
+
+		if (zero_lv_pair) {
+			zero_lv_pair = FALSE;
+		} else {
+			argv++;
+		}
+	}
+
+	/* If service ID raw value was not provided, calculate from name */
+	if (!hash_raw) {
+		/* As focus is on NaN1.0 CERT so for making test setup, we need to support old
+		 * chip like 4359 which have svc_hash as non hash value so to accept that
+		 * we made svc_hash as non hash value beacuse publish with hash and subscibe
+		 * without hash and vice-versa is not acceptable.
+		 */
+		strncpy((char*)params->svc_hash, hash, WL_NAN_SVC_HASH_LEN);
+	} else {
+		 /* 6-byte Service ID (hash) value */
+		if (strlen(hash_raw)/2 != WL_NAN_SVC_HASH_LEN) {
+			printf("Need 6 byte service id\n");
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		} else {
+			if (get_ie_data((uchar*)hash_raw, params->svc_hash,
+				WL_NAN_SVC_HASH_LEN)) {
+				ret = BCME_BADARG;
+				goto exit;
+			}
+		}
+	}
+
+	/* Optional parameters */
+	/* TODO other optional params */
+	if (svc_info) {
+		ret = bcm_pack_xtlv_entry_from_hex_string(&pxtlv,
+			&buflen, WL_NAN_XTLV_SVC_INFO, svc_info);
+		if (ret != BCME_OK)
+		goto exit;
+	}
+	if (match_raw) {
+		ret = bcm_pack_xtlv_entry_from_hex_string(&pxtlv,
+			&buflen, WL_NAN_XTLV_MATCH_TX, match_raw);
+		if (ret != BCME_OK)
+			goto exit;
+	}
+	if (match_rx_raw) {
+		/* Create XTLV only if matching filter rx is unique from tx */
+		if (!match_raw || (match_raw && strcmp(match_raw, match_rx_raw))) {
+			ret = bcm_pack_xtlv_entry_from_hex_string(&pxtlv,
+				&buflen, WL_NAN_XTLV_MATCH_RX, match_rx_raw);
+			if (ret != BCME_OK)
+				goto exit;
+		}
+	}
+	if (followup) {
+		ret = bcm_pack_xtlv_entry_from_hex_string(&pxtlv,
+			&buflen, WL_NAN_XTLV_FOLLOWUP, followup);
+		if (ret != BCME_OK)
+			goto exit;
+	}
+	if (match) {
+		m_len = matchtmp - match;
+		ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_NAN_XTLV_MATCH_TX,
+			m_len, match, BCM_XTLV_OPTION_ALIGN32);
+		if (ret != BCME_OK) goto exit;
+	}
+	if (match_rx) {
+		m_len = match_rxtmp - match_rx;
+		ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_NAN_XTLV_MATCH_RX,
+			m_len, match_rx, BCM_XTLV_OPTION_ALIGN32);
+		if (ret != BCME_OK) goto exit;
+	}
+	/* Check that there is a list of MAC addresses */
+	if (mac_list) {
+		uint8 srf_control = 0;
+		/* Construct SRF control field */
+		if (bloom_len) {
+			/* This is a bloom filter */
+			srf_control = 1;
+			if (bloom_idx == 0xFFFFFFFF) {
+				bloom_idx = params->instance_id % 4;
+			}
+			srf_control |= bloom_idx << 2;
+		}
+		if (srf_include == NAN_SD_PARAM_MAC_INCLUDE) {
+			srf_control |= 1 << 1;
+		}
+
+		if (bloom_len == 0) {
+			/* MAC list */
+			if (mac_num < NAN_SRF_MAX_MAC) {
+				if ((srf = malloc(mac_num * ETHER_ADDR_LEN + 1))	== NULL) {
+					printf("Failed to malloc %d bytes \n",
+						mac_num * ETHER_ADDR_LEN + 1);
+					ret = BCME_NOMEM;
+					goto exit;
+				}
+
+				srftmp = srf;
+				memcpy(srftmp++, &srf_control, 1);
+				memcpy(srftmp, mac_list, mac_num * ETHER_ADDR_LEN);
+			} else {
+				printf("%s: Too many MAC addresses\n", __FUNCTION__);
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+
+			ret = bcm_pack_xtlv_entry(&pxtlv, &buflen,
+				WL_NAN_XTLV_SR_FILTER, (mac_num * ETHER_ADDR_LEN + 1),
+				(uint8 *)srf, BCM_XTLV_OPTION_ALIGN32);
+			if (ret != BCME_OK)
+				goto exit;
+
+		} else {
+			/* Bloom filter */
+			if (wl_nan_bloom_create(&bp, &bloom_idx, bloom_len) != BCME_OK) {
+				printf("%s: Bloom create failed\n", __FUNCTION__);
+				ret = BCME_ERROR;
+				goto exit;
+			}
+			uint i;
+			srftmp = mac_list;
+			for (i = 0; i < mac_num; i++) {
+				if (bcm_bloom_add_member(bp, srftmp,
+					ETHER_ADDR_LEN) != BCME_OK) {
+					printf("%s: Cannot add to bloom filter\n",
+						__FUNCTION__);
+				}
+				srftmp += ETHER_ADDR_LEN;
+			}
+
+			/* Create bloom filter */
+			if ((srf = malloc(bloom_len + 1)) == NULL) {
+				printf("Failed to malloc %d bytes \n", bloom_len + 1);
+				ret = BCME_NOMEM;
+				goto exit;
+			}
+			srftmp = srf;
+			memcpy(srftmp++, &srf_control, 1);
+
+			uint bloom_size;
+			if ((bcm_bloom_get_filter_data(bp, bloom_len, srftmp,
+				&bloom_size)) != BCME_OK) {
+				printf("%s: Cannot get filter data\n", __FUNCTION__);
+				ret = BCME_ERROR;
+				goto exit;
+			}
+
+			ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_NAN_XTLV_SR_FILTER,
+				(bloom_len + 1), (uint8 *)srf, BCM_XTLV_OPTION_ALIGN32);
+			if (ret != BCME_OK)
+				goto exit;
+		}
+	}
+	if (srf_raw) {
+		ret = bcm_pack_xtlv_entry_from_hex_string(&pxtlv,
+			&buflen, WL_NAN_XTLV_SR_FILTER, srf_raw);
+		if (ret != BCME_OK)
+			goto exit;
+	}
+	if (sde_control >= 0) {
+		uint16 tmp = (uint16)sde_control;
+		ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_NAN_XTLV_SDE_CONTROL,
+			sizeof(uint16), (uint8*)&tmp, BCM_XTLV_OPTION_ALIGN32);
+		if (ret != BCME_OK)
+			goto exit;
+	}
+	if (sde_range_limit >= 0) {
+		uint32 tmp = (uint32)sde_range_limit;
+		ret = bcm_pack_xtlv_entry(&pxtlv, &buflen, WL_NAN_XTLV_SDE_RANGE_LIMIT,
+			sizeof(uint32), (uint8*)&tmp, BCM_XTLV_OPTION_ALIGN32);
+		if (ret != BCME_OK)
+			goto exit;
+	}
+	/* adjust avail_len to the end of last data record */
+	*avail_len -= (buflen_at_start - buflen);
+
+exit:
+	if (srf)
+		free(srf);
+	if (mac_list)
+		free(mac_list);
+	if (match)
+		free(match);
+	if (match_rx)
+		free(match_rx);
+	if (bp)
+		bcm_bloom_destroy(&bp, wl_nan_bloom_free);
+	return ret;
+}
+
+static int wl_nan_bloom_create(bcm_bloom_filter_t** bp, uint* idx, uint size)
+{
+	uint i;
+	int err;
+
+	err = bcm_bloom_create(wl_nan_bloom_alloc, wl_nan_bloom_free,
+		idx, WL_NAN_HASHES_PER_BLOOM, size, bp);
+	if (err != BCME_OK) {
+		goto exit;
+	}
+
+	/* Populate bloom filter with hash functions */
+	for (i = 0; i < WL_NAN_HASHES_PER_BLOOM; i++) {
+		err = bcm_bloom_add_hash(*bp, wl_nan_hash, &i);
+		if (err) {
+			goto exit;
+		}
+	}
+exit:
+	return err;
+}
+
+static void* wl_nan_bloom_alloc(void *ctx, uint size)
+{
+	BCM_REFERENCE(ctx);
+	uint8 *buf;
+
+	if ((buf = malloc(size)) == NULL) {
+		printf("Failed to malloc %d bytes \n", size);
+		buf = NULL;
+	}
+
+	return buf;
+}
+
+static void wl_nan_bloom_free(void *ctx, void *buf, uint size)
+{
+	BCM_REFERENCE(ctx);
+	BCM_REFERENCE(size);
+
+	free(buf);
+}
+
+static uint wl_nan_hash(void* ctx, uint index, const uint8 *input, uint input_len)
+{
+	uint8* filter_idx = (uint8*)ctx;
+	uint8 i = (*filter_idx * WL_NAN_HASHES_PER_BLOOM) + (uint8)index;
+	uint b = 0;
+
+	/* Steps 1 and 2 as explained in Section 6.2 */
+	/* Concatenate index to input and run CRC32 by calling hndcrc32 twice */
+	b = hndcrc32(&i, sizeof(uint8), CRC32_INIT_VALUE);
+	b = hndcrc32((uint8*) input, input_len, b);
+	/* Obtain the last 2 bytes of the CRC32 output */
+	b &= NAN_BLOOM_CRC32_MASK;
+
+	/* Step 3 is completed by bcmbloom functions */
+	return b;
+
+}
+
+/*
+ * Service Discovery commands
+ */
+#define NAN_SD_PARAMS_FLAGS_RANGE_CLOSE	((1 << 6))
+#define NAN_SD_PARAMS_FLAGS_RANGE_LIMIT (~(1 << 6))
+#define NAN_SD_PARAMS_FLAGS_UNSOLICITED ((1 << 12))
+#define NAN_SD_PARAMS_FLAGS_SOLICITED	((1 << 13))
+#define NAN_SD_PARAMS_FLAGS_UCAST		(~(1 << 14))
+#define NAN_SD_PARAMS_FLAGS_BCAST		((1 << 14))
+#define NAN_SD_PARAMS_DEFAULT_PERIOD	1
+#define NAN_SD_PARAMS_DEFAULT_TTL		0xFFFFFFFF
+static int
+wl_nan_subcmd_publish(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len = 0;
+	int int_val = 0;
+
+	UNUSED_PARAMETER(is_set);
+
+	if (*argv == NULL) {
+		res = BCME_USAGE_ERROR;
+		goto done;
+	}
+
+	int_val = atoi(*argv);
+	/* Instance ID must be from 1 to 255 */
+	if ((res = wl_nan_is_instance_valid(int_val)) != WL_NAN_E_OK) {
+		printf("Invalid instance_id.\n");
+		goto done;
+	}
+	argv++;
+	argc--;
+	if (*argv == NULL || argc == 0) {
+		memcpy(iov_data, &int_val, sizeof(int_val));
+		*avail_len -= sizeof(int_val);
+		/* GET command support for publish */
+		*is_set = FALSE;
+		goto done;
+	} else {
+		len = sizeof(wl_nan_sd_params_t);
+
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			res = BCME_BUFTOOSHORT;
+			goto done;
+		}
+
+		res = wl_nan_subcmd_svc(wl, cmd, int_val, argc, argv, iov_data,
+			avail_len, WL_NAN_PUB_BOTH);
+	}
+done:
+	return res;
+}
+
+static int
+wl_nan_subcmd_publish_list(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	if (*argv == NULL || argc == 0) {
+		*is_set = FALSE;
+	} else if (!*argv) {
+		printf("publish_list: requires no parameters\n");
+		res = BCME_USAGE_ERROR;
+	}
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_subscribe(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	int int_val = 0;
+	uint16 len = 0;
+
+	UNUSED_PARAMETER(is_set);
+
+	if (*argv == NULL) {
+		res = BCME_USAGE_ERROR;
+		goto done;
+	}
+
+	int_val = atoi(*argv);
+	/* Instance ID must be from 1 to 255 */
+	if ((res = wl_nan_is_instance_valid(int_val)) != WL_NAN_E_OK) {
+		printf("Invalid instance_id.\n");
+		*is_set = FALSE;
+		goto done;
+	}
+	argv++;
+	argc--;
+	if (*argv == NULL || argc == 0) { /* get  */
+		memcpy(iov_data, &int_val, sizeof(int_val));
+		*avail_len -= sizeof(int_val);
+		*is_set = FALSE;
+		goto done;
+	} else {
+		len = sizeof(wl_nan_sd_params_t);
+
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			res = BCME_BUFTOOSHORT;
+			goto done;
+		}
+
+		res = wl_nan_subcmd_svc(wl, cmd, int_val, argc, argv, iov_data,
+			avail_len, 0);
+	}
+
+done:
+	return res;
+}
+
+/*
+ * Returns active subscribe list instance
+ */
+static int
+wl_nan_subcmd_subscribe_list(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	if (*argv == NULL || argc == 0) {
+		*is_set = FALSE;
+	} else if (*argv) {
+		printf("subscribe: requires no parameters\n");
+		res = BCME_USAGE_ERROR;
+	}
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cancel(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int ret = BCME_OK;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(argc);
+	int int_val = 0;
+	wl_nan_instance_id_t instance_id;
+	uint16 buflen, buflen_at_start;
+
+	if (!argv[0] || argv[1]) {
+		printf("Incorrect number of parameters.\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+
+	}
+	int_val = atoi(argv[0]);
+	/* instance id '0' means cancel all publish/subscribe.
+	 * So, allowing instance ID '0' also for cancel IOVARs.
+	 */
+	if (int_val && ((ret = wl_nan_is_instance_valid(int_val)) != WL_NAN_E_OK)) {
+		printf("Invalid instance id.\n");
+		goto exit;
+	}
+
+	instance_id = int_val;
+
+	/* max data we can write, it will be decremented as we pack */
+	buflen = *avail_len;
+	buflen_at_start = buflen;
+
+	/* Mandatory parameters */
+	memcpy(iov_data, &instance_id, sizeof(instance_id));
+	buflen -= sizeof(instance_id);
+
+	/* adjust iocsz to the end of last data record */
+	*avail_len -= (buflen_at_start - buflen);
+
+
+exit:
+	return ret;
+}
+
+/*
+ *  wl "nan" iovar iovar handler
+ */
+static int
+wl_nan_subcmd_cancel_publish(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	return wl_nan_subcmd_cancel(wl, cmd, argc, argv,
+		is_set, iov_data, avail_len);
+}
+
+static int
+wl_nan_subcmd_cancel_subscribe(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	return wl_nan_subcmd_cancel(wl, cmd, argc, argv,
+		is_set, iov_data, avail_len);
+}
+
+static int
+wl_nan_subcmd_sd_transmit(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int ret = BCME_OK;
+	int id, dest_id = 0;
+	struct ether_addr dest = ether_null;
+	/* Set highest value as the default value for priority */
+	uint8 *pxtlv = NULL;
+	uint16 buflen, buflen_at_start, sd_info_len_start;
+	wl_nan_sd_transmit_t *sd_xmit = NULL;
+	const nan_sd_config_param_info_t *param_p = NULL;
+	bool is_lcl_id = FALSE;
+	bool is_dest_id = FALSE;
+	bool is_dest_mac = FALSE;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(argc);
+
+	/* Copy mandatory parameters from command line. */
+	if (!*argv) {
+		printf("Missing instance id parameter.\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	id = atoi(*argv);
+	if ((ret = wl_nan_is_instance_valid(id)) != WL_NAN_E_OK) {
+		printf("Invalid instance_id.\n");
+		goto exit;
+	}
+	is_lcl_id = TRUE;
+	argv++;
+	sd_xmit = (wl_nan_sd_transmit_t *)iov_data;
+	sd_xmit->local_service_id = id;
+	pxtlv = (uint8 *)&sd_xmit->service_info[0];
+
+	/* max data we can write, it will be decremented as we pack */
+	buflen = *avail_len;
+	buflen_at_start = buflen;
+
+	buflen -= OFFSETOF(wl_nan_sd_transmit_t, service_info[0]);
+
+	while (*argv != NULL) {
+		if ((param_p = nan_lookup_sd_config_param(*argv)) == NULL) {
+			break;
+		}
+		/*
+		 * Skip param name
+		 */
+		argv++;
+		switch (param_p->id) {
+		case NAN_SD_PARAM_DEST_INST_ID:
+			if (!*argv) {
+				printf("Missing requestor id parameter.\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			dest_id = atoi(*argv);
+			if ((ret = wl_nan_is_instance_valid(dest_id)) != WL_NAN_E_OK) {
+				printf("Invalid requestor_id.\n");
+				goto exit;
+			}
+			sd_xmit->requestor_service_id = dest_id;
+			is_dest_id = TRUE;
+			break;
+		case NAN_SD_PARAM_DEST_MAC:
+			if (!*argv) {
+				printf("Missing destination MAC address.\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			if (!wl_ether_atoe(*argv, &dest)) {
+				printf("Invalid ether addr provided\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			memcpy(&sd_xmit->destination_addr, &dest, ETHER_ADDR_LEN);
+			is_dest_mac = TRUE;
+			break;
+		case NAN_SD_PARAM_PRIORITY:
+			sd_xmit->priority = atoi(*argv);
+			break;
+		case NAN_SD_PARAM_SVC_INFO:
+			sd_info_len_start = buflen;
+			ret = bcm_pack_xtlv_entry_from_hex_string(&pxtlv, &buflen,
+				WL_NAN_XTLV_SVC_INFO, *argv);
+			if (ret != BCME_OK) {
+				goto exit;
+			}
+			if ((sd_info_len_start - buflen) > 0xFF) {
+				printf("Invalid service info length %d\n",
+					(sd_info_len_start - buflen));
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			sd_xmit->service_info_len = (uint8)(sd_info_len_start - buflen);
+			break;
+		default:
+			printf("Unrecognized parameter %s\n", *argv);
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv++;
+	}
+
+	/* Check if all mandatory params are provided */
+	if (is_lcl_id && is_dest_id && is_dest_mac) {
+		/* adjust avail_len to the end of last data record */
+		*avail_len -= (buflen_at_start - buflen);
+	} else {
+		printf("Missing parameters\n");
+		ret = BCME_USAGE_ERROR;
+	}
+exit:
+	return ret;
+}
+
+static int
+wl_nan_subcmd_sd_vendor_info(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_sd_statistics(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_sd_connection(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_sd_show(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_sync_tsschedule(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	return res;
+}
+
+/*
+ *  packs user data (in hex string) into tlv record
+ *  advances tlv pointer to next xtlv slot
+ *  buflen is used for tlv_buf space check
+ */
+static int
+bcm_pack_xtlv_entry_from_hex_string(uint8 **tlv_buf, uint16 *buflen, uint16 type, char *hex)
+{
+	bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf;
+	uint16 len = strlen(hex)/2;
+
+	/* copy data from tlv buffer to dst provided by user */
+
+	if (ALIGN_SIZE(BCM_XTLV_HDR_SIZE_EX(BCM_XTLV_OPTION_ALIGN32) + len,
+		sizeof(uint32)) > *buflen) {
+		printf("bcm_pack_xtlv_entry: no space tlv_buf: requested:%d, available:%d\n",
+		 ((int)BCM_XTLV_HDR_SIZE_EX(BCM_XTLV_OPTION_ALIGN32) + len), *buflen);
+		return BCME_BADLEN;
+	}
+	ptlv->id = htol16(type);
+	ptlv->len = htol16(len);
+
+	/* copy callers data */
+	if (get_ie_data((uchar*)hex, ptlv->data, len)) {
+		return BCME_BADARG;
+	}
+
+	/* advance callers pointer to tlv buff */
+	*tlv_buf += BCM_XTLV_SIZE_EX(ptlv, BCM_XTLV_OPTION_ALIGN32);
+	/* decrement the len */
+	*buflen -=  BCM_XTLV_SIZE_EX(ptlv, BCM_XTLV_OPTION_ALIGN32);
+	return BCME_OK;
+}
+
+static int
+wl_nan_subcmd_merge(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+
+	int res = BCME_OK;
+	wl_nan_merge_enable_t enable;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(enable);
+
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		enable = (uint8)atoi(*argv);
+		memcpy(iov_data, &enable, sizeof(enable));
+	}
+
+	*avail_len -= len;
+
+	return res;
+}
+
+const wl_nan_sub_cmd_t *
+nan_get_subcmd_info(char **argv)
+{
+	char *cmdname = *argv;
+	const wl_nan_sub_cmd_t *p_subcmd_info = &nan_cmd_list[0];
+
+	while (p_subcmd_info->name != NULL) {
+		if (stricmp(p_subcmd_info->name, cmdname) == 0) {
+			return p_subcmd_info;
+		}
+		p_subcmd_info++;
+	}
+
+	return NULL;
+}
+
+static int
+nan_get_arg_count(char **argv)
+{
+	int count = 0;
+	while (*argv != NULL) {
+		if (strcmp(*argv, WL_IOV_BATCH_DELIMITER) == 0) {
+			break;
+		}
+		argv++;
+		count++;
+	}
+
+	return count;
+}
+
+static int
+wl_nan_control(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_USAGE_ERROR;
+	const wl_nan_sub_cmd_t *nancmd = NULL;
+	bcm_iov_batch_buf_t *b_buf = NULL;
+	uint8 *p_iov_buf;
+	uint16 iov_len, iov_len_start, subcmd_len, nancmd_data_len;
+	bool is_set = TRUE;
+	bool first_cmd_req = is_set;
+	int argc = 0;
+	/* Skip the command name */
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+	/* skip to cmd name after "nan" */
+	if (*argv) {
+		if (!strcmp(*argv, "-h") || !strcmp(*argv, "help"))  {
+			/* help , or -h* */
+			argv++;
+			wl_nan_help(NAN_HELP_ALL);
+			goto fail;
+		}
+	}
+
+	/*
+	 * malloc iov buf memory
+	 */
+	b_buf = (bcm_iov_batch_buf_t *)calloc(1, WLC_IOCTL_MEDLEN);
+	if (b_buf == NULL) {
+		return BCME_NOMEM;
+	}
+	/*
+	 * Fill the header
+	 */
+	iov_len = iov_len_start = WLC_IOCTL_MEDLEN;
+	b_buf->version = htol16(0x8000);
+	b_buf->count = 0;
+	p_iov_buf = (uint8 *)(&b_buf->cmds[0]);
+	iov_len -= OFFSETOF(bcm_iov_batch_buf_t, cmds[0]);
+
+	while (*argv != NULL) {
+		bcm_iov_batch_subcmd_t *sub_cmd =
+			(bcm_iov_batch_subcmd_t *)p_iov_buf;
+		/*
+		 * Lookup sub-command info
+		 */
+		nancmd = nan_get_subcmd_info(argv);
+		if (!nancmd) {
+			goto fail;
+		}
+		/* skip over sub-cmd name */
+		argv++;
+
+		/*
+		 * Get arg count for sub-command
+		 */
+		argc = nan_get_arg_count(argv);
+
+		sub_cmd->u.options =
+			htol32(BCM_XTLV_OPTION_ALIGN32);
+		/*
+		 * Skip over sub-command header
+		 */
+		iov_len -= OFFSETOF(bcm_iov_batch_subcmd_t, data);
+
+		/*
+		 * take a snapshot of curr avail len,
+		 * to calculate iovar data len to be packed.
+		 */
+		subcmd_len = iov_len;
+
+		/* invoke nan sub-command handler */
+		ret = nancmd->handler(wl, nancmd, argc, argv, &is_set,
+				(uint8 *)&sub_cmd->data[0], &subcmd_len);
+
+		if (ret != BCME_OK) {
+			goto fail;
+		}
+		nancmd_data_len = (iov_len - subcmd_len);
+		/*
+		 * In Batched commands, sub-commands TLV length
+		 * includes size of options as well. Because,
+		 * options are considered as part bcm xtlv data
+		 * considered as part bcm xtlv data
+		 */
+		nancmd_data_len += sizeof(sub_cmd->u.options);
+
+		/*
+		 * Data buffer is set NULL, because sub-cmd
+		 * tlv data is already filled by command hanlder
+		 * and no need of memcpy.
+		 */
+		ret = bcm_pack_xtlv_entry(&p_iov_buf, &iov_len,
+				nancmd->id, nancmd_data_len,
+				NULL, BCM_XTLV_OPTION_ALIGN32);
+
+		/*
+		 * iov_len is already compensated before sending
+		 * the buffer to cmd handler.
+		 * xtlv hdr and options size are compensated again
+		 * in bcm_pack_xtlv_entry().
+		 */
+		iov_len += OFFSETOF(bcm_iov_batch_subcmd_t, data);
+		if (ret == BCME_OK) {
+			/* Note whether first command is set/get */
+			if (!b_buf->count) {
+				first_cmd_req = is_set;
+			} else if (first_cmd_req != is_set) {
+				/* Returning error, if sub-sequent commands req is
+				 * not same as first_cmd_req type.
+				 */
+				 ret = BCME_UNSUPPORTED;
+				 break;
+			}
+
+			/* bump sub-command count */
+			b_buf->count++;
+			/* No more commands to parse */
+			if (*argv == NULL) {
+				break;
+			}
+			/* Still un parsed arguments exist and
+			 * immediate argument to parse is not
+			 * a BATCH_DELIMITER
+			 */
+			while (*argv != NULL) {
+				if (strcmp(*argv, WL_IOV_BATCH_DELIMITER) == 0) {
+					/* skip BATCH_DELIMITER i.e "+" */
+					argv++;
+					break;
+				}
+				argv++;
+			}
+		} else {
+			printf("Error handling sub-command %d\n", ret);
+			break;
+		}
+	}
+
+	/* Command usage error handling case */
+	if (ret != BCME_OK) {
+		goto fail;
+	}
+
+	iov_len = iov_len_start - iov_len;
+
+	/*
+	 * Dispatch iovar
+	 */
+	if (is_set) {
+		ret = wlu_var_setbuf(wl, "nan", (void *)b_buf, iov_len);
+	} else {
+		ret = wl_nan_do_get_ioctl(wl, (void *)b_buf, iov_len);
+	}
+
+fail:
+	if (ret != BCME_OK) {
+		printf("Error: %d\n", ret);
+		if (nancmd) {
+			wl_nan_help(nancmd->id);
+		} else {
+			wl_nan_help(NAN_HELP_ALL);
+		}
+	}
+	free(b_buf);
+	return ret;
+}
+
+static int
+wl_nan_subcmd_sync_tsreserve(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	chanspec_t chanspec;
+	wl_nan_timeslot_t tsconfig;
+	uint16 len;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(wl_nan_timeslot_t);
+		bzero(&tsconfig, sizeof(wl_nan_timeslot_t));
+		tsconfig.abitmap = strtoul(*argv, NULL, 0);
+		argv++;
+		if (tsconfig.abitmap) {
+			/* bitmap chanlist */
+			int i;
+			uint32 bitmap = tsconfig.abitmap;
+			for (i = 0; (i < NAN_MAX_TIMESLOT) && bitmap; i++) {
+				if (bitmap & (1 << i)) {
+					if (!*argv) {
+						fprintf(stderr, "missing chanspec\n");
+						goto fail;
+					}
+					if ((chanspec = wf_chspec_aton(*argv)) == 0) {
+						fprintf(stderr, "invalid chanspec %s\n", argv[0]);
+						res = BCME_BADARG;
+						goto fail;
+					}
+					tsconfig.chanlist[i] = chanspec;
+					bitmap &= ~(1 << i);
+					argv++;
+				}
+			}
+		} else {
+			/* bitmap chanspec duration */
+			if (*argv && *(argv + 1)) {
+				if ((chanspec = wf_chspec_aton(*argv)) == 0) {
+					fprintf(stderr, "%s: could not parse \"%s\" as channel\n",
+							cmd->name, argv[0]);
+					res = BCME_BADARG;
+					goto fail;
+				}
+				tsconfig.chanlist[0] = wl_chspec_to_driver(chanspec);
+				tsconfig.chanlist[1] = atoi(*(argv + 1));
+			} else if (!*argv) {
+				fprintf(stderr, "missing chanspec\n");
+				goto fail;
+			} else {
+				fprintf(stderr, "missing duration\n");
+				goto fail;
+			}
+		}
+		memcpy(iov_data, (uint8 *)&tsconfig, sizeof(wl_nan_timeslot_t));
+	}
+	*avail_len -= len;
+
+fail:
+	return res;
+}
+
+static int
+wl_nan_subcmd_sync_tsrelease(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	wl_nan_ts_bitmap_t rbitmap;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	*is_set = TRUE;
+	rbitmap =  strtoul(*argv, NULL, 0);
+	memcpy(iov_data, (uint8 *)&rbitmap, sizeof(rbitmap));
+	*avail_len -= sizeof(rbitmap);
+
+	return res;
+}
+static int
+wl_nan_subcmd_cfg_oui(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	wl_nan_oui_type_t *nan_oui_type;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		if (ARGCNT(argv) < WL_NAN_CMD_CFG_OUI_ARGC) {
+			return BCME_USAGE_ERROR;
+		}
+
+		*is_set = TRUE;
+		len = sizeof(*nan_oui_type);
+
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		nan_oui_type = (wl_nan_oui_type_t *)iov_data;
+
+		if (get_oui_bytes((uchar *)(*argv), (uchar *)nan_oui_type->nan_oui)) {
+			fprintf(stderr, "invalid OUI\n");
+			return BCME_BADARG;
+		}
+
+		/* advance to the next param */
+		argv++;
+
+		nan_oui_type->type =  strtoul(*argv, NULL, 0);
+	}
+
+	*avail_len -= len;
+
+	return res;
+}
+
+static void
+print_peer_rssi(wl_nan_peer_rssi_data_t *prssi)
+{
+	uint16 peer_cnt, rssi_cnt;
+	wl_nan_peer_rssi_entry_t *peer;
+	char buf[MAX_MAC_BUF] = {'\0'};
+	char raw_rssi[MAX_RSSI_BUF] = {'\0'};
+	char avg_rssi[MAX_RSSI_BUF] = {'\0'};
+	size_t raw_sz_left, avg_sz_left;
+	uint16 raw_sz = 0, avg_sz = 0;
+
+	printf("> RSSI Data: \n");
+	printf("no of peers: %d\n", prssi->peer_cnt);
+	for (peer_cnt = 0; peer_cnt < prssi->peer_cnt; peer_cnt++) {
+		peer = &prssi->peers[peer_cnt];
+		bcm_ether_ntoa(&peer->mac, buf);
+		raw_sz_left = avg_sz_left = 128;
+		raw_sz = avg_sz = 0;
+		for (rssi_cnt = 0; rssi_cnt < peer->rssi_cnt; rssi_cnt++) {
+			raw_sz += snprintf(raw_rssi+raw_sz, MAX_RSSI_BUF-raw_sz,
+				"%d(%u) ", peer->rssi[rssi_cnt].rssi_raw,
+				peer->rssi[rssi_cnt].rx_chan);
+			raw_sz_left -= raw_sz;
+			avg_sz += snprintf(avg_rssi+avg_sz, MAX_RSSI_BUF-avg_sz,
+				"%d(%u) ", peer->rssi[rssi_cnt].rssi_avg,
+				peer->rssi[rssi_cnt].rx_chan);
+			avg_sz_left -= avg_sz;
+		}
+		if (prssi->flags & WL_NAN_PEER_RSSI) {
+			printf("%s %s %s \n", buf, raw_rssi, avg_rssi);
+		}
+		else if (prssi->flags & WL_NAN_PEER_RSSI_LIST)
+		{
+			printf("%s\n", buf);
+			printf("raw: %s\n", raw_rssi);
+			printf("avg: %s\n", avg_rssi);
+		} else {
+			/* Invalid */
+		}
+	}
+}
+
+static int
+wl_nan_subcmd_dump(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int ret = BCME_OK;
+	wl_nan_dbg_dump_type_t dump_type;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* It is always a get */
+	*is_set = FALSE;
+
+	if (!argv[0] || argc != 1) {
+		printf("Incorrect number of parameters.\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	if (!strcmp(argv[0], "rssi")) {
+		dump_type = WL_NAN_DBG_DT_RSSI_DATA;
+	} else if (!strcmp(argv[0], "stats")) {
+		dump_type = WL_NAN_DBG_DT_STATS_DATA;
+	} else {
+		printf("Invalid argument %s.\n", argv[0]);
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	len = sizeof(dump_type);
+
+	if (len > *avail_len) {
+		printf("Buf short, requested:%d, available:%d\n",
+				len, *avail_len);
+		return BCME_BUFTOOSHORT;
+	}
+
+	memcpy(iov_data, &dump_type, len);
+	*avail_len -= len;
+
+exit:
+	return ret;
+}
+
+static int
+wl_nan_subcmd_dbg_level(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint16 len;
+	wl_nan_dbg_level_t dbg_level;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(is_set);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(wl_nan_dbg_level_t);
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		memset(&dbg_level, 0, len);
+		if ((*argv != NULL)) {
+			dbg_level.nan_err_level = strtoul(*argv, NULL, 16);
+			argv++;
+			if ((*argv != NULL)) {
+				dbg_level.nan_dbg_level = strtoul(*argv, NULL, 16);
+				argv++;
+				if ((*argv != NULL)) {
+					dbg_level.nan_info_level = strtoul(*argv, NULL, 16);
+				}
+			}
+		}
+		memcpy(iov_data, (uint8 *)&dbg_level, sizeof(wl_nan_dbg_level_t));
+	}
+
+	*avail_len -= len;
+	return res;
+}
+
+static int
+wl_nan_subcmd_clear(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int ret = BCME_OK;
+	wl_nan_dbg_dump_type_t clear_type;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* It is always set */
+	*is_set = TRUE;
+
+	if (!argv[0] || argc != 1) {
+		printf("Incorrect number of parameters.\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	if (!strcmp(argv[0], "rssi")) {
+		clear_type = WL_NAN_DBG_DT_RSSI_DATA;
+	} else if (!strcmp(argv[0], "stats")) {
+		clear_type = WL_NAN_DBG_DT_STATS_DATA;
+	} else {
+		printf("Invalid argument %s.\n", argv[0]);
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	len = sizeof(clear_type);
+
+	if (len > *avail_len) {
+		printf("Buf short, requested:%d, available:%d\n",
+				len, *avail_len);
+		return BCME_BUFTOOSHORT;
+	}
+
+	memcpy(iov_data, &clear_type, len);
+	*avail_len -= len;
+
+exit:
+	return ret;
+}
+
+/* nan 2.0 iovars */
+
+/* device capabilities */
+static int
+wl_nan_subcmd_dp_cap(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	return res;
+}
+
+/* status */
+static int
+wl_nan_subcmd_dp_status(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint8 ndp_id;
+	uint16 len;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if (*argv == NULL) {
+		return BCME_IOCTL_ERROR;
+	} else {
+		/* set is not supported */
+		*is_set = FALSE;
+		ndp_id = atoi(*argv);
+
+		if (ndp_id == 255) {
+			return BCME_BADARG;
+		}
+		len = sizeof(ndp_id);
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+		memcpy(iov_data, &ndp_id, sizeof(ndp_id));
+	}
+	*avail_len -= len;
+	return res;
+}
+
+/* statistics */
+static int
+wl_nan_subcmd_dp_stats(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	return res;
+}
+
+/* schedule update */
+static int
+wl_nan_subcmd_dp_schedupd(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(is_set);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	return res;
+}
+
+enum {
+	NAN_DP_CFG_TYPE_UCAST		= 0x0001,
+	NAN_DP_CFG_TYPE_MCAST		= 0x0002,
+	NAN_DP_CFG_SECURITY		= 0x0003,
+	NAN_DP_CFG_QOS			= 0x0004,
+	NAN_DP_CFG_PUB_INST		= 0x0005,
+	NAN_DP_CFG_PEER_IFADDR		= 0x0006,
+	NAN_DP_CFG_MCAST_IFADDR		= 0x0007,
+	NAN_DP_CFG_DATA_IFADDR		= 0x0008,
+	NAN_DP_CFG_SVC_SPEC_INFO	= 0x0009,
+	NAN_DP_CFG_NDPID		= 0x000a,
+	NAN_DP_CFG_STATUS		= 0x000b,
+	NAN_DP_CFG_REASON_CODE		= 0x000c,
+	NAN_DP_CFG_AVAIL		= 0x000d,
+	NAN_DP_CFG_INIT_DATA_IFADDR	= 0x000e,
+	NAN_DP_CFG_CONFIRM		= 0x000f
+};
+
+typedef struct nan_dp_config_param_info {
+	char *name;	/* <param-name> string to identify the config item */
+	uint16 id;
+	uint16 len; /* len in bytes */
+	char *help_msg; /* Help message */
+} nan_dp_config_param_info_t;
+
+/*
+ * Parameter name and size for service discovery IOVARs
+ */
+static const nan_dp_config_param_info_t nan_dp_config_param_info[] = {
+	/* param-name	param_id	len	help message */
+	{"ucast",	NAN_DP_CFG_TYPE_UCAST,		0,
+	"unicast req"},
+	{"mcast",	NAN_DP_CFG_TYPE_MCAST,		0,
+	"multicast req"},
+	{"pub_id",	NAN_DP_CFG_PUB_INST,		sizeof(uint16),
+	"public instance id"},
+	{"status",	NAN_DP_CFG_STATUS,		sizeof(uint8),
+	"response frame status"},
+	{"confirm",	NAN_DP_CFG_CONFIRM,		sizeof(uint8),
+	"sets confirm/explicit confirm for dp_req/dp_resp"},
+	{"reason",	NAN_DP_CFG_REASON_CODE,		sizeof(uint8),
+	"response frame reason code"},
+	{"ndp_id",	NAN_DP_CFG_NDPID,		sizeof(uint8),
+	"Local ndp_id of peer"},
+	{"security",	NAN_DP_CFG_SECURITY,		sizeof(uint8),
+	"is security enabled"},
+	{"peer_mac",	NAN_DP_CFG_PEER_IFADDR,		ETHER_ADDR_LEN,
+	"peer mac address"},
+	{"data_mac",	NAN_DP_CFG_DATA_IFADDR,		ETHER_ADDR_LEN,
+	"local data mac address"},
+	{"init_data_mac", NAN_DP_CFG_INIT_DATA_IFADDR,	ETHER_ADDR_LEN,
+	"Initiators data address(used in dataresp)"},
+	{"mcast_mac",	NAN_DP_CFG_MCAST_IFADDR,	ETHER_ADDR_LEN,
+	"multicast mac address"},
+	{"qos",		NAN_DP_CFG_QOS,			sizeof(wl_nan_dp_qos_t),
+	"qos <tid> <pkt size> <mean rate> <svc_interval>"},
+	{"svc_spec_info", NAN_DP_CFG_SVC_SPEC_INFO,	WL_NAN_DP_MAX_SVC_INFO,
+	"service specific info"},
+	{"avail",	NAN_DP_CFG_AVAIL,		(OFFSETOF(wl_nan_ndp_config_t, data) +
+	WL_AVAIL_ALLOC_SIZE(WLU_AVAIL_MAX_SLOTS)),
+	"availability window"}
+};
+
+const nan_dp_config_param_info_t *
+nan_lookup_dp_config_param(char *param_name)
+{
+	int i = 0;
+	const nan_dp_config_param_info_t *param_p = &nan_dp_config_param_info[0];
+
+	for (i = 0; i < (int)ARRAYSIZE(nan_dp_config_param_info); i++) {
+		if (stricmp(param_p->name, param_name) == 0) {
+			return param_p;
+		}
+		param_p++;
+	}
+
+	return NULL;
+}
+
+static int
+wl_nan_subcmd_dp_autoconn(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint8 autoconn = 0;
+	uint16 len;
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+		len = 0;
+	} else {
+		*is_set = TRUE;
+		len = sizeof(autoconn);
+
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		autoconn = (uint8)atoi(*argv);
+		if (autoconn & WL_NAN_AUTO_DPRESP) {
+			printf("auto_dpresp enabled \n");
+		} else {
+			printf("auto_dpresp disabled \n");
+		}
+		if (autoconn & WL_NAN_AUTO_DPCONF) {
+			printf("auto_dpconf enabled \n");
+		} else {
+			printf("auto_dpconf disabled \n");
+		}
+		memcpy(iov_data, &autoconn, sizeof(autoconn));
+	}
+
+	*avail_len -= len;
+
+	return res;
+}
+
+int
+wl_nan_get_qos_params(char **argv, wl_nan_dp_qos_t *qos, uint8 *qos_num_params)
+{
+	if (*argv != NULL) {
+		qos->tid = (uint8)atoi(*argv);
+		argv++;
+		(*qos_num_params)++;
+
+		if (*argv != NULL) {
+			qos->pkt_size = (uint16)atoi(*argv);
+			argv++;
+			(*qos_num_params)++;
+
+			if (*argv != NULL) {
+				qos->mean_rate = (uint16)atoi(*argv);
+				argv++;
+				(*qos_num_params)++;
+
+				if (*argv != NULL) {
+					qos->svc_interval = (uint16)atoi(*argv);
+					(*qos_num_params)++;
+					return BCME_OK;
+				}
+			}
+		}
+	}
+	return BCME_ERROR;
+}
+
+static int
+wl_nan_subcmd_dp_req(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	wl_nan_dp_req_t *datareq = NULL;
+	int ret = BCME_OK;
+	uint16 len = 0;
+	uint8 qos_num_params = 0;
+	const nan_dp_config_param_info_t *param_p = NULL;
+
+	uint8 *pxtlv;
+	uint16 buflen = *avail_len, buflen_at_start;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if (*argv == NULL) {
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	datareq = (wl_nan_dp_req_t *)iov_data;
+	pxtlv = (uint8 *)&datareq->svc_spec_info;
+
+	if (*avail_len < sizeof(*datareq)) {
+		/* buffer is insufficient */
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+
+	/* Setting default data path type to unicast */
+	datareq->type = WL_NAN_DP_TYPE_UNICAST;
+
+	*is_set = FALSE;
+
+	/* Parse optional args. Validity is checked by discovery engine */
+	while (*argv != NULL) {
+		if ((param_p = nan_lookup_dp_config_param(*argv)) == NULL) {
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		/*
+		 * Skip param name
+		 */
+		argv++;
+		switch (param_p->id) {
+
+		case NAN_DP_CFG_TYPE_UCAST:
+			datareq->type = WL_NAN_DP_TYPE_UNICAST;
+			break;
+
+		case NAN_DP_CFG_TYPE_MCAST:
+			datareq->type = WL_NAN_DP_TYPE_MULTICAST;
+			break;
+
+		case NAN_DP_CFG_CONFIRM:
+			datareq->flag |= WL_NAN_DP_FLAG_CONFIRM;
+			break;
+
+		case NAN_DP_CFG_SECURITY:
+			if (*argv != NULL) {
+				datareq->security = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_DP_CFG_QOS:
+			ret = wl_nan_get_qos_params(argv, &datareq->qos, &qos_num_params);
+			if (ret != BCME_OK) {
+				return ret;
+			}
+			argv += qos_num_params;
+			break;
+
+		case NAN_DP_CFG_PUB_INST:
+			if (*argv != NULL) {
+				datareq->pub_id = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_DP_CFG_PEER_IFADDR:
+			if (*argv) {
+				if (!wl_ether_atoe(argv[0], &datareq->peer_mac)) {
+					printf("Malformed MAC address parameter\n");
+					break;
+				}
+				argv++;
+			}
+			break;
+
+		case NAN_DP_CFG_MCAST_IFADDR:
+			if (*argv != NULL) {
+				if (datareq->type != WL_NAN_DP_TYPE_MULTICAST) {
+					printf("ERROR: multicast mac addr specified"
+							"with unicast type\n");
+					return BCME_ERROR;
+				}
+				if (!wl_ether_atoe(argv[0], &datareq->mcast_mac)) {
+					printf("Malformed MAC address parameter\n");
+					break;
+				}
+				argv++;
+			}
+			break;
+
+		case NAN_DP_CFG_SVC_SPEC_INFO:
+			if (*argv) {
+				buflen_at_start = buflen;
+				ret = bcm_pack_xtlv_entry_from_hex_string(&pxtlv,
+						&buflen, WL_NAN_XTLV_SVC_INFO, *argv);
+				if (ret != BCME_OK) {
+					printf("unable to process svc_spec_info: %d\n", ret);
+					return ret;
+				}
+				len += (uint8)(buflen_at_start - buflen);
+				datareq->flag |= WL_NAN_DP_FLAG_SVC_INFO;
+				argv++;
+			}
+			break;
+
+		default:
+			return BCME_ERROR;
+			break;
+
+		} /* switch */
+	} /* while */
+
+	len += OFFSETOF(wl_nan_dp_req_t, svc_spec_info);
+	*avail_len -= len;
+
+exit:
+	return ret;
+}
+
+static int
+wl_nan_subcmd_dp_resp(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	wl_nan_dp_resp_t *dataresp = NULL;
+	int ret = BCME_OK;
+	uint16 len = 0;
+	uint8 qos_num_params = 0;
+	const nan_dp_config_param_info_t *param_p = NULL;
+
+	uint8 *pxtlv;
+	uint16 buflen = *avail_len, buflen_at_start;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if (*argv == NULL) {
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	dataresp = (wl_nan_dp_resp_t *)iov_data;
+	pxtlv = (uint8 *)&dataresp->svc_spec_info;
+
+	if (*avail_len < sizeof(*dataresp)) {
+		/* buffer is insufficient */
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+
+	/* Setting default data path type to unicast */
+	dataresp->type = WL_NAN_DP_TYPE_UNICAST;
+
+	*is_set = FALSE;
+
+	/* Parse optional args. Validity is checked by discovery engine */
+	while (*argv != NULL) {
+		if ((param_p = nan_lookup_dp_config_param(*argv)) == NULL) {
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		/*
+		 * Skip param name
+		 */
+		argv++;
+		switch (param_p->id) {
+
+		case NAN_DP_CFG_TYPE_UCAST:
+			dataresp->type = WL_NAN_DP_TYPE_UNICAST;
+			break;
+
+		case NAN_DP_CFG_TYPE_MCAST:
+			dataresp->type = WL_NAN_DP_TYPE_MULTICAST;
+			break;
+
+		case NAN_DP_CFG_CONFIRM:
+			dataresp->flag |= WL_NAN_DP_FLAG_EXPLICIT_CFM;
+			break;
+
+		case NAN_DP_CFG_SECURITY:
+			if (*argv != NULL) {
+				dataresp->security = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_DP_CFG_STATUS:
+			if (*argv != NULL) {
+				dataresp->status = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_DP_CFG_REASON_CODE:
+			if (*argv != NULL) {
+				dataresp->reason_code = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_DP_CFG_QOS:
+			ret = wl_nan_get_qos_params(argv, &dataresp->qos, &qos_num_params);
+			if (ret != BCME_OK) {
+				return ret;
+			}
+			argv += qos_num_params;
+			break;
+
+		case NAN_DP_CFG_NDPID:
+			if (*argv != NULL) {
+				dataresp->ndp_id = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_DP_CFG_PEER_IFADDR:
+		case NAN_DP_CFG_MCAST_IFADDR:
+			if (*argv != NULL) {
+				if (!wl_ether_atoe(argv[0], &dataresp->mac_addr)) {
+					printf("Malformed MAC address parameter\n");
+					break;
+				}
+				argv++;
+			}
+			break;
+
+		case NAN_DP_CFG_SVC_SPEC_INFO:
+			if (*argv) {
+				buflen_at_start = buflen;
+				ret = bcm_pack_xtlv_entry_from_hex_string(&pxtlv,
+						&buflen, WL_NAN_XTLV_SVC_INFO, *argv);
+				if (ret != BCME_OK) {
+					printf("unable to process svc_spec_info: %d\n", ret);
+					return ret;
+				}
+				len += (uint8)(buflen_at_start - buflen);
+				dataresp->flag |= WL_NAN_DP_FLAG_SVC_INFO;
+				argv++;
+			}
+			break;
+
+		default:
+			return BCME_ERROR;
+			break;
+
+		} /* switch */
+	} /* while */
+
+	len += OFFSETOF(wl_nan_dp_resp_t, svc_spec_info);
+	*avail_len -= len;
+
+exit:
+	return ret;
+}
+
+static int
+wl_nan_subcmd_dp_conf(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint8 ndp_id;
+	uint8 status;
+	uint16 len;
+	wl_nan_dp_conf_t *dataconf = (wl_nan_dp_conf_t *)iov_data;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if ((*argv == NULL) || (*argv != NULL && argc < 2)) {
+		return BCME_IOCTL_ERROR;
+	} else {
+		*is_set = TRUE;
+		ndp_id = atoi(*argv);
+
+		if (ndp_id == WL_NAN_INVALID_NDPID) {
+			return BCME_BADARG;
+		}
+
+		len = sizeof(*dataconf);
+
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		argv++;
+		status = atoi(*argv);
+
+		dataconf->lndp_id = ndp_id;
+		dataconf->status = status;
+	}
+
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_dp_dataend(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+	uint8 ndp_id;
+	uint8 status;
+	uint16 len;
+	wl_nan_dp_end_t dataend;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if ((*argv == NULL) || (*argv != NULL && argc < 2)) {
+		return BCME_IOCTL_ERROR;
+	} else {
+		/* get is not supported */
+		*is_set = TRUE;
+		ndp_id = atoi(*argv);
+
+		if (ndp_id == WL_NAN_INVALID_NDPID) {
+			return BCME_BADARG;
+		}
+
+		len = sizeof(dataend);
+
+		if (len > *avail_len) {
+			printf("Buf short, requested:%d, available:%d\n",
+					len, *avail_len);
+			return BCME_BUFTOOSHORT;
+		}
+
+		argv++;
+		status = atoi(*argv);
+		dataend.lndp_id = ndp_id;
+		dataend.status = status;
+
+		memcpy(iov_data, &dataend, sizeof(dataend));
+	}
+
+	*avail_len -= len;
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_dp_show(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int res = BCME_OK;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(iov_data);
+	UNUSED_PARAMETER(avail_len);
+
+	if ((*argv != NULL) || argc != 0) {
+		return BCME_IOCTL_ERROR;
+	} else {
+		/* only get is supported */
+		*is_set = FALSE;
+	}
+
+	return res;
+}
+
+static int
+wl_nan_subcmd_cfg_avail(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int ret = BCME_OK;
+	bool started = FALSE;
+	wl_avail_new_t *avail = (wl_avail_new_t *)iov_data;
+	wl_avail_entry_t *entry;		/* used for filling entry structure */
+	uint8 *p = avail->entry;		/* tracking pointer */
+	uint8 avail_type;	/* 1=local, 2=peer, 3=ndc, 4=immutable, 5=response, 6=counter */
+	uint8 entry_type;	/* 1=committed, 2=potential */
+	uint8 optional_num;
+
+	UNUSED_PARAMETER(argc);
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if (*argv == NULL) {
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	avail_type = atoi(*argv++);
+	if (avail_type < WL_AVAIL_LOCAL || avail_type > WL_AVAIL_TYPE_MAX) {
+		printf("Invalid availability type\n");
+		ret = BCME_USAGE_ERROR; goto exit;
+	}
+
+	/* check for GET first */
+	if (*argv == NULL || argc == 1) {
+		if ((avail_type >= WL_AVAIL_LOCAL) &&
+				(avail_type <= WL_AVAIL_TYPE_MAX)) {
+			memcpy(iov_data, &avail_type, sizeof(avail_type));
+			*avail_len -= sizeof(avail_type);
+			*is_set = FALSE;
+			goto exit;
+		}
+	}
+
+	*is_set = TRUE;
+	/* populate wl_avail fields */
+	avail->flags = avail_type;
+	avail->time_ref = WL_TIME_REF_NAN_DW0;
+	avail->length = sizeof(*avail);
+	avail->num_entries = 0;
+
+	printf("\nType (1=local, 2=peer, 3=ndc, 4=immutable, 5=response, "
+		"6=counter, 7=ranging): %d\n", avail_type);
+	/* populate avail entries */
+	while (*argv != NULL) {
+		entry = (wl_avail_entry_t*)p;
+		if ((stricmp(*argv++, "entry") != 0)) {
+			prhex("argv", (uchar*)*argv, 7);
+			if (!started) {
+				printf("Missing avail entry type\n");
+				ret = BCME_USAGE_ERROR; goto exit;
+			}
+			break;
+		} else {
+			started = TRUE;
+			entry_type = atoi(*argv++);
+			if ((entry_type == (WL_AVAIL_ENTRY_COM | WL_AVAIL_ENTRY_COND)) ||
+					(entry_type >= (WL_AVAIL_ENTRY_COM |
+					WL_AVAIL_ENTRY_POT | WL_AVAIL_ENTRY_COND))) {
+				printf("Invalid entry type\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			entry->flags = entry_type;
+		}
+		/* optional parameters */
+		optional_num = 0;
+		if ((ret = wl_nan_set_avail_entry_optional(argv, avail, entry,
+				avail_type, &optional_num)) != BCME_OK) {
+			goto exit;
+		}
+
+		/* update wl_avail and populate wl_avail_entry */
+		entry->length = htod16(sizeof(*entry) + entry->bitmap_len);
+		entry->flags = htod16(entry->flags);
+		avail->num_entries++;
+		avail->length += entry->length;
+
+		/* advance pointer for next entry */
+		p += entry->length;
+		argv += optional_num;
+
+		/* output configuration info */
+		wlu_nan_print_wl_avail_entry(avail_type & WL_AVAIL_TYPE_MASK, entry);
+	}
+
+	/* update avail_len only if there are avail entries */
+	if (avail->num_entries) {
+		*avail_len -= avail->length;
+	}
+	avail->length = htod16(avail->length);
+
+	prhex("\ntotal wl_avail", (uchar*)avail, avail->length);
+exit:
+	return ret;
+}
+
+#define WLU_AVAIL_NUM_ARGS_PER_PARAM	2
+/* process optional parameters and sets them in wl_avail_entry */
+static int
+wl_nan_set_avail_entry_optional(char** argv, wl_avail_new_t* avail, wl_avail_entry_t* entry,
+	uint8 avail_type, uint8* num)
+{
+	int ret = BCME_OK;
+	uint8 i;
+	char *a;
+	uint8 bitdur_type;
+	uint8 period_type;
+	uint16 offset;		/* start offset, 0-511 */
+	uint8 usage;		/* usage preference, 0-3 */
+	uint32 chanspec;	/* 0=all channels/bands */
+	uint32 band;		/* 0=all bands, 1=sub-1G, 2=2.4G, 4=5G */
+	struct ether_addr ndc_id;
+	struct ether_addr peer_nmi;
+	char def_ndc_id[ETHER_ADDR_LEN] = { 0xAA, 0xBB, 0xCC, 0x00, 0x0, 0x0 };
+	char def_peer_nmi[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0xaa, 0xbb, 0xcc };
+
+	/* set default values for optional parameters */
+	entry->start_offset = 0;
+	entry->u.band = 0;
+	entry->period = WL_AVAIL_PERIOD_512;
+	entry->flags |= (3 << WL_AVAIL_ENTRY_USAGE_SHIFT) |
+		(WL_AVAIL_BIT_DUR_16 << WL_AVAIL_ENTRY_BIT_DUR_SHIFT);
+	if (avail_type == WL_AVAIL_NDC) {
+		memcpy(&avail->u.addr, def_ndc_id, ETHER_ADDR_LEN);
+	} else if (avail_type == WL_AVAIL_PEER) {
+		memcpy(&avail->u.addr, def_peer_nmi, ETHER_ADDR_LEN);
+	}
+	entry->bitmap_len = 0;
+
+	/* parse optional parameters */
+	while ((*argv != NULL) && (stricmp(*argv, "entry") != 0)) {
+		if ((stricmp(*argv, "bitdur") == 0)) {
+			argv++;
+			bitdur_type = atoi(*argv++);
+			/* by design, local avail slots are 16TU */
+			if (bitdur_type > WL_AVAIL_BIT_DUR_128) {
+				printf("Invalid bitdur type\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			entry->flags |= bitdur_type << WL_AVAIL_ENTRY_BIT_DUR_SHIFT;
+		} else if ((stricmp(*argv, "period") == 0)) {
+			argv++;
+			period_type = atoi(*argv++);
+			if (period_type > WL_AVAIL_PERIOD_8192) {
+				printf("Invalid period type\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			entry->period = period_type;
+		} else if ((stricmp(*argv, "offset") == 0)) {
+			argv++;
+			offset = atoi(*argv++);
+			if (offset > 511) {
+				printf("Invalid offset\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			entry->start_offset = htod16(offset);
+		} else if ((stricmp(*argv, "usage") == 0)) {
+			argv++;
+			usage = atoi(*argv++);
+			if (usage > 3) {
+				printf("Invalid usage pref\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			entry->flags &= ~(WL_AVAIL_ENTRY_USAGE_MASK);
+			entry->flags |= usage << WL_AVAIL_ENTRY_USAGE_SHIFT;
+		} else if ((stricmp(*argv, "ndc") == 0)) {
+			argv++;
+			if (avail_type != WL_AVAIL_NDC) {
+				printf("ndc id is for type ndc\n");
+				ret = BCME_USAGE_ERROR; goto exit;
+			}
+			if (!wl_ether_atoe(*argv++, &ndc_id)) {
+				printf("Invalid ndc id\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			memcpy(&avail->u.addr, &ndc_id, ETHER_ADDR_LEN);
+		} else if ((stricmp(*argv, "chanspec") == 0)) {
+			argv++;
+			chanspec = wf_chspec_aton(*argv++);
+			if (chanspec == 0) {
+				printf("Invalid chanspec\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			entry->flags |= 1 << WL_AVAIL_ENTRY_CHAN_SHIFT;
+			entry->u.channel_info = htod32(chanspec);
+		} else if ((stricmp(*argv, "band") == 0)) {
+			argv++;
+			band = atoi(*argv++);
+			if (band > 4) {
+				printf("Invalid band\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			entry->flags |= 1 << WL_AVAIL_ENTRY_BAND_SHIFT;
+			entry->u.band = htod32(band);
+		} else if ((stricmp(*argv, "bitmap") == 0)) {
+			argv++;
+			/* point to bitmap value for processing */
+			a = *argv;
+			for (i = 0; i < strlen(*argv); i++) {
+				if (*a == '1') {
+					setbit(entry->bitmap, i);
+				}
+				a++;
+			}
+			argv++;
+			/* account for partially filled most significant byte */
+			entry->bitmap_len = (i + NBBY - 1) / NBBY;
+		} else if (stricmp(*argv, "otahexmap") == 0) {
+			argv++;
+			entry->bitmap_len = (strlen(*argv) + 1) / 2;
+			if (get_ie_data((uchar*)*argv++, entry->bitmap, entry->bitmap_len)) {
+				ret = BCME_BADARG;
+				goto exit;
+			}
+		/* peer nmi address for peer NA */
+		} else if ((stricmp(*argv, "peer") == 0)) {
+			/* peer nmi address for peer NA */
+			argv++;
+			if (avail_type != WL_AVAIL_PEER) {
+				printf("peer nmi is for type peer\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			if (!wl_ether_atoe(*argv++, &peer_nmi)) {
+				printf("Invalid peer nmi\n");
+				ret = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			memcpy(&avail->u.addr, &peer_nmi, ETHER_ADDR_LEN);
+		} else {
+			printf("Recognized parameter %s\n", *argv);
+			ret = BCME_BADARG;
+			*num = 0;
+			goto exit;
+		}
+		(*num)++;
+		/* TODO add option for channel entry in hex data (opclass + bitmap) */
+
+		/* TODO add option for entire avail entry in hex data */
+	}
+exit:
+	*num *= WLU_AVAIL_NUM_ARGS_PER_PARAM;
+	return ret;
+}
+
+typedef struct nan_rng_config_param_info {
+	char *name;	/* <param-name> string to identify the config item */
+	uint16 id;
+	uint16 len; /* len in bytes */
+	char *help_msg; /* Help message */
+} nan_rng_config_param_info_t;
+enum {
+	NAN_RNG_CFG_PEER	= 0x0001,
+	NAN_RNG_CFG_RANGE_ID	= 0x0002,
+	NAN_RNG_CFG_PUB_ID	= 0x0003,
+	NAN_RNG_CFG_INTERVAL	= 0x0004,
+	NAN_RNG_CFG_RESOLUTION	= 0x0005,
+	NAN_RNG_CFG_INDICATION	= 0x0006,
+	NAN_RNG_CFG_INGRESS_LIMIT	= 0x0007,
+	NAN_RNG_CFG_EGRESS_LIMIT	= 0x0008,
+	NAN_RNG_CFG_RESULT_REQUIRED	= 0x0009,
+	NAN_RNG_CFG_AUTO_RESPONSE	= 0x000a,
+	NAN_RNG_CFG_RANGE_STATUS	= 0x000b
+};
+
+
+/*
+ * Parameter name and size for service discovery IOVARs
+ */
+static const nan_rng_config_param_info_t nan_rng_config_param_info[] = {
+	/* param-name	param_id	len	help message */
+	{"range_id",	NAN_RNG_CFG_RANGE_ID,		sizeof(uint8),
+	"unique handle"},
+	{"peer",	NAN_RNG_CFG_PEER,		ETHER_ADDR_LEN,
+	"ranging peer"},
+	{"pub_id",	NAN_RNG_CFG_PUB_ID,		sizeof(uint8),
+	"range service public instance id"},
+	{"resolution",	NAN_RNG_CFG_RESOLUTION,		sizeof(uint32),
+	"resolution of distance"},
+	{"interval",	NAN_RNG_CFG_INTERVAL,		sizeof(uint32),
+	"interval in TU b/w ranging sessions"},
+	{"indication",	NAN_RNG_CFG_INDICATION,		sizeof(uint8),
+	"eventing condition, cont/ingress/egress/both"},
+	{"ingress",	NAN_RNG_CFG_INGRESS_LIMIT,		sizeof(uint32),
+	"ingress distance condition"},
+	{"egress",	NAN_RNG_CFG_EGRESS_LIMIT,		sizeof(uint32),
+	"egress distance condition"},
+	{"result",	NAN_RNG_CFG_RESULT_REQUIRED,		0,
+	"report required from peer"},
+	{"auto",	NAN_RNG_CFG_AUTO_RESPONSE,		0,
+	"auto respond to range req"},
+	{"status",	NAN_RNG_CFG_RANGE_STATUS,		sizeof(uint8),
+	"host status whether accepted or rejected"},
+};
+
+const nan_rng_config_param_info_t *
+nan_lookup_rng_config_param(char *param_name)
+{
+	int i = 0;
+	const nan_rng_config_param_info_t *param_p = &nan_rng_config_param_info[0];
+
+	for (i = 0; i < (int)ARRAYSIZE(nan_rng_config_param_info); i++) {
+		if (stricmp(param_p->name, param_name) == 0) {
+			return param_p;
+		}
+		param_p++;
+	}
+
+	return NULL;
+}
+
+static int
+wl_nan_subcmd_range_req(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	wl_nan_range_req_t *range_req = NULL;
+	int ret = BCME_OK;
+	uint16 len = 0;
+	const nan_rng_config_param_info_t *param_p = NULL;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if (*argv == NULL) {
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	range_req = (wl_nan_range_req_t *)iov_data;
+
+
+	if (*avail_len < NAN_RNG_REQ_IOV_LEN) {
+		/* buffer is insufficient */
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+
+	*is_set = FALSE;
+
+	/* Parse optional args. Validity is checked by discovery engine */
+	while (*argv != NULL) {
+		if ((param_p = nan_lookup_rng_config_param(*argv)) == NULL) {
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		/*
+		 * Skip param name
+		 */
+		argv++;
+		switch (param_p->id) {
+
+		case NAN_RNG_CFG_PUB_ID:
+			if (*argv != NULL) {
+				range_req->publisher_id = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_PEER:
+			if (*argv != NULL) {
+				if (!wl_ether_atoe(argv[0], &range_req->peer)) {
+					printf("Malformed MAC address parameter\n");
+					break;
+				}
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_INDICATION:
+			if (*argv != NULL) {
+				range_req->indication = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_RESOLUTION:
+			if (*argv != NULL) {
+				range_req->resolution = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_INGRESS_LIMIT:
+			if (*argv != NULL) {
+				range_req->ingress = (uint32)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_EGRESS_LIMIT:
+			if (*argv != NULL) {
+				range_req->egress = (uint32)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_INTERVAL:
+			if (*argv != NULL) {
+				range_req->interval = (uint16)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		default:
+			return BCME_ERROR;
+			break;
+		}
+	}
+	len += NAN_RNG_REQ_IOV_LEN;
+	*avail_len -= len;
+exit:
+	return ret;
+}
+
+static int
+wl_nan_subcmd_range_auto(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	int ret = BCME_OK;
+	uint16 len = 0;
+	uint8 auto_accept = 0;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if (*argv == NULL) {
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	if (*avail_len < sizeof(auto_accept)) {
+		/* buffer is insufficient */
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+
+	*is_set = TRUE;
+
+	*iov_data = auto_accept = (uint8)(atoi(*argv));
+
+	len += sizeof(auto_accept);
+	*avail_len -= len;
+exit:
+	return ret;
+
+}
+
+static int
+wl_nan_subcmd_range_resp(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	wl_nan_range_resp_t *range_resp = NULL;
+	int ret = BCME_OK;
+	uint16 len = 0;
+	uint8 flags = 0;
+	const nan_rng_config_param_info_t *param_p = NULL;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if (*argv == NULL) {
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	range_resp = (wl_nan_range_resp_t *)iov_data;
+
+	if (*avail_len < NAN_RNG_RESP_IOV_LEN) {
+		/* buffer is insufficient */
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+
+	range_resp->range_id = (uint8)(atoi(*argv));
+	argv++;
+	argc--;
+
+	*is_set = TRUE;
+
+	/* Parse optional args. Validity is checked by discovery engine */
+	while (*argv != NULL) {
+		if ((param_p = nan_lookup_rng_config_param(*argv)) == NULL) {
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		/*
+		 * Skip param name
+		 */
+		argv++;
+		switch (param_p->id) {
+
+		case NAN_RNG_CFG_INDICATION:
+			if (*argv != NULL) {
+				range_resp->indication = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_RESOLUTION:
+			if (*argv != NULL) {
+				range_resp->resolution = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_INGRESS_LIMIT:
+			if (*argv != NULL) {
+				range_resp->ingress = (uint32)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_EGRESS_LIMIT:
+			if (*argv != NULL) {
+				range_resp->egress = (uint32)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_INTERVAL:
+			if (*argv != NULL) {
+				range_resp->interval = (uint16)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		case NAN_RNG_CFG_RESULT_REQUIRED:
+			flags |= NAN_RANGE_FLAG_RESULT_REQUIRED;
+			break;
+
+		case NAN_RNG_CFG_RANGE_STATUS:
+			if (*argv != NULL) {
+				range_resp->status = (uint8)(atoi(*argv));
+				argv++;
+			}
+			break;
+
+		default:
+			return BCME_ERROR;
+			break;
+		}
+	}
+	range_resp->flags = flags;
+	len += NAN_RNG_RESP_IOV_LEN;
+	*avail_len -= len;
+exit:
+	return ret;
+}
+
+static int
+wl_nan_subcmd_range_cancel(void *wl, const wl_nan_sub_cmd_t *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	wl_nan_range_id range_id = 0;
+	int ret = BCME_OK;
+	uint16 len = 0;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argc);
+
+	if (*argv == NULL) {
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (*avail_len < sizeof(range_id)) {
+		/* buffer is insufficient */
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+
+	*is_set = TRUE;
+
+	*iov_data = range_id = (uint8)(atoi(*argv));
+
+	len += sizeof(range_id);
+	*avail_len -= len;
+exit:
+	return ret;
+}
+
+/*  WFA testmode operation */
+static int
+wl_nan_subcmd_cfg_wfa_testmode(void *wl, const wl_nan_sub_cmd_t  *cmd, int argc, char **argv,
+	bool *is_set, uint8 *iov_data, uint16 *avail_len)
+{
+	wl_nan_wfa_testmode_t flags = 0;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* If no more parameters are passed, it is GET command */
+	if ((*argv == NULL) || argc == 0) {
+		*is_set = FALSE;
+	} else {
+		char *endptr = NULL;
+
+		*is_set = TRUE;
+		flags = strtoul(*argv, &endptr, 0);
+
+		if (flags & ~WL_NAN_WFA_TM_FLAG_MASK) {
+			return BCME_BADARG;
+		}
+		if (*avail_len < sizeof(flags)) {
+			return BCME_BUFTOOSHORT;
+		}
+
+		flags = htod32(flags);
+		memcpy(iov_data, &flags, sizeof(flags));
+		*avail_len -= sizeof(flags);
+	}
+
+	return BCME_OK;
+}
+
+#endif /* WL_NAN */
diff --git a/wl/src/wl/exe/wluc_natoe.c b/wl/src/wl/exe/wluc_natoe.c
new file mode 100644
index 0000000..dd30b51
--- /dev/null
+++ b/wl/src/wl/exe/wluc_natoe.c
@@ -0,0 +1,572 @@
+/*
+ * wl natoe command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_natoe.c 625864 2016-03-18 00:12:54Z $
+ */
+#include <wlioctl.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_natoe_control;
+typedef struct wl_natoe_sub_cmd wl_natoe_sub_cmd_t;
+typedef int (natoe_cmd_handler_t)(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv);
+
+struct wl_natoe_sub_cmd {
+	char *name;
+	uint8  version;              /* cmd  version */
+	uint16 id;                   /* id for the dongle f/w switch/case */
+	uint16 type;                 /* base type of argument */
+	natoe_cmd_handler_t *handler; /* cmd handler  */
+};
+
+#define NATOE_PARAMS_USAGE        \
+"\tUsage: wl natoe [command] [cmd options] as follows:\n" \
+"\t\twl natoe enable [1/0] - enable disable natoe functionality\n" \
+"\t\twl natoe config_ips [sta ip][sta netmask][default router][sta dns]\n" \
+"\t\t\t[ap ip][ap netmask]\n" \
+"\t\twl natoe config_ports [starting port number][no of ports]\n" \
+"\t\twl natoe stats [0] - 0 to clear stats\n" \
+"\t\twl natoe tbl_cnt [no_tbl_entries]\n"
+
+#define WL_NATOE_CMD			"natoe"
+#define WL_NATOE_MAX_PORT_NUM		65535
+
+#define WL_NATOE_SUBCMD_ENABLE_ARGC		1
+#define WL_NATOE_SUBCMD_CONFIG_IPS_ARGC		6
+#define WL_NATOE_SUBCMD_CONFIG_PORTS_ARGC	2
+#define WL_NATOE_SUBCMD_DBG_STATS_ARGC		1
+#define WL_NATOE_SUBCMD_TBL_CNT_ARGC		1
+
+#define WL_NATOE_FUNC(suffix) wl_natoe_subcmd_ ##suffix
+static int wl_natoe_subcmd_enable(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv);
+static int wl_natoe_subcmd_config_ips(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv);
+static int wl_natoe_subcmd_config_ports(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv);
+static int wl_natoe_subcmd_dbg_stats(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv);
+static int wl_natoe_subcmd_tbl_cnt(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv);
+
+static cmd_t wl_natoe_cmds[] = {
+	{ WL_NATOE_CMD, wl_natoe_control, WLC_GET_VAR, WLC_SET_VAR,
+	"superfunction for natoe commands \n\n"
+	NATOE_PARAMS_USAGE},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static const wl_natoe_sub_cmd_t natoe_cmd_list[] = {
+	/* wl natoe enable [0/1] or new: "wl natoe [0/1]" */
+	{"enable", WL_NATOE_IOCTL_VERSION, WL_NATOE_CMD_ENABLE,
+	IOVT_BUFFER, WL_NATOE_FUNC(enable)
+	},
+	{"config_ips", WL_NATOE_IOCTL_VERSION, WL_NATOE_CMD_CONFIG_IPS,
+	IOVT_BUFFER, WL_NATOE_FUNC(config_ips)
+	},
+	{"config_ports", WL_NATOE_IOCTL_VERSION, WL_NATOE_CMD_CONFIG_PORTS,
+	IOVT_BUFFER, WL_NATOE_FUNC(config_ports)
+	},
+	{"stats", WL_NATOE_IOCTL_VERSION, WL_NATOE_CMD_DBG_STATS,
+	IOVT_BUFFER, WL_NATOE_FUNC(dbg_stats)
+	},
+	{"tbl_cnt", WL_NATOE_IOCTL_VERSION, WL_NATOE_CMD_TBL_CNT,
+	IOVT_BUFFER, WL_NATOE_FUNC(tbl_cnt)
+	},
+	{NULL, 0, 0, 0, NULL}
+};
+
+void
+wluc_natoe_module_init(void)
+{
+	/* register natoe commands */
+	wl_module_cmds_register(wl_natoe_cmds);
+}
+
+static int
+wlu_natoe_set_vars_cbfn(void *ctx, const uint8 *data, uint16 type, uint16 len)
+{
+	int res = BCME_OK;
+
+	UNUSED_PARAMETER(ctx);
+	UNUSED_PARAMETER(len);
+
+	switch (type) {
+
+	case WL_NATOE_XTLV_ENABLE:
+	{
+		printf("natoe: %s\n", *data?"enabled":"disabled");
+		break;
+	}
+
+	case WL_NATOE_XTLV_CONFIG_IPS:
+	{
+		wl_natoe_config_ips_t *config_ips;
+
+		config_ips = (wl_natoe_config_ips_t *)data;
+		printf("sta ip: %s\n", wl_iptoa((struct ipv4_addr *)&config_ips->sta_ip));
+		printf("sta netmask: %s\n", wl_iptoa((struct ipv4_addr *)&config_ips->sta_netmask));
+		printf("sta router ip: %s\n",
+				wl_iptoa((struct ipv4_addr *)&config_ips->sta_router_ip));
+		printf("sta dns ip: %s\n", wl_iptoa((struct ipv4_addr *)&config_ips->sta_dnsip));
+		printf("ap ip: %s\n", wl_iptoa((struct ipv4_addr *)&config_ips->ap_ip));
+		printf("ap netmask: %s\n", wl_iptoa((struct ipv4_addr *)&config_ips->ap_netmask));
+		break;
+	}
+
+	case WL_NATOE_XTLV_CONFIG_PORTS:
+	{
+		wl_natoe_ports_config_t *ports_config;
+
+		ports_config = (wl_natoe_ports_config_t *)data;
+		printf("starting port num: %d\n", dtoh16(ports_config->start_port_num));
+		printf("number of ports: %d\n", dtoh16(ports_config->no_of_ports));
+		break;
+	}
+
+	case WL_NATOE_XTLV_DBG_STATS:
+	{
+		char *stats_dump = ((char *)data);
+
+		printf("%s\n", stats_dump);
+		break;
+	}
+
+	case WL_NATOE_XTLV_TBL_CNT:
+	{
+		printf("natoe max table entries count: %d\n", dtoh32(*(uint32 *)data));
+		break;
+	}
+
+	default:
+		/* ignore */
+		break;
+	}
+	return res;
+}
+
+static int
+wl_natoe_get_stats(void *wl, wl_natoe_ioc_t *natoe_ioc, uint16 iocsz)
+{
+	/* for gets we only need to pass ioc header */
+	wl_natoe_ioc_t *iocresp = NULL;
+	int res;
+	int iocresp_sz = sizeof(*iocresp) + WL_NATOE_DBG_STATS_BUFSZ;
+
+	/*  send getbuf natoe iovar */
+	iocresp = calloc(1, iocresp_sz);
+	if (iocresp == NULL) {
+		 return BCME_NOMEM;
+	}
+
+	res = wlu_iovar_getbuf(wl, WL_NATOE_CMD, natoe_ioc, iocsz,
+			(void *)iocresp, iocresp_sz);
+	/*  check the response buff  */
+	if (res == BCME_OK) {
+		/* scans ioctl tlvbuf f& invokes the cbfn for processing  */
+		res = bcm_unpack_xtlv_buf(natoe_ioc, iocresp->data, iocresp->len,
+				BCM_XTLV_OPTION_ALIGN32, wlu_natoe_set_vars_cbfn);
+	}
+
+	free(iocresp);
+
+	return res;
+}
+
+/*
+ *   --- common for all natoe get commands except for stats ----
+ */
+static int
+wl_natoe_get_ioctl(void *wl, wl_natoe_ioc_t *natoe_ioc, uint16 iocsz)
+{
+	/* for gets we only need to pass ioc header */
+	wl_natoe_ioc_t *iocresp = NULL;
+	int res;
+
+	/*  send getbuf natoe iovar */
+	res = wlu_var_getbuf(wl, WL_NATOE_CMD, natoe_ioc, iocsz, (void *)&iocresp);
+	/*  check the response buff  */
+	if ((res == BCME_OK) && (iocresp != NULL)) {
+		/* scans ioctl tlvbuf f& invokes the cbfn for processing  */
+		res = bcm_unpack_xtlv_buf(natoe_ioc, iocresp->data, iocresp->len,
+				BCM_XTLV_OPTION_ALIGN32, wlu_natoe_set_vars_cbfn);
+	}
+
+	return res;
+}
+
+static int
+wl_natoe_subcmd_enable(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv)
+{
+	int res = BCME_OK;
+	wl_natoe_ioc_t *natoe_ioc;
+	uint16 buflen, buflen_at_start;
+	uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
+	bcm_xtlv_t *pxtlv = NULL;
+
+	/*  alloc mem for ioctl headr +  tlv data  */
+	natoe_ioc = calloc(1, iocsz);
+	if (natoe_ioc == NULL) {
+		 return BCME_NOMEM;
+	}
+
+	/* make up natoe cmd ioctl header */
+	natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
+	natoe_ioc->id = htod16(cmd->id);
+	natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
+	pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
+
+	if(*argv == NULL) { /* get */
+		iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
+		res = wl_natoe_get_ioctl(wl, natoe_ioc, iocsz);
+
+	} else {	/* set */
+		/* max tlv data we can write, it will be decremented as we pack */
+		uint8 val;
+
+		if (ARGCNT(argv) != WL_NATOE_SUBCMD_ENABLE_ARGC) {
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		val =  atoi(*argv);
+		buflen = WL_NATOE_IOC_BUFSZ;
+		/* save buflen at start */
+		buflen_at_start = buflen;
+
+		/* we'll adjust final ioc size at the end */
+		res = bcm_pack_xtlv_entry((uint8**)&pxtlv, &buflen, WL_NATOE_XTLV_ENABLE,
+			sizeof(uint8), &val, BCM_XTLV_OPTION_ALIGN32);
+
+		if (res != BCME_OK) {
+			goto exit;
+		}
+
+		/* adjust iocsz to the end of last data record */
+		natoe_ioc->len = (buflen_at_start - buflen);
+		iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
+
+		res = wlu_var_setbuf(wl, WL_NATOE_CMD, natoe_ioc, iocsz);
+	}
+exit:
+
+	free(natoe_ioc);
+	return res;
+}
+
+static int
+wl_natoe_subcmd_config_ips(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv)
+{
+	int res = BCME_USAGE_ERROR;
+	wl_natoe_config_ips_t config_ips;
+	wl_natoe_ioc_t *natoe_ioc = NULL;
+	uint16 buflen, buflen_at_start;
+	uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
+	bcm_xtlv_t *pxtlv = NULL;
+
+	/*  alloc mem for ioctl headr +  tlv data  */
+	natoe_ioc = calloc(1, iocsz);
+	if (natoe_ioc == NULL) {
+		return BCME_NOMEM;
+	}
+
+	/* make up natoe cmd ioctl header */
+	natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
+	natoe_ioc->id = htod16(cmd->id);
+	natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
+	pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
+
+	if (*argv == NULL) {
+		iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
+		res = wl_natoe_get_ioctl(wl, natoe_ioc, iocsz);
+	} else {
+		memset(&config_ips, 0, sizeof(config_ips));
+
+		if (ARGCNT(argv) != WL_NATOE_SUBCMD_CONFIG_IPS_ARGC) {
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		if (!wl_atoip(*argv++, (struct ipv4_addr *)&config_ips.sta_ip)) {
+			printf("%s: Invalid STA IP addr provided\n", __FUNCTION__);
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		if (!wl_atoip(*argv++, (struct ipv4_addr *)&config_ips.sta_netmask)) {
+			printf("%s: Invalid STA netmask addr provided\n", __FUNCTION__);
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		if (!wl_atoip(*argv++, (struct ipv4_addr *)&config_ips.sta_router_ip)) {
+			printf("%s: Invalid STA router IP addr provided\n", __FUNCTION__);
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		if (!wl_atoip(*argv++, (struct ipv4_addr *)&config_ips.sta_dnsip)) {
+			printf("%s: Invalid STA DNS IP addr provided\n", __FUNCTION__);
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		if (!wl_atoip(*argv++, (struct ipv4_addr *)&config_ips.ap_ip)) {
+			printf("%s: Invalid AP IP addr provided\n", __FUNCTION__);
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		if (!wl_atoip(*argv++, (struct ipv4_addr *)&config_ips.ap_netmask)) {
+			printf("%s: Invalid AP netmask addr provided\n", __FUNCTION__);
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		/* max data we can write, it will be decremented as we pack */
+		buflen = WL_NATOE_IOC_BUFSZ;
+		buflen_at_start = buflen;
+
+		res = bcm_pack_xtlv_entry((uint8 **)&pxtlv,
+				&buflen, WL_NATOE_XTLV_CONFIG_IPS, sizeof(config_ips),
+				(uint8 *)&config_ips, BCM_XTLV_OPTION_ALIGN32);
+
+		if (res != BCME_OK) {
+			goto exit;
+		}
+
+		/* adjust iocsz to the end of last data record */
+		natoe_ioc->len = (buflen_at_start - buflen);
+		iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
+		res = wlu_var_setbuf(wl, WL_NATOE_CMD, natoe_ioc, iocsz);
+	}
+
+exit:
+	free(natoe_ioc);
+	return res;
+}
+
+static int
+wl_natoe_subcmd_config_ports(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv)
+{
+	int res = BCME_USAGE_ERROR;
+	wl_natoe_ports_config_t ports_config;
+	wl_natoe_ioc_t *natoe_ioc = NULL;
+	uint16 buflen, buflen_at_start;
+	uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
+	bcm_xtlv_t *pxtlv = NULL;
+
+	/*  alloc mem for ioctl headr +  tlv data  */
+	natoe_ioc = calloc(1, iocsz);
+	if (natoe_ioc == NULL) {
+		return BCME_NOMEM;
+	}
+
+	/* make up natoe cmd ioctl header */
+	natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
+	natoe_ioc->id = htod16(cmd->id);
+	natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
+	pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
+
+	if (*argv == NULL) {
+		iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
+		res = wl_natoe_get_ioctl(wl, natoe_ioc, iocsz);
+	} else {
+		memset(&ports_config, 0, sizeof(ports_config));
+
+		if (ARGCNT(argv) != WL_NATOE_SUBCMD_CONFIG_PORTS_ARGC) {
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		ports_config.start_port_num = htod16(strtoul(*argv++, NULL, 0));
+		ports_config.no_of_ports = htod16(strtoul(*argv++, NULL, 0));
+
+		if ((uint32)(ports_config.start_port_num + ports_config.no_of_ports) >
+				WL_NATOE_MAX_PORT_NUM) {
+			res = BCME_BADOPTION;
+			goto exit;
+		}
+		/* max data we can write, it will be decremented as we pack */
+		buflen = WL_NATOE_IOC_BUFSZ;
+		buflen_at_start = buflen;
+
+		res = bcm_pack_xtlv_entry((uint8 **)&pxtlv,
+				&buflen, WL_NATOE_XTLV_CONFIG_PORTS, sizeof(ports_config),
+				(uint8 *)&ports_config, BCM_XTLV_OPTION_ALIGN32);
+
+		if (res != BCME_OK) {
+			goto exit;
+		}
+
+		/* adjust iocsz to the end of last data record */
+		natoe_ioc->len = (buflen_at_start - buflen);
+		iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
+		res = wlu_var_setbuf(wl, WL_NATOE_CMD, natoe_ioc, iocsz);
+	}
+
+exit:
+	free(natoe_ioc);
+	return res;
+}
+
+static int
+wl_natoe_subcmd_dbg_stats(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv)
+{
+	int res = BCME_USAGE_ERROR;
+	wl_natoe_ioc_t *natoe_ioc = NULL;
+	uint16 buflen, buflen_at_start;
+	uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_DBG_STATS_BUFSZ;
+	bcm_xtlv_t *pxtlv = NULL;
+
+	/*  alloc mem for ioctl headr +  tlv data  */
+	natoe_ioc = calloc(1, iocsz);
+	if (natoe_ioc == NULL) {
+		return BCME_NOMEM;
+	}
+
+	/* make up natoe cmd ioctl header */
+	natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
+	natoe_ioc->id = htod16(cmd->id);
+	natoe_ioc->len = htod16(WL_NATOE_DBG_STATS_BUFSZ);
+	pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
+
+	if (*argv == NULL) {
+		iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
+		res = wl_natoe_get_stats(wl, natoe_ioc, iocsz);
+	} else {
+		uint8 val;
+
+		if (ARGCNT(argv) != WL_NATOE_SUBCMD_DBG_STATS_ARGC) {
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		val =  atoi(*argv);
+		buflen = WL_NATOE_DBG_STATS_BUFSZ;
+		/* save buflen at start */
+		buflen_at_start = buflen;
+
+		/* we'll adjust final ioc size at the end */
+		res = bcm_pack_xtlv_entry((uint8**)&pxtlv, &buflen, WL_NATOE_XTLV_DBG_STATS,
+			sizeof(uint8), &val, BCM_XTLV_OPTION_ALIGN32);
+
+		if (res != BCME_OK) {
+			goto exit;
+		}
+
+		/* adjust iocsz to the end of last data record */
+		natoe_ioc->len = (buflen_at_start - buflen);
+		iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
+
+		res = wlu_var_setbuf(wl, WL_NATOE_CMD, natoe_ioc, iocsz);
+	}
+
+exit:
+	free(natoe_ioc);
+	return res;
+}
+
+static int
+wl_natoe_subcmd_tbl_cnt(void *wl, const wl_natoe_sub_cmd_t *cmd, char **argv)
+{
+	int res = BCME_OK;
+	wl_natoe_ioc_t *natoe_ioc;
+	uint16 buflen, buflen_at_start;
+	uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ;
+	bcm_xtlv_t *pxtlv = NULL;
+
+	/*  alloc mem for ioctl headr +  tlv data  */
+	natoe_ioc = calloc(1, iocsz);
+	if (natoe_ioc == NULL) {
+		 return BCME_NOMEM;
+	}
+
+	/* make up natoe cmd ioctl header */
+	natoe_ioc->version = htod16(WL_NATOE_IOCTL_VERSION);
+	natoe_ioc->id = htod16(cmd->id);
+	natoe_ioc->len = htod16(WL_NATOE_IOC_BUFSZ);
+	pxtlv = (bcm_xtlv_t *)natoe_ioc->data;
+
+	if(*argv == NULL) { /* get */
+		iocsz = sizeof(*natoe_ioc) + sizeof(*pxtlv);
+		res = wl_natoe_get_ioctl(wl, natoe_ioc, iocsz);
+
+	} else {	/* set */
+		/* max tlv data we can write, it will be decremented as we pack */
+		uint32 val;
+
+		if (ARGCNT(argv) != WL_NATOE_SUBCMD_TBL_CNT_ARGC) {
+			res = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		val =  atoi(*argv);
+		buflen = WL_NATOE_IOC_BUFSZ;
+		/* save buflen at start */
+		buflen_at_start = buflen;
+
+		/* we'll adjust final ioc size at the end */
+		res = bcm_pack_xtlv_entry((uint8**)&pxtlv, &buflen, WL_NATOE_XTLV_TBL_CNT,
+			sizeof(val), (uint8 *)&val, BCM_XTLV_OPTION_ALIGN32);
+
+		if (res != BCME_OK) {
+			goto exit;
+		}
+
+		/* adjust iocsz to the end of last data record */
+		natoe_ioc->len = (buflen_at_start - buflen);
+		iocsz = sizeof(*natoe_ioc) + natoe_ioc->len;
+
+		res = wlu_var_setbuf(wl, WL_NATOE_CMD, natoe_ioc, iocsz);
+	}
+exit:
+
+	free(natoe_ioc);
+	return res;
+}
+
+static int
+wl_natoe_control(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_USAGE_ERROR;
+	char *natoe_query[2] = {"enable", NULL};
+	char *natoe_en[3] = {"enable", "1", NULL};
+	char *natoe_dis[3] = {"enable", "0", NULL};
+	const wl_natoe_sub_cmd_t *natoe_cmd = &natoe_cmd_list[0];
+	/* Skip the command name */
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+	/* skip to cmd name after "natoe" */
+	if (!*argv) {
+		/* query natoe "enable" state */
+		argv = natoe_query;
+	} else if (*argv[0] == '1') {
+		argv = natoe_en;
+	} else if (*argv[0] == '0') {
+		argv = natoe_dis;
+	} else if (!strcmp(*argv, "-h") || !strcmp(*argv, "help")) {
+		/* help , or -h* */
+		return ret;
+	}
+
+	while (natoe_cmd->name != NULL) {
+		if (strcmp(natoe_cmd->name, *argv) == 0)  {
+			/* dispacth cmd to appropriate handler */
+			if (natoe_cmd->handler) {
+				ret = natoe_cmd->handler(wl, natoe_cmd, ++argv);
+			}
+			return ret;
+		}
+		natoe_cmd++;
+	}
+	return ret;
+}
diff --git a/wl/src/wl/exe/wluc_ndoe.c b/wl/src/wl/exe/wluc_ndoe.c
new file mode 100644
index 0000000..021f27e
--- /dev/null
+++ b/wl/src/wl/exe/wluc_ndoe.c
@@ -0,0 +1,368 @@
+/*
+ * wl ndoe command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_ndoe.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_ndstatus, wl_solicitipv6, wl_remoteipv6;
+static cmd_func_t wl_nd_hostip_extended;
+
+static cmd_t wl_ndoe_cmds[] = {
+	{ "nd_hostip", wl_nd_hostip_extended, WLC_GET_VAR, WLC_SET_VAR,
+	"Add/delete a local host Ipv6 address or get list of address\n"
+	"Usage: wl nd_hostip <ver|add|del|list> [addr] [-t <uc|ac>]\n"
+	"       wl nd_hostip ver              : get iovar version supported\n"
+	"       wl nd_hostip add <addr>       : add unicast host ip addr\n"
+	"       wl nd_hostip add <addr> -t ac : add anycast host ip addr\n"
+	"       wl nd_hostip del <addr>       : delete specified addr\n"
+	"       wl nd_hostip del -t uc        : delete all unicast addr\n"
+	"       wl nd_hostip del -t ac        : delete all anycast addr\n"
+	"       wl nd_hostip del              : delete all addr\n"
+	"       wl nd_hostip list             : get list of all addr\n"
+	"     * wl nd_hostip <addr>           : add unicast host ip address\n"
+	"     * wl nd_hostip                  : display list of address\n"},
+	{ "nd_solicitip", wl_solicitipv6, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a local host solicit ipv6 address or display them"},
+	{ "nd_remoteip", wl_remoteipv6, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a local remote ipv6 address or display them"},
+	{ "nd_status", wl_ndstatus, WLC_GET_VAR, -1,
+	"Displays Neighbor Discovery Status"},
+	{ "nd_hostip_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear all host-ip addresses"},
+	{ "nd_macaddr", wl_iov_mac, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/set the MAC address for offload" },
+	{ "nd_status_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear neighbor discovery status"},
+	{ "nd_unsolicited_na_filter", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/disable Unsolicited Neighbor Advertisement Filtering"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_ndoe_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register ndoe commands */
+	wl_module_cmds_register(wl_ndoe_cmds);
+}
+
+static int
+wl_print_ipv6_addr(struct ipv6_addr *addr)
+{
+	if (addr) {
+		uint i;
+		uint16 *ip_addr = (uint16*)addr;
+
+		/* IPv6 is represented as 8 groups of 4 hex digit separated by : */
+		for (i = 0; i < (IPV6_ADDR_LEN/sizeof(uint16)); i++) {
+			printf("%x", ntoh16(ip_addr[i]));
+			if (i < 7)
+				printf(":");
+		}
+		return 0;
+	} else {
+		printf("null");
+		return -1;
+	}
+}
+
+static int
+wl_nd_hostip_extended(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	wl_nd_hostip_t hostip_op;
+	char **saved_argv = argv;
+
+	if (!*++argv) {
+		/* Get for nd_hostip iovar old syntax */
+		return wl_hostipv6(wl, cmd, saved_argv);
+	} else if (!stricmp(*argv, "ver")) {
+		wl_nd_hostip_t *nd_hostip_ver = NULL;
+
+		/* Get iovar version */
+		hostip_op.version = htod16(WL_ND_HOSTIP_IOV_VER);
+		hostip_op.op_type = htod16(WL_ND_HOSTIP_OP_VER);
+		hostip_op.length = htod32(WL_ND_HOSTIP_FIXED_LEN + sizeof(uint16));
+		hostip_op.u.version = 0;
+
+		ret = wlu_var_getbuf(wl, cmd->name, &hostip_op,
+				WL_ND_HOSTIP_FIXED_LEN + sizeof(uint16), (void **)&nd_hostip_ver);
+
+		if (ret < 0) {
+			return BCME_UNSUPPORTED;
+		}
+
+		nd_hostip_ver->version = dtoh16(nd_hostip_ver->version);
+		nd_hostip_ver->op_type = dtoh16(nd_hostip_ver->op_type);
+		nd_hostip_ver->length = dtoh32(nd_hostip_ver->length);
+		nd_hostip_ver->u.version = dtoh16(nd_hostip_ver->u.version);
+
+		if ((nd_hostip_ver->version == WL_ND_HOSTIP_IOV_VER) &&
+		   (nd_hostip_ver->op_type == WL_ND_HOSTIP_OP_VER) &&
+		   (nd_hostip_ver->length == WL_ND_HOSTIP_FIXED_LEN +
+		    sizeof(uint16))) {
+			printf("nd_hostip ver %d\n", nd_hostip_ver->u.version);
+		} else {
+			printf("nd_hostip ver 0\n");
+			return BCME_UNSUPPORTED;
+		}
+	} else if (!stricmp(*argv, "add")) {
+		/* Add host ip */
+		hostip_op.version = htod16(WL_ND_HOSTIP_IOV_VER);
+		hostip_op.op_type = htod16(WL_ND_HOSTIP_OP_ADD);
+		hostip_op.length = htod32(WL_ND_HOSTIP_WITH_ADDR_LEN);
+
+		if (*++argv) {
+			/* address */
+			if (!wl_atoipv6(*argv, &hostip_op.u.host_ip.ip_addr)) {
+				/* Invalid address */
+				return BCME_USAGE_ERROR;
+			}
+
+			/* type of address (unicast default) */
+			hostip_op.u.host_ip.type = WL_ND_IPV6_ADDR_TYPE_UNICAST;
+
+			if (*++argv && !stricmp(*argv, "-t")) {
+				if (*++argv && !stricmp(*argv, "ac")) {
+					/* anycast address */
+					hostip_op.u.host_ip.type = WL_ND_IPV6_ADDR_TYPE_ANYCAST;
+				}
+			}
+
+			ret = wlu_var_setbuf(wl, cmd->name, &hostip_op,
+					WL_ND_HOSTIP_WITH_ADDR_LEN);
+		} else {
+			/* no address given */
+			return BCME_USAGE_ERROR;
+		}
+	} else if (!stricmp(*argv, "del")) {
+		/* Delete host ip */
+		hostip_op.version = htod16(WL_ND_HOSTIP_IOV_VER);
+
+		if (!*++argv) {
+			/* delete all address */
+			hostip_op.op_type = htod16(WL_ND_HOSTIP_OP_DEL_ALL);
+			hostip_op.length = htod32(WL_ND_HOSTIP_FIXED_LEN);
+			ret = wlu_var_setbuf(wl, cmd->name, &hostip_op, WL_ND_HOSTIP_FIXED_LEN);
+		} else if (!stricmp(*argv, "-t")) {
+			if (*++argv) {
+				if (!stricmp(*argv, "uc")) {
+					/* delete unicast address */
+					hostip_op.op_type = htod16(WL_ND_HOSTIP_OP_DEL_UC);
+					hostip_op.length = htod32(WL_ND_HOSTIP_FIXED_LEN);
+				} else if (!stricmp(*argv, "ac")) {
+					/* delete anycast address */
+					hostip_op.op_type = htod16(WL_ND_HOSTIP_OP_DEL_AC);
+					hostip_op.length = htod32(WL_ND_HOSTIP_FIXED_LEN);
+				} else {
+					return BCME_USAGE_ERROR;
+				}
+				ret = wlu_var_setbuf(wl, cmd->name, &hostip_op,
+						WL_ND_HOSTIP_FIXED_LEN);
+			} else {
+				return BCME_USAGE_ERROR;
+			}
+		} else if (wl_atoipv6(*argv, &hostip_op.u.host_ip.ip_addr)) {
+			/* delete specified address */
+			hostip_op.op_type = htod16(WL_ND_HOSTIP_OP_DEL);
+			hostip_op.length = htod32(WL_ND_HOSTIP_WITH_ADDR_LEN);
+			hostip_op.u.host_ip.type = 0;   /* don't care */
+			ret = wlu_var_setbuf(wl, cmd->name, &hostip_op,
+					WL_ND_HOSTIP_WITH_ADDR_LEN);
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+	} else if (!stricmp(*argv, "list")) {
+		/* get list of address */
+		wl_nd_host_ip_list_t *list = NULL;
+
+		hostip_op.version = htod16(WL_ND_HOSTIP_IOV_VER);
+		hostip_op.op_type = htod16(WL_ND_HOSTIP_OP_LIST);
+		hostip_op.length = htod32(WL_ND_HOSTIP_FIXED_LEN);
+
+		ret = wlu_var_getbuf(wl, cmd->name, &hostip_op,
+				WL_ND_HOSTIP_FIXED_LEN, (void **)&list);
+		if (!ret) {
+			uint i;
+			list->count = dtoh32(list->count);
+			for (i = 0; i < list->count; i++) {
+				uint32 addr_type = list->host_ip[i].type;
+				wl_print_ipv6_addr(&list->host_ip[i].ip_addr);
+				if (addr_type == WL_ND_IPV6_ADDR_TYPE_UNICAST) {
+					printf(" unicast\r\n");
+				} else if (addr_type == WL_ND_IPV6_ADDR_TYPE_ANYCAST) {
+					printf(" anycast\r\n");
+				} else {
+					printf(" unknown type\n\n");
+				}
+			}
+		}
+	} else {
+		/* Set for nd_hostip iovar old syntax */
+		return wl_hostipv6(wl, cmd, saved_argv);
+	}
+
+	return ret;
+}
+
+static int
+wl_ndstatus(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	struct nd_ol_stats_t *nd_stats;
+
+	if (!*++argv) {
+	/* Get */
+	void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		nd_stats = (struct nd_ol_stats_t *)ptr;
+
+		printf("host_ip_entries %d\r\n", nd_stats->host_ip_entries);
+		printf("host_ip_overflow %d\r\n", nd_stats->host_ip_overflow);
+		printf("peer_request %d\r\n", nd_stats->peer_request);
+		printf("peer_request_drop %d\r\n", nd_stats->peer_request_drop);
+		printf("peer_reply_drop %d\r\n", nd_stats->peer_reply_drop);
+		printf("peer_service %d\r\n", nd_stats->peer_service);
+	} else {
+		printf("Cannot set nd stats\n");
+	}
+
+	return 0;
+}
+
+/*
+ * If a solicit IP address is given, add it
+ * e.g. "wl nd_solicitip fe00:0:0:0:0:290:1fc0:18c0 ".
+ * If no address is given, dump all the addresses.
+ */
+static int
+wl_solicitipv6(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	struct ipv6_addr ipa_set, *ipa_get, null_ipa;
+	uint16 *ip_addr;
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		ip_addr = (uint16*)ptr;
+		memset(null_ipa.addr, 0, IPV6_ADDR_LEN);
+		for (ipa_get = (struct ipv6_addr *)ptr;
+			 memcmp(null_ipa.addr, ipa_get->addr, IPV6_ADDR_LEN) != 0;
+			 ipa_get++) {
+			/* Print ipv6 Addr */
+			for (i = 0; i < 8; i++) {
+				printf("%x", ntoh16(ip_addr[i]));
+				if (i < 7)
+					printf(":");
+			}
+			printf("\r\n");
+
+			ip_addr += 8;
+		}
+	} else {
+		/* Add */
+		if (!wl_atoipv6(*argv, &ipa_set))
+			return BCME_USAGE_ERROR;
+
+		/* we add one ip-addr at a time */
+		return wlu_var_setbuf(wl, cmd->name, &ipa_set, IPV6_ADDR_LEN);
+	}
+	return ret;
+}
+
+/*
+ * If a remote IP address is given, add it
+ * e.g. "wl nd_remoteip fe00:0:0:0:0:290:1fc0:18c0 ".
+ * If no address is given, dump the addresses.
+ */
+static int
+wl_remoteipv6(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	struct ipv6_addr ipa_set, *ipa_get, null_ipa;
+	uint16 *ip_addr;
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+
+		ip_addr = (uint16*)ptr;
+		memset(null_ipa.addr, 0, IPV6_ADDR_LEN);
+		for (ipa_get = (struct ipv6_addr *)ptr;
+			 memcmp(null_ipa.addr, ipa_get->addr, IPV6_ADDR_LEN) != 0;
+			 ipa_get++) {
+			/* Print ipv6 Addr */
+			for (i = 0; i < 8; i++) {
+				printf("%x", ntoh16(ip_addr[i]));
+				if (i < 7)
+					printf(":");
+			}
+			printf("\r\n");
+
+			ip_addr += 8;
+		}
+	} else {
+		/* Add */
+		if (!wl_atoipv6(*argv, &ipa_set))
+			return BCME_USAGE_ERROR;
+
+		/* we add one ip-addr at a time */
+		return wlu_var_setbuf(wl, cmd->name, &ipa_set, IPV6_ADDR_LEN);
+	}
+	return ret;
+}
diff --git a/wl/src/wl/exe/wluc_obss.c b/wl/src/wl/exe/wluc_obss.c
new file mode 100644
index 0000000..df23873
--- /dev/null
+++ b/wl/src/wl/exe/wluc_obss.c
@@ -0,0 +1,289 @@
+/*
+ * wl obss command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_obss.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_obss_scan, wl_obss_coex_action;
+
+static cmd_t wl_obss_cmds[] = {
+	{ "obss_scan_params", wl_obss_scan, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get Overlapping BSS scan parameters\n"
+	"Usage: wl obss_scan a b c d e ...; where\n"
+	"\ta-Passive Dwell, {5-1000TU}, default = 100\n"
+	"\tb-Active Dwell, {10-1000TU}, default = 20\n"
+	"\tc-Width Trigger Scan Interval, {10-900sec}, default = 300\n"
+	"\td-Passive Total per Channel, {200-10000TU}, default = 200\n"
+	"\te-Active Total per Channel, {20-1000TU}, default = 20\n"
+	"\tf-Channel Transition Delay Factor, {5-100}, default = 5\n"
+	"\tg-Activity Threshold, {0-100%}, default = 25"},
+	{ "obss_coex_action", wl_obss_coex_action, -1, WLC_SET_VAR,
+	"send OBSS 20/40 Coexistence Mangement Action Frame\n"
+	"\tUsage: wl obss_coex_action -i <1/0> -w <1/0> -c <channel list>\n"
+	"\t -i: 40MHz intolerate bit; -w: 20MHz width Req bit;\n"
+	"\t -c: channel list, 1 - 14\n"
+	"\t At least one option must be provided"
+	},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_obss_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register obss commands */
+	wl_module_cmds_register(wl_obss_cmds);
+}
+
+static int
+wl_obss_scan_params_range_chk(wl_obss_scan_arg_t *obss_scan_arg)
+{
+	if (obss_scan_arg->passive_dwell < 0)
+		obss_scan_arg->passive_dwell = WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT;
+	else if (obss_scan_arg->passive_dwell < WLC_OBSS_SCAN_PASSIVE_DWELL_MIN ||
+		obss_scan_arg->passive_dwell > WLC_OBSS_SCAN_PASSIVE_DWELL_MAX) {
+		printf("passive dwell not in range %d\n", obss_scan_arg->passive_dwell);
+		return -1;
+	}
+
+	if (obss_scan_arg->active_dwell < 0)
+		obss_scan_arg->active_dwell = WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT;
+	else if (obss_scan_arg->active_dwell < WLC_OBSS_SCAN_ACTIVE_DWELL_MIN ||
+		obss_scan_arg->active_dwell > WLC_OBSS_SCAN_ACTIVE_DWELL_MAX) {
+		printf("active dwell not in range %d\n", obss_scan_arg->active_dwell);
+		return -1;
+	}
+
+	if (obss_scan_arg->bss_widthscan_interval < 0)
+		obss_scan_arg->bss_widthscan_interval =
+			WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT;
+	else if (obss_scan_arg->bss_widthscan_interval < WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN ||
+		obss_scan_arg->bss_widthscan_interval > WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX) {
+		printf("Width Trigger Scan Interval not in range %d\n",
+		       obss_scan_arg->bss_widthscan_interval);
+		return -1;
+	}
+
+	if (obss_scan_arg->chanwidth_transition_delay < 0)
+		obss_scan_arg->chanwidth_transition_delay =
+			WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT;
+	else if ((obss_scan_arg->chanwidth_transition_delay <
+		WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN) ||
+		(obss_scan_arg->chanwidth_transition_delay >
+		WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX)) {
+		printf("Width Channel Transition Delay Factor not in range %d\n",
+		       obss_scan_arg->chanwidth_transition_delay);
+		return -1;
+	}
+
+	if (obss_scan_arg->passive_total < 0)
+		obss_scan_arg->passive_total = WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT;
+	else if (obss_scan_arg->passive_total < WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN ||
+		obss_scan_arg->passive_total > WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX) {
+		printf("Passive Total per Channel not in range %d\n", obss_scan_arg->passive_total);
+		return -1;
+	}
+
+	if (obss_scan_arg->active_total < 0)
+		obss_scan_arg->active_total = WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT;
+	if (obss_scan_arg->active_total < WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN ||
+		obss_scan_arg->active_total > WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX) {
+		printf("Active Total per Channel not in range %d\n", obss_scan_arg->active_total);
+		return -1;
+	}
+
+	if (obss_scan_arg->activity_threshold < 0)
+		obss_scan_arg->activity_threshold = WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT;
+	else if (obss_scan_arg->activity_threshold < WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN ||
+		obss_scan_arg->activity_threshold > WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX) {
+		printf("Activity Threshold not in range %d\n", obss_scan_arg->activity_threshold);
+		return -1;
+	}
+	return 0;
+}
+
+static int
+wl_obss_scan(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	wl_obss_scan_arg_t obss_scan_arg;
+	char *endptr = NULL;
+	uint buflen;
+	uint argc = 0;
+
+	if (!*++argv) {
+		void *ptr = NULL;
+		wl_obss_scan_arg_t *obss_scan_param;
+
+		err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr);
+		if (err < 0)
+		        return err;
+
+		obss_scan_param = (wl_obss_scan_arg_t *)ptr;
+		printf("%d %d %d %d %d %d %d\n",
+		       dtoh16(obss_scan_param->passive_dwell),
+		       dtoh16(obss_scan_param->active_dwell),
+		       dtoh16(obss_scan_param->bss_widthscan_interval),
+		       dtoh16(obss_scan_param->passive_total),
+		       dtoh16(obss_scan_param->active_total),
+		       dtoh16(obss_scan_param->chanwidth_transition_delay),
+		       dtoh16(obss_scan_param->activity_threshold));
+		return 0;
+	}
+
+	/* arg count */
+	while (argv[argc])
+		argc++;
+
+	buflen = WL_OBSS_SCAN_PARAM_LEN;
+	memset((uint8 *)&obss_scan_arg, 0, buflen);
+
+	/* required argments */
+	if (argc < WL_MIN_NUM_OBSS_SCAN_ARG) {
+		fprintf(stderr, "Too few/many arguments (require %d, got %d)\n",
+			WL_MIN_NUM_OBSS_SCAN_ARG, argc);
+		return BCME_USAGE_ERROR;
+	}
+
+	obss_scan_arg.passive_dwell = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.active_dwell = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.bss_widthscan_interval = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.passive_total = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.active_total = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.chanwidth_transition_delay = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	obss_scan_arg.activity_threshold = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	if (wl_obss_scan_params_range_chk(&obss_scan_arg))
+		return BCME_RANGE;
+
+	err = wlu_var_setbuf(wl, cmd->name, &obss_scan_arg, buflen);
+
+	return err;
+}
+
+static int
+wl_obss_coex_action(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	char var[256];
+	wl_action_obss_coex_req_t *req = (wl_action_obss_coex_req_t *)var;
+	int val;
+	int num = 0;
+	uint8 options = 0;
+
+	argv++;
+	memset(&var, 0, sizeof(wl_action_obss_coex_req_t));
+	while (*argv) {
+		if (!strncmp(*argv, "-i", 2) && ((options & 0x1) != 0x1)) {
+			argv++;
+			if (!*argv)
+				return BCME_USAGE_ERROR;
+			val = atoi(*argv);
+			if ((val != 0) && (val != 1))
+				return BCME_BADARG;
+			req->info |= val ? WL_COEX_40MHZ_INTOLERANT : 0;
+			options |= 0x1;
+		}
+		else if (!strncmp(*argv, "-w", 2) && ((options & 0x2) != 0x2)) {
+			argv++;
+			if (!*argv)
+				return BCME_USAGE_ERROR;
+			val = atoi(*argv);
+			if ((val != 0) && (val != 1))
+				return BCME_BADARG;
+			req->info |= val ? WL_COEX_WIDTH20 : 0;
+			options |= 0x2;
+		}
+		else if (!strncmp(*argv, "-c", 2) && ((options & 0x4) != 0x4)) {
+			argv++;
+			while (*argv) {
+				if (isdigit((unsigned char)(**argv))) {
+					val = htod32(strtoul(*argv, NULL, 0));
+					if ((val == 0) || (val > 14)) {
+						printf("Invalid channel %d\n", val);
+						return BCME_BADARG;
+					}
+					req->ch_list[num] = (uint8)val;
+					num++;
+					argv++;
+					if (num > 14) {
+						printf("Too many channels (max 14)\n");
+						return BCME_BADARG;
+					}
+				} else
+					break;
+			}
+			if (!num) {
+				printf("With option '-c' specified, a channel list is required\n");
+				return BCME_BADARG;
+			}
+			req->num = num;
+			options |= 0x4;
+			continue;
+		}
+		else
+			return BCME_USAGE_ERROR;
+		argv++;
+	}
+	if (!options)
+		return BCME_BADARG;
+	err = wlu_var_setbuf(wl, cmd->name, &var, (sizeof(wl_action_obss_coex_req_t) +
+		(req->num ? (req->num - 1) * sizeof(uint8) : 0)));
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_offloads.c b/wl/src/wl/exe/wluc_offloads.c
new file mode 100644
index 0000000..1a92298
--- /dev/null
+++ b/wl/src/wl/exe/wluc_offloads.c
@@ -0,0 +1,242 @@
+/*
+ * wl offloads command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_offloads.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wlu_offloads_stats;
+static cmd_func_t wl_ol_notify_bcn_ie;
+
+static cmd_t wl_offloads_cmds[] = {
+	{ "ol_stats", wlu_offloads_stats, WLC_GET_VAR, -1,
+	"Give suboption \"list\" to list various suboptions" },
+	{ "ol_eventlog", wlu_offloads_stats, WLC_GET_VAR, -1,
+	"Give suboption \"list\" to list various suboptions" },
+	{ "ol_cons", wlu_offloads_stats, WLC_GET_VAR, WLC_SET_VAR,
+	"Display the ARM console or issue a command to the ARM console\n"
+	"  Usage: ol_cons [<cmd>]\n"
+	"\t\"?\" - Display the list of active console commands"
+	},
+	{ "ol_wowl_cons", wlu_offloads_stats, WLC_GET_VAR, -1,
+	"Give suboption \"list\" to list various suboptions" },
+	{ "ol_clr", wlu_offloads_stats, WLC_GET_VAR, -1,
+	"Give suboption \"list\" to list various suboptions" },
+	{ "ol_notify_bcn_ie", wl_ol_notify_bcn_ie, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/Disable IE ID notification"},
+	{ "ol_arp_hostip", wl_hostip, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a host-ip address or display them"},
+	{ "ol_nd_hostip", wl_hostipv6, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a local host-ipv6 address or display them"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_offloads_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register offloads commands */
+	wl_module_cmds_register(wl_offloads_cmds);
+}
+
+static int
+wlu_offloads_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	char *dump_buf;
+	int bufsz = WL_DUMP_BUF_LEN;
+	bool cons_cmd = FALSE;
+
+	if (cmd->get < 0)
+		return -1;
+
+	if (!strcmp(cmd->name, "ol_clr"))
+	{
+		ret = wlu_iovar_get(wl, cmd->name, NULL, 0);
+		return ret;
+	}
+
+	if (!strcmp(cmd->name, "ol_cons")) {
+		/* Check for command */
+		if (*(argv + 1)) {
+			argv++;
+			cons_cmd = TRUE;
+			bufsz = CMDLINESZ;
+		}
+	}
+
+	dump_buf = malloc(bufsz);
+	if (dump_buf == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n", bufsz);
+		return -1;
+	}
+	memset(dump_buf, 0, bufsz);
+
+	while (*argv) {
+		/* add space delimiter if this is not the first section name */
+		if (dump_buf[0] != '\0')
+			strcat(dump_buf, " ");
+
+		strcat(dump_buf, *argv);
+
+		argv++;
+	}
+
+	if (cons_cmd) {
+		ret = wlu_iovar_set(wl, cmd->name, dump_buf, bufsz);
+	} else {
+		ret = wlu_iovar_get(wl, cmd->name, dump_buf, bufsz);
+		if (!ret)
+			fputs(dump_buf, stdout);
+	}
+
+	free(dump_buf);
+
+	return ret;
+}
+
+static int
+wl_ol_notify_bcn_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	void *ptr = NULL;
+
+#define	VNDR_IE_ID		(221)
+#define OLMSG_BCN_MAX_IE	(222)
+
+	struct beacon_ie_notify_cmd {
+		uint32		id;
+		uint32		enable;
+		struct ipv4_addr vndriemask;
+	} beacon_notification_cmd;
+
+	memset(&beacon_notification_cmd, 0, sizeof(beacon_notification_cmd));
+
+	++argv; /* skip the command iteself */
+
+	if (!*argv) {
+		/* Get Everything */
+		beacon_notification_cmd.id = -1; /* -1 indicates NONE */
+		ret = wlu_var_getbuf(wl, cmd->name, &beacon_notification_cmd,
+			sizeof(beacon_notification_cmd), &ptr);
+	} else {
+		if (stricmp(*argv, "enable") == 0) { /* Enable Global flag */
+			beacon_notification_cmd.id = -1; /* -1 indicates NONE */
+			beacon_notification_cmd.enable = 1;
+			return wlu_var_setbuf(wl, cmd->name, &beacon_notification_cmd,
+				sizeof(beacon_notification_cmd));
+		} else if (stricmp(*argv, "disable") == 0) { /* Disable Global flag */
+			beacon_notification_cmd.id = -1; /* -1 indicates NONE */
+			beacon_notification_cmd.enable = 0;
+			return wlu_var_setbuf(wl, cmd->name, &beacon_notification_cmd,
+				sizeof(beacon_notification_cmd));
+		} else { /* Get/Set Enable/Disable some ID */
+
+		    beacon_notification_cmd.id = (uint8) atoi(*argv);
+
+		    if (beacon_notification_cmd.id == VNDR_IE_ID) {
+			/* Get VNDR OUI */
+			++argv;
+			if (*argv) { /* Get a specific Vendor IE */
+				if (!wl_atoip(*argv, &beacon_notification_cmd.vndriemask)) {
+					return -1;
+				}
+				++argv;
+				/* Get enable/disable flag */
+				if (*argv) { /* Set a specific Vendor ie */
+					if (stricmp(*argv, "enable") == 0)
+						beacon_notification_cmd.enable = 1;
+					else if (stricmp(*argv, "disable") == 0)
+						beacon_notification_cmd.enable = 0;
+					else
+						return -1;
+
+					return wlu_var_setbuf(wl, cmd->name,
+						&beacon_notification_cmd,
+						sizeof(beacon_notification_cmd));
+				} else {
+					ret = wlu_var_getbuf(wl, cmd->name,
+						&beacon_notification_cmd,
+						sizeof(beacon_notification_cmd),
+						&ptr);
+				}
+			} else { /* Get ALL Vendor IE */
+				ret = wlu_var_getbuf(wl, cmd->name,
+					&beacon_notification_cmd,
+					sizeof(beacon_notification_cmd),
+					&ptr);
+			}
+		    } else {
+			if (beacon_notification_cmd.id > OLMSG_BCN_MAX_IE) {
+				return -1;
+			}
+			/* Get enable/disable flag */
+			++argv;
+			if(*argv) { /* Set IE ID */
+				if (stricmp(*argv, "enable") == 0)
+					beacon_notification_cmd.enable = 1;
+				else if (stricmp(*argv, "disable") == 0)
+					beacon_notification_cmd.enable = 0;
+				else
+					return -1;
+				return wlu_var_setbuf(wl, cmd->name,
+					&beacon_notification_cmd,
+					sizeof(beacon_notification_cmd));
+			} else { /* Get IE ID */
+				ret = wlu_var_getbuf(wl, cmd->name,
+					&beacon_notification_cmd,
+					sizeof(beacon_notification_cmd),
+					&ptr);
+			}
+		    }
+		}
+	}
+	if ((ret >= 0) && (ptr != NULL)) {
+		printf("%s\n", (char *)ptr); /* Print Everything */
+	}
+	return ret;
+}
diff --git a/wl/src/wl/exe/wluc_ota_test.c b/wl/src/wl/exe/wluc_ota_test.c
new file mode 100644
index 0000000..772af42
--- /dev/null
+++ b/wl/src/wl/exe/wluc_ota_test.c
@@ -0,0 +1,903 @@
+/*
+ * wl ota test command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_ota_test.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_ota_loadtest, wl_otatest_status, wl_load_cmd_stream;
+static cmd_func_t wl_ota_teststop, wl_otatest_rssi;
+
+static cmd_t wl_ota_cmds[] = {
+	{ "ota_teststop", wl_ota_teststop, -1, WLC_SET_VAR,
+	"\tUsage: ota_teststop"
+	},
+	{ "ota_loadtest", wl_ota_loadtest, -1, WLC_SET_VAR,
+	"\tUsage: ota_loadtest [filename] \n"
+	"\t\tpicks up ota_test.txt if file is not given"
+	},
+	{ "ota_stream", wl_load_cmd_stream, -1, WLC_SET_VAR,
+	"\tUsage: wl ota_stream start   : to start the test\n"
+	"\twl ota_stream ota_sync \n"
+	"\twl ota_stream test_setup synchtimeoout(seconds) synchbreak/loop synchmac txmac rxmac \n"
+	"\twl ota_stream ota_tx chan bandwidth contrlchan rates stf txant rxant tx_ifs tx_len"
+	"num_pkt pwrctrl start:delta:end \n"
+	"\twl ota_stream ota_rx chan bandwidth contrlchan -1 stf txant rxant tx_ifs"
+	"tx_len num_pkt \n"
+	"\twl ota_stream stop   : to stop the test"
+	},
+	{ "ota_teststatus", wl_otatest_status, WLC_GET_VAR, -1,
+	"\tUsage: otatest_status"
+	"\t\tDisplays current running test details"
+	"\totatest_status n	"
+	"\t\tdisplays test arguments for nth line"
+	},
+	{ "ota_rssi", wl_otatest_rssi, WLC_GET_VAR, -1,
+	"\tUsage: wl ota_rssi"
+	"\t\tDisplays RSSI values for each ota_rx test"
+	},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_ota_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register ota test commands */
+	wl_module_cmds_register(wl_ota_cmds);
+}
+
+#define WL_OTA_STRING_MAX_LEN		100
+#define WL_OTA_CMDSTREAM_MAX_LEN	200
+
+/* test_setup cmd argument ordering */
+enum {
+	WL_OTA_SYNC_TIMEOUT = 1,	/* Timeout in seconds */
+	WL_OTA_SYNCFAIL_ACTION,		/* Fail actio -1/0/1 */
+	WL_OTA_SYNC_MAC,		/* Mac address for sync */
+	WL_OTA_TX_MAC,			/* Mac address for tx test */
+	WL_OTA_RX_MAC,			/* Mac address for rx test */
+	WL_OTA_LOOP_TEST		/* Put test into loop mode */
+};
+
+/* ota_tx / ota_rx format ordering */
+enum {
+	WL_OTA_CUR_TEST,		/* ota_tx or ota_rx */
+	WL_OTA_CHAN,			/* cur channel */
+	WL_OTA_BW,			/* cur bandwidth */
+	WL_OTA_CONTROL_BAND,		/* cur control band */
+	WL_OTA_RATE,			/* cur rate */
+	WL_OTA_STF_MODE,		/* cur stf mode */
+	WL_OTA_TXANT,			/* tx ant to be used */
+	WL_OTA_RXANT,			/* rx ant to be used */
+	WL_OTA_TX_IFS,			/* ifs */
+	WL_OTA_TX_PKT_LEN,		/* pkt length */
+	WL_OTA_TX_NUM_PKT,		/* num of packets */
+	WL_OTA_PWR_CTRL_ON,		/* power control on/off */
+	WL_OTA_PWR_SWEEP,		/* start:delta:stop */
+	WL_OTA_LDPC,        /* Use LDPC Encoding */
+	WL_OTA_SGI          /* Use Short Guard Interval */
+};
+/* Various error chcking options */
+enum {
+	WL_OTA_SYNCFAILACTION,
+	WL_OTA_CTRLBANDVALID,
+	WL_OTA_TXANTVALID,
+	WL_OTA_RXANTVALID,
+	WL_OTA_PWRCTRLVALID
+};
+/* Display init test seq */
+void
+wl_ota_display_test_init_info(wl_ota_test_status_t *init_info)
+{
+	printf("Test Init Summary\n");
+	printf("----------------------------------------------------------\n");
+	printf("Toatl Number of test req %d\n\n", init_info->test_cnt);
+	printf("Sync timeout %d synch fail action: %d \n", init_info->sync_timeout,
+		init_info->sync_fail_action);
+	printf("Sync Mac address : \t");
+	printf("%s\n", wl_ether_etoa(&(init_info->sync_mac)));
+	printf("Tx Mac address : \t");
+	printf("%s\n", wl_ether_etoa(&(init_info->tx_mac)));
+	printf("Rx Mac address : \t");
+	printf("%s\n", wl_ether_etoa(&(init_info->rx_mac)));
+	printf("Test in Loop mode : %d \n", init_info->loop_test);
+	printf("\n\n\n");
+}
+static void
+wl_ota_display_rt_info(uint16 rate)
+{
+	if (rate & VHT_MCS_INUSE) {
+		printf("v");
+		printf("%d ", rate & OTA_RATE_MASK);
+	} else if (rate & HT_MCS_INUSE) {
+		printf("m");
+		printf("%d ", rate & OTA_RATE_MASK);
+	} else if (rate == 11) {
+		printf("5.5 ");
+	} else {
+		printf("%d ", (rate & OTA_RATE_MASK) / 2);
+	}
+}
+/* display nth tesr arg details */
+void
+wl_ota_display_test_option(wl_ota_test_args_t *test_arg, int16 cnt)
+{
+	uint8 i;
+	printf("Test cnt %d  \n", cnt);
+	printf("-----------------------------------------------------------\n");
+	printf("Curr Test : %s\n", ((test_arg->cur_test == 0) ? "TX" : "RX"));
+	printf("Wait for sync enabled %d \n", test_arg->wait_for_sync);
+	printf("Channel : %d", test_arg->chan);
+	printf("\t Bandwidth : %s ", ((test_arg->bw == WL_OTA_TEST_BW_20MHZ) ? "20" :
+		((test_arg->bw == WL_OTA_TEST_BW_40MHZ) ? "40" : "20 in 40")));
+	printf("\t Control Band : %c \n",  test_arg->control_band);
+	printf("Rates : ");
+	for (i = 0; i < test_arg->rt_info.rate_cnt; i++)
+		wl_ota_display_rt_info(test_arg->rt_info.rate_val_mbps[i]);
+	printf("\nStf mode :  %d \n", test_arg->stf_mode);
+	printf("Txant: %d(0x%2x)   rxant: %d(0x%2x) \n",
+		test_arg->txant, test_arg->txant, test_arg->rxant, test_arg->rxant);
+	printf("Pkt eng Options :  ifs %d  len: %d num: %d \n", test_arg->pkteng.delay,
+		test_arg->pkteng.length, test_arg->pkteng.nframes);
+	printf("Tx power sweep options :\nPower control %d \nstart pwr: %d  "
+		"delta: %d end pwr : %d \n", test_arg->pwr_info.pwr_ctrl_on,
+		test_arg->pwr_info.start_pwr, test_arg->pwr_info.delta_pwr,
+		test_arg->pwr_info.end_pwr);
+}
+/* do minimum string validations possible */
+/* Make stricter conditions in future */
+static int
+wl_ota_validate_string(uint8 arg, void* value)
+{
+	int ret = 0;
+	uint8	cores;
+
+	switch (arg) {
+		case WL_OTA_TXANTVALID:
+		case WL_OTA_RXANTVALID:
+			/* check if the 'txCore bitmask' of txant/rxant parameter is valid or not */
+			cores = WL_OTA_TEST_GET_CORE(*(uint8*) value);
+			if (cores > 7)
+				ret = -1;
+			break;
+		case WL_OTA_CTRLBANDVALID:
+			if ((strncmp((char *)value, "l", 1)) && (strncmp((char *)value, "u", 1)))
+				ret = -1;
+			break;
+		case WL_OTA_PWRCTRLVALID:
+		case WL_OTA_SYNCFAILACTION:
+			if ((*(int8 *)value < -2) || (*(int8 *)value > 1))
+				ret = -1;
+			break;
+		default:
+			break;
+	}
+	return ret;
+}
+
+
+/* convert power info string to integer */
+/* start:delta:end */
+static int
+wl_ota_pwrinfo_parse(const char *tok_bkp, wl_ota_test_args_t *test_arg)
+{
+	char *endptr = NULL;
+	int ret = 0;
+
+	/* convert string to int */
+	/* Read start pwr */
+	test_arg->pwr_info.start_pwr = (int8)strtol(tok_bkp, &endptr, 10);
+	if (*endptr == ':') {
+		endptr++;
+		tok_bkp = endptr;
+	} else {
+		return -1;
+	}
+	/* read delta pwr */
+	test_arg->pwr_info.delta_pwr = (int8)strtol(tok_bkp, &endptr, 10);
+	if (*endptr == ':') {
+		endptr++;
+		tok_bkp = endptr;
+	} else {
+		return -1;
+	}
+	/* read end pwr */
+	test_arg->pwr_info.end_pwr = (int8)strtol(tok_bkp, &endptr, 10);
+
+	if ((*endptr != '\0') && (*endptr != '\n') && (*endptr != ' '))
+		ret = -1;
+
+	return ret;
+}
+
+/* parsing the test init seq line */
+static int
+wl_ota_parse_test_init(wl_ota_test_vector_t * init_info, char * tok, uint16 cnt)
+{
+	int ret = 0;
+	char * endptr = NULL;
+
+	switch (cnt) {
+		case WL_OTA_SYNC_TIMEOUT:
+			init_info->sync_timeout = (uint8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0')
+				ret = -1;
+			break;
+		case WL_OTA_SYNCFAIL_ACTION:
+			init_info->sync_fail_action = (int8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0') {
+				ret = -1;
+				break;
+			} else {
+				ret = wl_ota_validate_string(WL_OTA_SYNCFAILACTION,
+					&(init_info->sync_fail_action));
+			}
+			break;
+		case WL_OTA_SYNC_MAC:
+			if (!wl_ether_atoe(tok, &(init_info->sync_mac)))
+				ret = -1;
+			break;
+		case WL_OTA_TX_MAC:
+			if (!wl_ether_atoe(tok, &(init_info->tx_mac)))
+				ret = -1;
+			break;
+		case WL_OTA_RX_MAC:
+			if (!wl_ether_atoe(tok, &(init_info->rx_mac)))
+				ret = -1;
+			break;
+		case WL_OTA_LOOP_TEST:
+			init_info->loop_test = (int8)strtol(tok, &endptr, 10);
+
+			if ((*endptr != '\0') && (*endptr != '\n') && (*endptr != ' '))
+				ret = -1;
+			break;
+		default:
+			break;
+	}
+	return ret;
+}
+/* parse test arguments */
+static int
+wl_ota_test_parse_test_option(wl_ota_test_args_t *test_arg, char * tok, uint16 cnt,
+	char rt_string[])
+{
+	char * endptr = NULL;
+	uint16 tok_len = 0;
+	int ret = 0;
+
+	if (test_arg->cur_test == WL_OTA_TEST_RX) {
+		switch (cnt) {
+			case WL_OTA_PWR_CTRL_ON:
+			case WL_OTA_PWR_SWEEP:
+				return 0;
+				break;
+			default:
+				break;
+		}
+	}
+	switch (cnt) {
+		case WL_OTA_CUR_TEST:
+			if (strncmp(tok, "ota_tx", 6) == 0)
+				test_arg->cur_test = WL_OTA_TEST_TX;
+			else if (strncmp(tok, "ota_rx", 6) == 0)
+				test_arg->cur_test = WL_OTA_TEST_RX;
+			else
+				ret = -1;
+			break;
+		case WL_OTA_CHAN:
+			test_arg->chan = (uint8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0')
+				ret = -1;
+			break;
+		case WL_OTA_BW:
+			if (strncmp(tok, "20/40", 5) == 0) {
+				test_arg->bw = WL_OTA_TEST_BW_20MHZ;
+			} else if (strncmp(tok, "20", 2) == 0) {
+				test_arg->bw = WL_OTA_TEST_BW_20MHZ;
+			} else if (strncmp(tok, "40", 2) == 0) {
+				test_arg->bw = WL_OTA_TEST_BW_40MHZ;
+			} else if (strncmp(tok, "80", 2) == 0) {
+				test_arg->bw = WL_OTA_TEST_BW_80MHZ;
+			} else {
+				ret = -1;
+			}
+			break;
+		case WL_OTA_CONTROL_BAND:
+			test_arg->control_band = *tok;
+			ret = wl_ota_validate_string(WL_OTA_CTRLBANDVALID, tok);
+			break;
+		case WL_OTA_RATE:
+			tok_len = strlen(tok);
+			if (tok_len > WL_OTA_STRING_MAX_LEN) {
+				ret = -1;
+				goto fail;
+			}
+			strncpy(rt_string, tok, tok_len);
+			break;
+		case WL_OTA_STF_MODE:
+#ifndef D11AC_IOTYPES
+			if (strncmp(tok, "siso", 4) == 0)
+				test_arg->stf_mode = OTA_STF_SISO;
+			else if (strncmp(tok, "cdd", 3) == 0)
+				test_arg->stf_mode = OTA_STF_CDD;
+			else if (strncmp(tok, "stbc", 4) == 0)
+				test_arg->stf_mode = OTA_STF_STBC;
+			else if (strncmp(tok, "sdm", 3) == 0)
+				test_arg->stf_mode = OTA_STF_SDM;
+			else
+				ret = -1;
+#endif
+			break;
+		case WL_OTA_TXANT:
+			test_arg->txant = (uint8) strtol(tok, &endptr, 0);
+			if (*endptr != '\0') {
+				ret = -1;
+				goto fail;
+			}
+			ret = wl_ota_validate_string(WL_OTA_TXANTVALID, &test_arg->txant);
+			break;
+		case WL_OTA_RXANT:
+			test_arg->rxant = (uint8)strtol(tok, &endptr, 0);
+			if (*endptr != '\0') {
+				ret = -1;
+				goto fail;
+			}
+			ret = wl_ota_validate_string(WL_OTA_RXANTVALID, &test_arg->rxant);
+			break;
+		case WL_OTA_TX_IFS:
+			test_arg->pkteng.delay =  (uint16)strtol(tok, &endptr, 10);
+			if (*endptr != '\0')
+				ret = -1;
+			break;
+		case WL_OTA_TX_PKT_LEN:
+			test_arg->pkteng.length = (uint16)strtol(tok, &endptr, 10);
+			if (*endptr != '\0')
+				ret = -1;
+			break;
+		case WL_OTA_TX_NUM_PKT:
+			test_arg->pkteng.nframes = (uint16)strtol(tok, &endptr, 10);
+			if ((*endptr != '\0') && (*endptr != '\n') && (*endptr != ' '))
+				ret = -1;
+			break;
+		case WL_OTA_PWR_CTRL_ON:
+			test_arg->pwr_info.pwr_ctrl_on = (int8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0') {
+				ret = -1;
+				goto fail;
+			}
+			ret = wl_ota_validate_string(WL_OTA_PWRCTRLVALID,
+				&test_arg->pwr_info.pwr_ctrl_on);
+			break;
+		case WL_OTA_PWR_SWEEP:
+			ret = wl_ota_pwrinfo_parse(tok, test_arg);
+			break;
+		case WL_OTA_LDPC:
+			test_arg->ldpc = (uint8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0')
+				ret = -1;
+			break;
+		case WL_OTA_SGI:
+			test_arg->sgi = (uint8)strtol(tok, &endptr, 10);
+			if (*endptr != '\0')
+				ret = -1;
+			break;
+		default:
+			break;
+	}
+
+fail:
+	return ret;
+}
+static int
+wl_ota_test_parse_rate_string(wl_ota_test_args_t *test_arg, char rt_string[100])
+{
+
+	uint8 cnt = 0;
+	char * tok = NULL;
+	char rate_st[5] = "\0";
+	uint16 int_val = 0;
+	uint16 tok_len = 0;
+	int ret = 0;
+	tok = strtok(rt_string, ",");
+
+	/* convert rate strings to int array */
+	while (tok != NULL) {
+		strncpy(rate_st, " ", 4);
+		/* skip rate parsing if its rx test case */
+		if (test_arg->cur_test == WL_OTA_TEST_RX) {
+			test_arg->rt_info.rate_val_mbps[cnt] = 0;
+			cnt = 1;
+			break;
+		}
+
+		/* Support a max of 30 rates */
+		if (cnt >= WL_OTA_TEST_MAX_NUM_RATE) {
+			ret = -1;
+			break;
+		}
+		tok_len = strlen(tok);
+		if (tok_len > 5) {
+			ret = -1;
+			break;
+		}
+		strncpy(rate_st, tok, tok_len);
+		if (strncmp(rate_st, "5.5", 3) == 0) {
+			int_val = 11;
+		} else {
+			if (rate_st[0] == 'm') {
+				rate_st[0] = ' ';
+				int_val = atoi(rate_st);
+				int_val |= HT_MCS_INUSE;
+			} else if (rate_st[0] == 'v') {
+				rate_st[0] = ' ';
+				int_val = atoi(rate_st);
+				int_val |= VHT_MCS_INUSE;
+			} else {
+				int_val = 2 * atoi(rate_st);
+			}
+		}
+		test_arg->rt_info.rate_val_mbps[cnt] = int_val;
+		tok = strtok(NULL, ",");
+		cnt++;
+	}
+	test_arg->rt_info.rate_cnt = cnt;
+	return ret;
+}
+static int
+wl_ota_test_parse_arg(char line[], wl_ota_test_vector_t *ota_test_vctr, uint16 *test_cnt,
+	uint8 *ota_sync_found)
+{
+	char * tok = NULL;
+	char rt_string[WL_OTA_STRING_MAX_LEN] = "\0";
+	uint16 cnt = 0;
+	int ret = 0;
+	tok = strtok(line, " ");
+
+	if (tok == NULL)
+		 goto fail;
+
+	/* Initialize the power arguments */
+	ota_test_vctr->test_arg[*test_cnt].pwr_info.pwr_ctrl_on = -1;
+	ota_test_vctr->test_arg[*test_cnt].pwr_info.start_pwr = -1;
+	ota_test_vctr->test_arg[*test_cnt].pwr_info.delta_pwr = -1;
+	ota_test_vctr->test_arg[*test_cnt].pwr_info.end_pwr = -1;
+
+	if (!strncmp(tok, "test_setup", 10))  {
+		/* Parse test setup details */
+		cnt = 0;
+		while (tok != NULL) {
+			if ((ret = wl_ota_parse_test_init(ota_test_vctr, tok, cnt)) != 0)
+				return ret;
+			tok = strtok(NULL, " ");
+			cnt++;
+		}
+	} else if (!(strncmp(tok, "ota_tx", 6)) || (!strncmp(tok, "ota_rx", 6))) {
+		/* parse tx /rx test argumenst */
+		cnt = 0;
+		while (tok != NULL) {
+			if ((ret = wl_ota_test_parse_test_option
+				(&(ota_test_vctr->test_arg[*test_cnt]),
+				tok, cnt, rt_string)) != 0) {
+				goto fail;
+			}
+			tok = strtok(NULL, " ");
+			cnt++;
+		}
+
+		/* split rate string into integer array */
+		if ((ret = wl_ota_test_parse_rate_string(&(ota_test_vctr->test_arg[*test_cnt]),
+			rt_string)) != 0) {
+			goto fail;
+		}
+
+		/* Add sync option if specified by user */
+		ota_test_vctr->test_arg[*test_cnt].wait_for_sync  = (*ota_sync_found);
+
+		/* Reset ota_sync_found for next test arg */
+		*ota_sync_found = 0;
+
+		/* Increment test cnt */
+		*test_cnt = *test_cnt + 1;
+	} else if (strncmp(tok, "ota_sync", 8) == 0) {
+		/* detect if a sync packet is required */
+		*ota_sync_found = 1;
+		ret = 0;
+	}
+fail:
+	return (ret);
+}
+static int
+wl_load_cmd_stream(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	char test_arg[WL_OTA_CMDSTREAM_MAX_LEN] = "\0";
+	uint16 test_cnt = 0;
+	uint8 * ptr1 = NULL;
+	uint8 i, num_loop = 0;
+	uint8 ota_sync_found = 0;
+	uint cmdlen = 0;
+
+	wl_seq_cmd_pkt_t *next_cmd;
+	wl_ota_test_vector_t *ota_test_vctr = NULL;
+
+	argv++;
+
+	if (*argv == NULL) {
+		return ret;
+	} else if (!strncmp(argv[0], "start", 5)) {
+		ret = wl_seq_start(wl, cmd, argv);
+	} else if (!strncmp(argv[0], "stop", 4)) {
+		ret = 0;
+		/* test info pointer */
+		ota_test_vctr = (wl_ota_test_vector_t *)malloc(sizeof(wl_ota_test_vector_t));
+
+		if (ota_test_vctr == NULL) {
+			fprintf(stderr, "Failed to allocate  %d bytes of memory \n",
+				(uint16)sizeof(wl_ota_test_vector_t));
+			return BCME_NOMEM;
+		}
+
+		/* Assign a new pointer so that byte wise operation is possible */
+		ptr1 = (uint8 *)ota_test_vctr;
+
+		/* Passing test structure to dongle happens in steps */
+		/* For OTA implementations its split up into chunks of 1200 bytes */
+		num_loop = sizeof(wl_ota_test_vector_t) / WL_OTA_ARG_PARSE_BLK_SIZE;
+
+		if (!cmd_batching_mode) {
+			printf("calling ota_stream stop when it's already out of batching mode\n");
+			ret = BCME_ERROR;
+			goto fail;
+		}
+		cmd_batching_mode = FALSE;
+		next_cmd = cmd_list.head;
+		if (next_cmd == NULL) {
+			printf("no command batched\n");
+			ret = 0;
+			goto fail;
+		}
+		test_cnt = 0;
+		while (next_cmd != NULL) {
+			/* Max number of test options is ARRAYSIZE(ota_test_vctr->test_arg) */
+			if (test_cnt == ARRAYSIZE(ota_test_vctr->test_arg))
+				break;
+
+			if ((ret = wl_ota_test_parse_arg(next_cmd->data, ota_test_vctr, &test_cnt,
+				&ota_sync_found)) != 0) {
+				printf("Error Parsing the test command \n");
+				ret = BCME_BADARG;
+				goto fail;
+			}
+			next_cmd = next_cmd->next;
+		}
+		ota_test_vctr->test_cnt = test_cnt;
+		/* Full size of wl_ota_test_vector_t can not be parse through wl */
+		/* max size whihc can be passed from host to dongle is limited by eth size */
+		for (i = 0; i <= num_loop; i++) {
+			/* pass on the test info to wl->test_info structure */
+			if ((ret = wlu_var_setbuf(wl, "ota_loadtest", ptr1 + i *
+				WL_OTA_ARG_PARSE_BLK_SIZE, WL_OTA_ARG_PARSE_BLK_SIZE)) < 0) {
+				fprintf(stderr, "host to dongle download failed to pass  %d"
+					"bytes in stage %d \n",
+					WL_OTA_ARG_PARSE_BLK_SIZE, i);
+			}
+		}
+fail:
+		clean_up_cmd_list();
+		free(ota_test_vctr);
+	} else {
+		cmdlen = sizeof(test_arg) - 1;
+		while (*argv) {
+			strncat(test_arg, *argv, cmdlen);
+			cmdlen -= strlen(*argv);
+			argv++;
+			if (*argv) {
+				strncat(test_arg, " ", 1);
+				cmdlen--;
+			}
+			if (*argv && cmdlen < (strlen(*argv)))
+			{
+				fprintf(stderr, "\n Insufficient length for cmd buffer\n");
+				return -1;
+			}
+		}
+		return add_one_batched_cmd(WLC_SET_VAR, test_arg, strlen(test_arg));
+
+	}
+	return ret;
+}
+
+int
+ota_loadtest(void *wl, char *command, char **argv)
+{
+	int ret = -1;
+	FILE *fp;
+	const char *fname = "ota_test.txt";
+	char line[WL_OTA_CMDSTREAM_MAX_LEN] = "\0";
+	char line_bkp[WL_OTA_CMDSTREAM_MAX_LEN] = "\0";
+	uint16 test_cnt = 0;
+	uint8 * ptr1 = NULL;
+	uint8 i, num_loop = 0;
+	uint8 ota_sync_found = 0;
+	wl_ota_test_vector_t *ota_test_vctr = NULL;
+
+	UNUSED_PARAMETER(wl);
+
+	/* Read the file name */
+	if (argv[1]) {
+		fname = argv[1];
+	} else {
+		fprintf(stderr, "Missing ota test flow file name\n");
+		return BCME_BADARG;
+	}
+
+	/* test info pointer */
+	ota_test_vctr = (wl_ota_test_vector_t *)malloc(sizeof(wl_ota_test_vector_t));
+
+	if (ota_test_vctr == NULL) {
+		fprintf(stderr, "Failed to allocate  %d bytes of memory \n",
+			(uint16)sizeof(wl_ota_test_vector_t));
+		return BCME_NOMEM;
+	}
+
+	/* Assign a new pointer so that byte wide operation is possible */
+	ptr1 = (uint8 *)ota_test_vctr;
+
+	/* find number of iterations required to parse full block form host to dongle */
+	num_loop = sizeof(wl_ota_test_vector_t) / WL_OTA_ARG_PARSE_BLK_SIZE;
+
+
+	/* open the flow file */
+	if ((fp = fopen(fname, "r")) == NULL) {
+		fprintf(stderr, "Problem opening file %s\n", fname);
+		free(ota_test_vctr);
+		return BCME_BADARG;
+	}
+
+	/* Updating version for wl_ota_test_vector_t */
+	ota_test_vctr->version = WL_OTA_TESTVEC_T_VERSION;
+
+	test_cnt = 0;
+	while (1) {
+		fgets(line, WL_OTA_CMDSTREAM_MAX_LEN - 1, fp);
+
+		if (feof(fp)) {
+			break;
+		}
+
+		/* Max number of test options is ARRAYSIZE(ota_test_vctr->test_arg) */
+		if (test_cnt == ARRAYSIZE(ota_test_vctr->test_arg))
+			break;
+
+		strncpy(line_bkp, line, WL_OTA_CMDSTREAM_MAX_LEN - 1);
+
+		if ((ret = wl_ota_test_parse_arg(line_bkp, ota_test_vctr,
+			&test_cnt, &ota_sync_found)) != 0) {
+			printf("Flow File Error: \nError Parsing string : %s \n", line);
+			ret = BCME_BADARG;
+			goto fail;
+		}
+	}
+	if (ota_sync_found) {
+		ret = -1;
+		printf("Flow File Error : \nFile can not end with ota_sync\n");
+		goto fail;
+	}
+	ota_test_vctr->test_cnt = test_cnt;
+
+	/* Full size of wl_ota_test_vector_t can not be parse through wl */
+	/* max size whihc can be passed from host to dongle is limited by eth size */
+	for (i = 0; i <= num_loop; i++) {
+		/* pass on the test info to wl->test_info structure */
+		if ((ret = wlu_var_setbuf(wl, command, ptr1 + i * WL_OTA_ARG_PARSE_BLK_SIZE,
+			WL_OTA_ARG_PARSE_BLK_SIZE)) < 0) {
+			fprintf(stderr, "host to dongle download failed to pass  %d"
+				"bytes in stage %d \n",
+				WL_OTA_ARG_PARSE_BLK_SIZE, i);
+			break;
+		}
+	}
+fail:
+	/* close the fp */
+	if (fp)
+		fclose(fp);
+
+	free(ota_test_vctr);
+	return ret;
+}
+
+static int
+wl_ota_loadtest(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd);
+	ret = ota_loadtest(wl, "ota_loadtest", argv);
+
+	return ret;
+}
+
+void
+wl_otatest_display_skip_test_reason(int8 skip_test_reason)
+{
+	switch (skip_test_reason) {
+		case 0 :
+			printf("Test successfully finished\n");
+			break;
+		case WL_OTA_SKIP_TEST_CAL_FAIL:
+			printf("Phy cal Failure \n");
+			break;
+		case WL_OTA_SKIP_TEST_SYNCH_FAIL:
+			printf("Sync Packet failure \n");
+			break;
+		case WL_OTA_SKIP_TEST_FILE_DWNLD_FAIL:
+			printf("File download Failure \n");
+			break;
+		case WL_OTA_SKIP_TEST_NO_TEST_FOUND:
+			printf("No test found in the flow file \n");
+			break;
+		case WL_OTA_SKIP_TEST_WL_NOT_UP:
+			printf("WL Not UP \n");
+			break;
+		case WL_OTA_SKIP_TEST_UNKNOWN_CALL:
+			printf("Erroneous scheduling of test. Not intended \n");
+			break;
+		default:
+			printf("Unknown test state \n");
+			break;
+	}
+}
+
+static int
+wl_otatest_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	int16 cnt = 0;
+	wl_ota_test_status_t *test_status = NULL;
+	wl_ota_test_vector_t *ota_test_vctr = NULL;
+
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd);
+
+	test_status = (wl_ota_test_status_t *)buf;
+	if (argv[1]) {
+
+		cnt = atoi(argv[1]);
+		if ((cnt < 1) || ((uint16)cnt > ARRAYSIZE(ota_test_vctr->test_arg))) {
+			printf("Error, Out of range \n");
+			return BCME_RANGE;
+		}
+		/* read nth test arg details */
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, &cnt, sizeof(uint16),
+			buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+		if (cnt > (test_status->test_cnt)) {
+			printf("Error : Number of test seq downloaded %d  \n",
+				test_status->test_cnt);
+			return BCME_RANGE;
+		}
+
+		/* Display Test init info */
+		wl_ota_display_test_init_info(test_status);
+
+		/* Dsiplay test arg info */
+		wl_ota_display_test_option(&(test_status->test_arg), cnt);
+	} else {
+		/* read back current state */
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, NULL, 0,
+			buf, WLC_IOCTL_MAXLEN)) < 0)
+			return ret;
+		cnt = test_status->cur_test_cnt;
+
+		switch (test_status->test_stage) {
+			case WL_OTA_TEST_IDLE:		/* Idle state */
+				printf("Init state \n");
+				break;
+			case WL_OTA_TEST_ACTIVE:	/* Active test state */
+				/* Read back details for current test arg */
+				cnt++;
+				ret = wlu_iovar_getbuf(wl, cmd->name, &cnt, sizeof(uint16),
+					buf, WLC_IOCTL_MAXLEN);
+				if (test_status->sync_status == WL_OTA_SYNC_ACTIVE)
+					printf("Waiting for sync \n");
+				else
+					wl_ota_display_test_option(&(test_status->test_arg), cnt);
+				break;
+			case WL_OTA_TEST_SUCCESS:	/* Test Finished */
+				printf("Test completed \n");
+				break;
+			case WL_OTA_TEST_FAIL:		/* Test Failed to complete */
+				wl_otatest_display_skip_test_reason(test_status->skip_test_reason);
+				break;
+			default:
+				printf("Invalid test Phase \n");
+				break;
+		}
+	}
+	return ret;
+}
+static int
+wl_otatest_rssi(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	int16 cnt = 0, rssi;
+	wl_ota_test_rssi_t *test_rssi = NULL;
+	wl_ota_rx_rssi_t *rx_rssi = NULL;
+
+	if (*++(argv)) {
+		printf("Too many arguments\n");
+		return BCME_ERROR;
+	}
+
+	test_rssi = (wl_ota_test_rssi_t *)buf;
+	if ((ret = wlu_iovar_getbuf(wl, cmd->name, NULL, 0,
+		buf, WLC_IOCTL_MEDLEN)) < 0)
+		return ret;
+
+	if (test_rssi->version != WL_OTARSSI_T_VERSION)
+		return BCME_VERSION;
+
+	rx_rssi = test_rssi->rx_rssi;
+	for (cnt = 0; cnt < test_rssi->testcnt; cnt++) {
+		rssi = dtoh16(rx_rssi[cnt].rssi);
+		if (rssi < 0)
+			printf("-%d.%02d  ", ((-rssi) >> 2),
+				((-rssi) & 0x3)*25);
+		else
+			printf("%d.%02d  ", (rssi >> 2),
+				(rssi & 0x3)*25);
+	}
+	printf("\n");
+	return ret;
+}
+/* To stop the ota test suite */
+static int
+wl_ota_teststop(void *wl, cmd_t *cmd, char **argv)
+{
+	UNUSED_PARAMETER(argv);
+	return (wlu_iovar_setint(wl, cmd->name, 1));
+}
diff --git a/wl/src/wl/exe/wluc_p2p.c b/wl/src/wl/exe/wluc_p2p.c
new file mode 100644
index 0000000..dacafb3
--- /dev/null
+++ b/wl/src/wl/exe/wluc_p2p.c
@@ -0,0 +1,539 @@
+/*
+ * wl p2p command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_p2p.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifdef LINUX
+#include <time.h>
+#endif /* LINUX */
+
+static cmd_func_t wl_p2p_state;
+static cmd_func_t wl_p2p_scan;
+static cmd_func_t wl_p2p_ifadd;
+static cmd_func_t wl_p2p_ifdel;
+static cmd_func_t wl_p2p_ifupd;
+static cmd_func_t wl_p2p_if;
+static cmd_func_t wl_p2p_ops;
+static cmd_func_t wl_p2p_noa;
+
+static cmd_t wl_p2p_cmds[] = {
+	{ "p2p_ssid", wl_ssid, WLC_GET_VAR, WLC_SET_VAR,
+	"set WiFi P2P wildcard ssid.\n"
+	"\tUsage: wl p2p_ssid <ssid>"
+	},
+	{ "p2p_state", wl_p2p_state, -1, WLC_SET_VAR,
+	"set WiFi P2P discovery state.\n"
+	"\tUsage: wl p2p_state <state> [<chanspec> <dwell time>]"
+	},
+	{ "p2p_scan", wl_p2p_scan, -1, WLC_SET_VAR,
+	"initiate WiFi P2P scan.\n"
+	"\tUsage: wl p2p_scan S|E <scan parms>\n"
+	SCAN_USAGE
+	},
+	{ "p2p_ifadd", wl_p2p_ifadd, -1, WLC_SET_VAR,
+	"add WiFi P2P interface\n"
+	"\tUsage: wl p2p_ifadd <MAC-address> go|client|dyngo [chanspec]\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx"
+	},
+	{ "p2p_ifdel", wl_p2p_ifdel, -1, WLC_SET_VAR,
+	"delete WiFi P2P interface\n"
+	"\tUsage: wl p2p_ifdel <MAC-address>\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx"
+	},
+	{ "p2p_ifupd", wl_p2p_ifupd, -1, WLC_SET_VAR,
+	"update an interface to WiFi P2P interface\n"
+	"\tUsage: wl p2p_ifupd <MAC-address> go|client\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx"
+	},
+	{ "p2p_if", wl_p2p_if, WLC_GET_VAR, -1,
+	"query WiFi P2P interface bsscfg index\n"
+	"\tUsage: wl p2p_if <MAC-address>\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx"
+	},
+	{ "p2p_noa", wl_p2p_noa, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get WiFi P2P NoA schedule\n"
+	"\tUsage: wl p2p_noa <type> <type-specific-params>\n"
+	"\t\ttype 0: Scheduled Absence (on GO): <type> <action> <action-specific-params>\n"
+	"\t\t\taction -1: Cancel the schedule: <type> <action>\n"
+	"\t\t\taction 0,1,2: <type> <action> <option> <option-specific-params>\n"
+	"\t\t\t\taction 0: Do nothing during absence periods\n"
+	"\t\t\t\taction 1: Sleep during absence periods\n"
+	"\t\t\t\toption 0: <start:tsf> <interval> <duration> <count> ...\n"
+	"\t\t\t\toption 1 [<start-percentage>] <duration-percentage>\n"
+	"\t\t\t\toption 2 <start:tsf-offset> <interval> <duration> <count>\n"
+	"\t\ttype 1: Requested Absence (on GO): \n"
+	"\t\t\taction -1: Cancel the schedule: <type> <action>\n"
+	"\t\t\taction 2: <type> <action> <option> <option-specific-params>\n"
+	"\t\t\t\taction 2: Turn off GO beacons and probe responses during absence period\n"
+	"\t\t\t\toption 2 <start:tsf-offset> <interval> <duration> <count>"
+	},
+	{ "p2p_ops", wl_p2p_ops, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get WiFi P2P OppPS and CTWindow\n"
+	"\tUsage: wl p2p_ops <ops> [<ctw>]\n"
+	"\t\t<ops>:\n"
+	"\t\t\t0: Disable OppPS\n"
+	"\t\t\t1: Enable OppPS\n"
+	"\t\t<ctw>:\n"
+	"\t\t\t10 and up to beacon interval"
+	},
+	{ "p2p_da_override", wl_iov_mac, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set WiFi P2P device interface addr\n"
+	"\tUsage: wl p2p_da_override <MAC-address>\n"
+	"MAC-address: xx:xx:xx:xx:xx:xx\n"
+	"(When MAC-address is set to 00:00:00:00:00:00, default da restored)"
+	},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_p2p_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register p2p commands */
+	wl_module_cmds_register(wl_p2p_cmds);
+}
+
+static int
+wl_p2p_state(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2p_disc_st_t st;
+	int count;
+	char *endptr;
+
+	argv++;
+
+	count = ARGCNT(argv);
+	if (count < 1)
+		return BCME_USAGE_ERROR;
+
+	st.state = (uint8) strtol(argv[0], &endptr, 0);
+	if (st.state == WL_P2P_DISC_ST_LISTEN) {
+		if (count != 3)
+			return BCME_USAGE_ERROR;
+		if ((st.chspec = wf_chspec_aton(argv[1])) == 0) {
+			fprintf(stderr, "error parsing chanspec arg \"%s\"\n", argv[1]);
+			return BCME_BADARG;
+		}
+		st.chspec = wl_chspec_to_driver(st.chspec);
+		if (st.chspec == INVCHANSPEC) {
+			return BCME_USAGE_ERROR;
+		}
+		st.dwell = (uint16) strtol(argv[2], &endptr, 0);
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, &st, sizeof(st));
+}
+
+static int
+wl_p2p_scan(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2p_scan_t *params = NULL;
+	int params_size = 0;
+	int malloc_size = 0;
+	int sparams_size = 0;
+	int err = 0;
+
+	if (*(argv + 1) != NULL) {
+		malloc_size = sizeof(wl_p2p_scan_t);
+		switch (toupper(**(argv + 1))) {
+		case 'S':
+			malloc_size += WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+			break;
+		case 'E':
+			malloc_size += OFFSETOF(wl_escan_params_t, params) +
+			        WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16);
+			break;
+		}
+	}
+	if (malloc_size == 0) {
+		fprintf(stderr, "wrong syntax, need 'S' or 'E'\n");
+		return BCME_BADARG;
+	}
+
+	malloc_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t);
+	params = (wl_p2p_scan_t *)malloc(malloc_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", malloc_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, malloc_size);
+
+	switch (toupper(**(argv + 1))) {
+	case 'S': {
+		wl_scan_params_t *sparams = (wl_scan_params_t *)(params+1);
+		sparams_size = malloc_size - sizeof(wl_p2p_scan_t);
+
+		params->type = 'S';
+
+		if ((err = wl_scan_prep(wl, cmd, argv + 1, sparams, &sparams_size)) == 0)
+			params_size = sizeof(wl_p2p_scan_t) + sparams_size;
+		break;
+	}
+
+	case 'E': {
+		wl_escan_params_t *eparams = (wl_escan_params_t *)(params+1);
+		sparams_size = malloc_size - sizeof(wl_p2p_scan_t) - sizeof(wl_escan_params_t);
+
+		params->type = 'E';
+
+		eparams->version = htod32(ESCAN_REQ_VERSION);
+		eparams->action = htod16(WL_SCAN_ACTION_START);
+
+#if defined(linux)
+		srand((unsigned)time(NULL));
+		eparams->sync_id = htod16(rand() & 0xffff);
+#else
+		eparams->sync_id = htod16(4321);
+#endif /* #if defined(linux) */
+
+		if ((err = wl_scan_prep(wl, cmd, argv + 1, &eparams->params, &sparams_size)) == 0)
+			params_size = sizeof(wl_p2p_scan_t) + sizeof(wl_escan_params_t) +
+				sparams_size;
+		break;
+	}
+	}
+
+	if (!err)
+		err = wlu_iovar_setbuf(wl, cmd->name, params, params_size, buf, WLC_IOCTL_MAXLEN);
+
+	free(params);
+	return err;
+}
+
+static int
+wl_p2p_ifadd(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2p_if_t ifreq;
+	int count;
+
+	argv++;
+
+	count = ARGCNT(argv);
+	if (count < 2)
+		return BCME_USAGE_ERROR;
+
+	if (!wl_ether_atoe(argv[0], &ifreq.addr))
+		return BCME_USAGE_ERROR;
+
+	if (stricmp(argv[1], "go") == 0)
+		ifreq.type = WL_P2P_IF_GO;
+	else if (stricmp(argv[1], "client") == 0)
+		ifreq.type = WL_P2P_IF_CLIENT;
+	else if (stricmp(argv[1], "dyngo") == 0)
+		ifreq.type = WL_P2P_IF_DYNBCN_GO;
+	else
+		return BCME_USAGE_ERROR;
+
+	if (ifreq.type == WL_P2P_IF_GO || ifreq.type == WL_P2P_IF_DYNBCN_GO) {
+		if (count > 2) {
+			if ((ifreq.chspec = wf_chspec_aton(argv[2])) == 0) {
+				fprintf(stderr, "error parsing chanspec arg \"%s\"\n", argv[2]);
+				return BCME_BADARG;
+			}
+			ifreq.chspec = wl_chspec_to_driver(ifreq.chspec);
+			if (ifreq.chspec == INVCHANSPEC) {
+				return BCME_BADARG;
+			}
+		}
+		else
+			ifreq.chspec = 0;
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, &ifreq, sizeof(ifreq));
+}
+
+static int
+wl_p2p_ifdel(void *wl, cmd_t *cmd, char **argv)
+{
+	struct ether_addr addr;
+	int count;
+
+	argv++;
+
+	count = ARGCNT(argv);
+	if (count != 1)
+		return BCME_USAGE_ERROR;
+
+	if (!wl_ether_atoe(argv[0], &addr))
+		return BCME_USAGE_ERROR;
+
+	return wlu_var_setbuf(wl, cmd->name, &addr, sizeof(addr));
+}
+
+static int
+wl_p2p_ifupd(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2p_if_t ifreq;
+	int count;
+	int ret;
+	int bsscfg_idx = 0;
+	int consumed = 0;
+
+	argv++;
+
+	/* parse a bsscfg_idx option if present */
+	if ((ret = wl_cfg_option(argv, cmd->name, &bsscfg_idx, &consumed)) != 0)
+		return ret;
+	argv += consumed;
+	if (consumed == 0)
+		bsscfg_idx = -1;
+
+	count = ARGCNT(argv);
+	if (count < 2)
+		return BCME_USAGE_ERROR;
+
+	if (!wl_ether_atoe(argv[0], &ifreq.addr))
+		return BCME_USAGE_ERROR;
+
+	if (stricmp(argv[1], "go") == 0)
+		ifreq.type = WL_P2P_IF_GO;
+	else if (stricmp(argv[1], "client") == 0)
+		ifreq.type = WL_P2P_IF_CLIENT;
+	else
+		return BCME_USAGE_ERROR;
+
+	ifreq.chspec = 0;
+
+	if (bsscfg_idx == -1)
+		return wlu_var_setbuf(wl, cmd->name, &ifreq, sizeof(ifreq));
+	return wlu_bssiovar_setbuf(wl, cmd->name, bsscfg_idx,
+	                          &ifreq, sizeof(ifreq),
+	                          buf, WLC_IOCTL_MAXLEN);
+}
+
+static int
+wl_p2p_if(void *wl, cmd_t *cmd, char **argv)
+{
+	struct ether_addr addr;
+	int count;
+	wl_p2p_ifq_t *ptr;
+	int err;
+
+	argv++;
+
+	count = ARGCNT(argv);
+	if (count != 1)
+		return BCME_USAGE_ERROR;
+
+	if (!wl_ether_atoe(argv[0], &addr))
+		return BCME_USAGE_ERROR;
+
+	err = wlu_var_getbuf(wl, cmd->name, &addr, sizeof(addr), (void*)&ptr);
+	if (err >= 0)
+		printf("%u %s\n", dtoh32(ptr->bsscfgidx), (ptr->ifname));
+
+	return err;
+}
+
+static int
+wl_p2p_ops(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2p_ops_t ops;
+	int count;
+	char *endptr;
+
+	argv++;
+
+	count = ARGCNT(argv);
+	if (count < 1) {
+		wl_p2p_ops_t *ops;
+		int err;
+
+		err = wlu_var_getbuf(wl, cmd->name, NULL, 0, (void *)&ops);
+		if (err != BCME_OK) {
+			fprintf(stderr, "%s: error %d\n", cmd->name, err);
+			return err;
+		}
+
+		printf("ops: %u ctw: %u\n", ops->ops, ops->ctw);
+
+		return BCME_OK;
+	}
+
+	ops.ops = (uint8) strtol(argv[0], &endptr, 0);
+	if (ops.ops != 0) {
+		if (count != 2)
+			return BCME_USAGE_ERROR;
+		ops.ctw = (uint8) strtol(argv[1], &endptr, 0);
+	}
+	else
+		ops.ctw = 0;
+
+	return wlu_var_setbuf(wl, cmd->name, &ops, sizeof(ops));
+}
+
+static int
+wl_p2p_noa(void *wl, cmd_t *cmd, char **argv)
+{
+	int count;
+	wl_p2p_sched_t *noa;
+	int len;
+	int i;
+	char *endptr;
+
+	argv ++;
+
+	strcpy(buf, cmd->name);
+
+	count = ARGCNT(argv);
+	if (count < 2) {
+		int err = wlu_get(wl, WLC_GET_VAR, buf, WLC_IOCTL_MAXLEN);
+		wl_p2p_sched_t *sched;
+		int i;
+
+		if (err != BCME_OK) {
+			fprintf(stderr, "%s: error %d\n", cmd->name, err);
+			return err;
+		}
+
+		sched = (wl_p2p_sched_t *)buf;
+		for (i = 0; i < 16; i ++) {
+			if (sched->desc[i].count == 0)
+				break;
+			printf("start: %u interval: %u duration: %u count: %u\n",
+			       sched->desc[i].start, sched->desc[i].interval,
+			       sched->desc[i].duration, sched->desc[i].count);
+		}
+
+		return BCME_OK;
+	}
+
+	len = strlen(buf);
+
+	noa = (wl_p2p_sched_t *)&buf[len + 1];
+	len += 1;
+
+	noa->type = (uint8)strtol(argv[0], &endptr, 0);
+	len += sizeof(noa->type);
+	noa->action = (uint8)strtol(argv[1], &endptr, 0);
+	len += sizeof(noa->action);
+
+	argv += 2;
+	count -= 2;
+
+	/* action == -1 is to cancel the current schedule */
+	if (noa->action == WL_P2P_SCHED_ACTION_RESET) {
+		/* the fixed portion of wl_p2p_sched_t with action == WL_P2P_SCHED_ACTION_RESET
+		 * is required to cancel the curret schedule.
+		 */
+		len += (char *)&noa->desc[0] - ((char *)buf + len);
+	}
+	/* Take care of any special cases only and let all other cases fall through
+	 * as normal 'start/interval/duration/count' descriptions.
+	 * All cases start with 'type' 'action' 'option'.
+	 * Any count value greater than 255 is to repeat unlimited.
+	 */
+	else {
+		switch (noa->type) {
+		case WL_P2P_SCHED_TYPE_ABS:
+		case WL_P2P_SCHED_TYPE_REQ_ABS:
+			if (count < 1)
+				return BCME_USAGE_ERROR;
+			noa->option = (uint8)strtol(argv[0], &endptr, 0);
+			len += sizeof(noa->option);
+			argv += 1;
+			count -= 1;
+			break;
+		}
+
+		/* add any paddings before desc field */
+		len += (char *)&noa->desc[0] - ((char *)buf + len);
+
+		switch (noa->type) {
+		case WL_P2P_SCHED_TYPE_ABS:
+			switch (noa->option) {
+			case WL_P2P_SCHED_OPTION_BCNPCT:
+				if (count == 1) {
+					noa->desc[0].duration = htod32(strtol(argv[0], &endptr, 0));
+					noa->desc[0].start = 100 - noa->desc[0].duration;
+				}
+				else if (count == 2) {
+					noa->desc[0].start = htod32(strtol(argv[0], &endptr, 0));
+					noa->desc[0].duration = htod32(strtol(argv[1], &endptr, 0));
+				}
+				else {
+					fprintf(stderr, "Usage: wl p2p_noa 0 %d 1 "
+					        "<start-pct> <duration-pct>\n",
+					        noa->action);
+					return BCME_USAGE_ERROR;
+				}
+				len += sizeof(wl_p2p_sched_desc_t);
+				break;
+
+			default:
+				if (count < 4 || (count % 4) != 0) {
+					fprintf(stderr, "Usage: wl p2p_noa 0 %d 0 "
+					        "<start> <interval> <duration> <count> ...\n",
+					        noa->action);
+					return BCME_USAGE_ERROR;
+				}
+				goto normal;
+			}
+			break;
+
+		default:
+			if (count != 4) {
+				fprintf(stderr, "Usage: wl p2p_noa 1 %d "
+				        "<start> <interval> <duration> <count> ...\n",
+				        noa->action);
+				return BCME_USAGE_ERROR;
+			}
+			/* fall through... */
+		normal:
+			for (i = 0; i < count; i += 4) {
+				noa->desc[i / 4].start = htod32(strtoul(argv[i], &endptr, 0));
+				noa->desc[i / 4].interval = htod32(strtol(argv[i + 1], &endptr, 0));
+				noa->desc[i / 4].duration = htod32(strtol(argv[i + 2], &endptr, 0));
+				noa->desc[i / 4].count = htod32(strtol(argv[i + 3], &endptr, 0));
+				len += sizeof(wl_p2p_sched_desc_t);
+			}
+			break;
+		}
+	}
+
+	return wlu_set(wl, WLC_SET_VAR, buf, len);
+}
diff --git a/wl/src/wl/exe/wluc_p2po.c b/wl/src/wl/exe/wluc_p2po.c
new file mode 100644
index 0000000..6fc7f98
--- /dev/null
+++ b/wl/src/wl/exe/wluc_p2po.c
@@ -0,0 +1,1050 @@
+/*
+ * wl p2po command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_p2po.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#include <string.h>
+
+#ifdef LINUX
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* LINUX */
+
+static cmd_func_t wl_p2po_listen;
+static cmd_func_t wl_p2po_addsvc;
+static cmd_func_t wl_p2po_delsvc;
+static cmd_func_t wl_p2po_sd_reqresp;
+static cmd_func_t wl_p2po_listen_channel;
+static cmd_func_t wl_p2po_find_config;
+static int wl_p2po_gas_config(void *wl, cmd_t *cmd, char **argv);
+static int wl_p2po_wfds_seek_get(void *wl, cmd_t *cmd, char **argv);
+static int wl_p2po_wfds_seek_add(void *wl, cmd_t *cmd, char **argv);
+static int wl_p2po_wfds_seek_del(void *wl, cmd_t *cmd, char **argv);
+static int wl_p2po_wfds_advertise_add(void *wl, cmd_t *cmd, char **argv);
+static int wl_p2po_wfds_advertise_del(void *wl, cmd_t *cmd, char **argv);
+#if defined(linux)
+static cmd_func_t wl_p2po_results;
+#endif	/* linux */
+
+
+static cmd_t wl_p2po_cmds[] = {
+	{ "p2po_listen", wl_p2po_listen, -1, -1,
+	"start/get listen\n"
+	"\n"
+	"\tStart listen\n"
+	"\tusage: p2po_listen <period(ms)> <interval(ms)> [count]\n"
+	"\n"
+	"\tRead back listen period, interval, count\n"
+	"\tusage: p2po_listen"
+	},
+	{ "p2po_find", wl_var_void, -1, WLC_SET_VAR,
+	"start discovery"
+	},
+	{ "p2po_stop", wl_var_void, -1, WLC_SET_VAR,
+	"stop both P2P listen and P2P device discovery offload\n"
+	"\tusage: p2po_stop"
+	},
+	{ "p2po_addsvc", wl_p2po_addsvc, -1, WLC_SET_VAR,
+	"add query-service pair\n"
+	"\tusage: p2po_addsvc <protocol> <\"query\"> <\"response\">\n"
+	"\t\t<protocol>: 1 = Bonjour, 2 = UPnP"
+	},
+	{ "p2po_delsvc", wl_p2po_delsvc, -1, WLC_SET_VAR,
+	"delete query-service pair\n"
+	"\tusage: p2po_delsvc <protocol> <\"query\">\n"
+	"\t\t<protocol>: 1 = Bonjour, 2 = UPnP, 0 = delete all"
+	},
+	{ "p2po_sd_req_resp", wl_p2po_sd_reqresp, -1, WLC_SET_VAR,
+	"find a service\n"
+	"\tusage: p2po_sd_req_resp <protocol> <\"query\">\n"
+	"\t\t<protocol>: 1 = Bonjour, 2 = UPnP"
+	},
+	{ "p2po_sd_cancel", wl_var_void, -1, WLC_SET_VAR,
+	"cancel finding a service"
+	},
+	{ "p2po_listen_channel", wl_p2po_listen_channel, WLC_GET_VAR, WLC_SET_VAR,
+	"set listen channel to channel 1, 6, 11, or default\n"
+	"\tusage: p2po_listen_channel <1|6|11|0>"
+	},
+	{ "p2po_find_config", wl_p2po_find_config, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the parameters for the p2po_find command\n"
+	"\tusage: p2po_find_config <flags> <home_time> <social channels>\n"
+	"\t       flags: bit 0 = scan for both P2P devices and non-P2P APs\n"
+	"\texample: p2po_find_config 0 100 11 165\n"
+	"\t         Scan for only P2P devices, home time 100ms, social channels 11 165\n"
+	},
+#if defined(linux)
+	{ "p2po_results", wl_p2po_results, -1, WLC_SET_VAR,
+	"Listens and displays P2PO results."
+	},
+#endif	/* linux */
+	{ "p2po_gas_config", wl_p2po_gas_config, WLC_GET_VAR, WLC_SET_VAR,
+	"set GAS state machine tunable parameters\n"
+	"\tusage: p2po_gas_config <max_retrans> <resp_timeout> <max_comeback_delay> <max_retries>"
+	},
+	{ "p2po_wfds_seek_add", wl_p2po_wfds_seek_add, WLC_GET_VAR, WLC_SET_VAR,
+	"\tSet usage: p2po_wfds_seek_add <seek_hdl> <service_hash> <macaddr> <service_name>"
+	" [service_info_req]\n"
+	"Add a WFDS service to seek\n"
+	"\t\t<hdl> An arbitrary number identifying this add request\n"
+	"\t\t<service_hash> 6 hex byte service hash of the service to seek\n"
+	"\t\t<macaddr> 6 hex byte advertiser MAC address to match, all FFs if wildcard\n"
+	"\t\t<service_name> Service name to seek\n"
+	"\t\t<service_info_req> Service Info Request string to send in Service Discovery request\n"
+	"\teg. p2po_wfds_seek_add 1234 1 0x090a0b112233 org.wi-fi.wfds.print.rx\n"
+	"\teg. p2po_wfds_seek_add 1234 1 0x090a0b112233 org.wi-fi.wfds.* abcdefg"
+	"\n"
+	"\tGet usage: p2po_wfds_seek_add <seek_hdl>"
+	"Get information about a configured WFDS seek\n"
+	"\t\t<hdl> The hdl of a previously added WFDS service to seek\n"
+	"\teg. p2po_wfds_seek_add 1234"
+	},
+	{ "p2po_wfds_seek_del", wl_p2po_wfds_seek_del, -1, WLC_SET_VAR,
+	"delete a WFDS service to seek\n"
+	"\tusage: p2po_wfds_seek_del <seek_hdl>\n"
+	"\t\t<hdl> the hdl specified in a previous p2po_wfds_seek_add"
+	},
+	{ "p2po_wfds_seek_dump", wl_var_void, -1, WLC_SET_VAR,
+	"dump WFDS services to seek"
+	},
+	{ "p2po_wfds_advertise_add", wl_p2po_wfds_advertise_add, WLC_GET_VAR, WLC_SET_VAR,
+	"add a WFDS service to advertise\n"
+	"\tSet usage: p2po_wfds_advertise_add <adv_hdl> <adv_id> <cfg_meth>"
+	" <hash> <service_name> <status> [service_info]\n"
+	"\t\t<hdl> An arbitrary number identifying this add request\n"
+	"\t\t<adv_id> 4 hex byte advertisement ID\n"
+	"\t\t<cfg_meth> 2 hex byte WPS config methods supported by this service\n"
+	"\t\t<service_hash> 6 hex byte service hash of the service to advertise\n"
+	"\t\t<service_name> Service name. Text string up to 255 chars\n"
+	"\t\t<status> Status code of the service to advertise, 0...255\n"
+	"\t\t<service_info> Service information to send in Service Discovery Response."
+	" Text string up to 255 chars\n"
+	"\teg. p2po_wfds_advertise_add 4321 0x7a7b9e9f 0x0080 0x1133557799aa"
+	" org.wi-fi.wfds.print.rx 0 abcdefg"
+	"\n"
+	"\tGet usage: p2po_wfds_advertise_add <adv_hdl>"
+	"Get information about a configured WFDS advertise service\n"
+	"\t\t<adv_hdl> The hdl of a previously added WFDS advertise service\n"
+	"\teg. p2po_wfds_advertise_add 4321"
+	},
+	{ "p2po_wfds_advertise_del", wl_p2po_wfds_advertise_del, -1, WLC_SET_VAR,
+	"\tusage: p2po_wfds_advertise_del <adv_hdl>\n"
+	"\t\t<hdl> the hdl specified in a previous p2po_wfds_advertise_add\n"
+	"\teg. p2po_wfds_advertise_del 4321"
+	},
+	{ "p2po_wfds_advertise_dump", wl_var_void, -1, WLC_SET_VAR,
+	"dump WFDS services to advertise"
+	},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_p2po_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register p2po commands */
+	wl_module_cmds_register(wl_p2po_cmds);
+}
+
+#define UPNP_QUERY_VERSION	"0x10"
+#define	BCM_SVC_RPOTYPE_ALL	0
+#define	BCM_SVC_RPOTYPE_BONJOUR	1
+#define	BCM_SVC_RPOTYPE_UPNP	2
+#define	BCM_SVC_RPOTYPE_WSD	3
+#define	BCM_SVC_RPOTYPE_VENDOR	255
+
+static int
+wl_p2po_listen(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, params_size;
+	wl_p2po_listen_t	params;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1]) {
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &params,
+			(sizeof(wl_p2po_listen_t)))) < 0)
+			return (err);
+		printf("    listen period=%u listen interval=%u listen count=%u\n",
+			dtoh16(params.period), dtoh16(params.interval), dtoh16(params.count));
+		return BCME_OK;
+	}
+
+	if (!argv[2] || !argv[3])
+		return BCME_USAGE_ERROR;
+
+		params.period = atoi(argv[1]);
+		params.interval = atoi(argv[2]);
+		params.count = atoi(argv[3]);
+
+	params_size = sizeof(wl_p2po_listen_t);
+
+	err = wlu_iovar_set(wl, "p2po_listen", &params, params_size);
+
+	return err;
+}
+
+static int
+wl_p2po_addsvc(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int protocol, query_len, response_len, params_size;
+	char *query, *response;
+	wl_p2po_qr_t *params;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1] || !argv[2] || !argv[3]) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	protocol = atoi(argv[1]);
+	if (protocol == BCM_SVC_RPOTYPE_BONJOUR) {
+		query = argv[2];
+		response = argv[3];
+		query_len = hexstr2hex(query);
+		response_len = hexstr2hex(response);
+	} else if (protocol == BCM_SVC_RPOTYPE_UPNP) {
+		if (memcmp(argv[2], UPNP_QUERY_VERSION, strlen(UPNP_QUERY_VERSION)) != 0 ||
+			memcmp(argv[3], UPNP_QUERY_VERSION, strlen(UPNP_QUERY_VERSION)) != 0) {
+			fprintf(stderr, "UPnP query/response string must start with 0x10");
+			return BCME_USAGE_ERROR;
+		}
+		query = argv[2] + strlen(UPNP_QUERY_VERSION) - 1;
+		response = argv[3] + strlen(UPNP_QUERY_VERSION) - 1;
+		query[0] = strtoul(UPNP_QUERY_VERSION, NULL, 16);
+		response[0] = strtoul(UPNP_QUERY_VERSION, NULL, 16);
+
+		query_len = strlen(query);
+		response_len = strlen(response);
+	}
+	else {
+		fprintf(stderr, "<protocol> should be <1|2>\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	params_size = sizeof(wl_p2po_qr_t) + query_len + response_len - 1;
+	params = (wl_p2po_qr_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+
+	params->protocol = protocol;
+	params->query_len = query_len;
+	params->response_len = response_len;
+	memcpy(params->qrbuf, query, query_len);
+	memcpy(params->qrbuf+query_len, response, response_len);
+
+	err = wlu_iovar_setbuf(wl, "p2po_addsvc", params, params_size, buf, WLC_IOCTL_MAXLEN);
+
+	free(params);
+
+	return err;
+}
+
+static int
+wl_p2po_delsvc(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int protocol, query_len, params_size;
+	char *query = NULL;
+	wl_p2po_qr_t *params;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1] || (*argv[1] != '0' && !argv[2])) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (*argv[1] == '0') {
+		protocol = 0;
+		query_len = 0;
+	}
+	else {
+		protocol = atoi(argv[1]);
+		if (protocol == BCM_SVC_RPOTYPE_BONJOUR) {
+			query = argv[2];
+			query_len = hexstr2hex(query);
+		} else if (protocol == BCM_SVC_RPOTYPE_UPNP) {
+			if (memcmp(argv[2], UPNP_QUERY_VERSION, strlen(UPNP_QUERY_VERSION)) != 0) {
+				fprintf(stderr, "UPnP query string must start with 0x10");
+				return BCME_USAGE_ERROR;
+			}
+			query = argv[2] + strlen(UPNP_QUERY_VERSION) - 1;
+			query[0] = strtoul(UPNP_QUERY_VERSION, NULL, 16);
+
+			query_len = strlen(query);
+		}
+		else {
+			fprintf(stderr, "<protocol> should be <1|2>\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	params_size = sizeof(wl_p2po_qr_t) + (query_len ? query_len - 1 : 0);
+	params = (wl_p2po_qr_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+
+	params->protocol = protocol;
+	params->query_len = query_len;
+	if (query_len)
+		memcpy(params->qrbuf, query, query_len);
+
+	err = wlu_iovar_set(wl, "p2po_delsvc", params, params_size);
+
+	free(params);
+
+	return err;
+}
+
+static int
+wl_p2po_sd_reqresp(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int transaction_id, protocol, query_len, params_size;
+	char *query = NULL;
+	wl_p2po_qr_t *params;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1] || !argv[2]) {
+			fprintf(stderr, "Too few arguments\n");
+			return BCME_USAGE_ERROR;
+	}
+
+	transaction_id = atoi(argv[1]);
+	if (transaction_id < 0 || transaction_id > 255) {
+		fprintf(stderr, "<transaction id> should be between 0 and 255\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	protocol = atoi(argv[2]);
+	if (!argv[3]) {
+		/* find everything for protocol */
+		query_len = 0;
+	} else if (protocol == BCM_SVC_RPOTYPE_BONJOUR) {
+		query = argv[3];
+		query_len = hexstr2hex(query);
+	} else if (protocol == BCM_SVC_RPOTYPE_UPNP) {
+		if (memcmp(argv[3], UPNP_QUERY_VERSION, strlen(UPNP_QUERY_VERSION)) != 0) {
+			fprintf(stderr, "UPnP query string must start with 0x10");
+			return BCME_USAGE_ERROR;
+		}
+		query = argv[3] + strlen(UPNP_QUERY_VERSION) - 1;
+		query[0] = strtoul(UPNP_QUERY_VERSION, NULL, 16);
+
+		query_len = strlen(query);
+	} else {
+		fprintf(stderr, "<protocol> should be <0|1|2>\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	params_size = sizeof(wl_p2po_qr_t) + (query_len ? query_len - 1 : 0);
+	params = (wl_p2po_qr_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Not enough memory\n");
+		return BCME_NOMEM;
+	}
+
+	params->transaction_id = transaction_id;
+	params->protocol = protocol;
+	params->query_len = query_len;
+	if (query_len)
+		memcpy(params->qrbuf, query, query_len);
+
+	err = wlu_iovar_set(wl, "p2po_sd_req_resp", params, params_size);
+
+	free(params);
+
+	return err;
+}
+
+static int
+wl_p2po_listen_channel(void *wl, cmd_t *cmd, char **argv)
+{
+	int error;
+	int32 val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		val = atoi(*argv);
+		return wlu_iovar_setint(wl, "p2po_listen_channel", val);
+	} else {
+		error =  wlu_iovar_getint(wl, "p2po_listen_channel", &val);
+		if (error < 0)
+			return error;
+		printf("P2P Offload Listen Channel: %d\n", dtoh32(val));
+		return BCME_OK;
+	}
+}
+
+static int
+wl_p2po_find_config(void *wl, cmd_t *cmd, char **argv)
+{
+	uint argc;
+	int error;
+	int i;
+	wl_p2po_find_config_t *fc;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* Get arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc == 0)
+		return BCME_ERROR;
+
+	if (argc == 1) {
+		error =  wlu_iovar_getbuf(wl, cmd->name, NULL, 0, buf, WLC_IOCTL_MEDLEN);
+		if (error < 0)
+			return error;
+
+		fc = (wl_p2po_find_config_t*) buf;
+		printf("P2P Offload Find configuration:\n");
+		printf("    Version: %u    Length: %u\n",
+			dtoh16(fc->version), dtoh16(fc->length));
+		printf("    Scan for non-P2P APs: %d\n",
+			(fc->flags & P2PO_FIND_FLAG_SCAN_ALL_APS) != 0);
+		printf("    Search home time: %d\n", dtoh32(fc->search_home_time));
+		printf("    # of social channels: %u\n", fc->num_social_channels);
+		printf("    Social channels:");
+		for (i = 0; i < fc->num_social_channels; i++) {
+			printf(" %u", fc->social_channels[i]);
+		}
+		printf("\n");
+	} else if (argc <= 3) {
+		fprintf(stderr, "At least 1 social channel is required.\n");
+		error = BCME_BADARG;
+	} else {
+		uint fc_size;
+		uint16 channel;
+		uint j;
+
+		fc_size = sizeof(wl_p2po_find_config_t) + (argc - 2) * sizeof(uint16);
+		fc = (wl_p2po_find_config_t*) malloc(fc_size);
+		if (fc == NULL) {
+			printf("Cannot not allocate %d bytes for p2po_find_config buffer\n",
+				fc_size);
+			return BCME_NOMEM;
+		}
+		memset(fc, 0, fc_size);
+
+		fc->version = WL_P2PO_FIND_CONFIG_VERSION;
+		fc->length = sizeof(*fc);
+		fc->flags = atoi(argv[1]);
+		fc->search_home_time = atoi(argv[2]);
+
+		/* Set the social channel list */
+		i = 0;
+		for (j = 3; j < argc; j++, i++) {
+			channel = atoi(argv[j]);
+			if (channel == 0) {
+				printf("Invalid channel %s\n", argv[j]);
+				break;
+			} else {
+				fc->social_channels[i] = channel;
+			}
+		}
+		fc->num_social_channels = i;
+
+		error = wlu_iovar_setbuf(wl, cmd->name, fc, fc_size, buf,
+			WLC_IOCTL_MEDLEN);
+		free(fc);
+	}
+
+	return error;
+}
+
+#if defined(linux)
+#define P2PO_EVENTS_BUFFER_SIZE	2048
+
+static int
+wl_p2po_results(void *wl, cmd_t *cmd, char **argv)
+{
+	int fd, err, octets;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	char *data;
+	uint8 event_inds_mask[WL_EVENTING_MASK_LEN];	/* event bit mask */
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+
+	memset(event_inds_mask, '\0', WL_EVENTING_MASK_LEN);
+	event_inds_mask[WLC_E_SERVICE_FOUND / 8] |= 1 << (WLC_E_SERVICE_FOUND % 8);
+	event_inds_mask[WLC_E_GAS_FRAGMENT_RX / 8] |= 1 << (WLC_E_GAS_FRAGMENT_RX % 8);
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		goto exit2;
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		err = -1;
+		goto exit2;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		goto exit1;
+	}
+
+	/* bind the socket first before starting so we won't miss any event */
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		goto exit1;
+	}
+
+	data = (char*)malloc(P2PO_EVENTS_BUFFER_SIZE);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			P2PO_EVENTS_BUFFER_SIZE);
+		err = BCME_NOMEM;
+		goto exit1;
+	}
+
+	/* receive result */
+	while (1) {
+		bcm_event_t *bcm_event;
+		int event_type;
+
+		octets = recv(fd, data, P2PO_EVENTS_BUFFER_SIZE, 0);
+		bcm_event = (bcm_event_t *)data;
+		event_type = ntoh32(bcm_event->event.event_type);
+
+		if (octets >= (int)sizeof(bcm_event_t)) {
+			if (event_type == WLC_E_SERVICE_FOUND) {
+				uint32 status = ntoh32(bcm_event->event.status);
+				wl_event_sd_t *sd_data =
+					(wl_event_sd_t *)&data[sizeof(bcm_event_t)];
+
+				sd_data->channel = dtoh16(sd_data->channel);
+
+				printf("WLC_E_SERVICE_FOUND: %s\n",
+					status == WLC_E_STATUS_PARTIAL ? "WLC_E_STATUS_PARTIAL" :
+					status == WLC_E_STATUS_SUCCESS ? "WLC_E_STATUS_SUCCESS" :
+					status == WLC_E_STATUS_FAIL ? "WLC_E_STATUS_FAIL" :
+					"unknown");
+				printf("   channel         = %d\n", sd_data->channel);
+				printf("   peer            = %s\n",
+					wl_ether_etoa(&bcm_event->event.addr));
+				if (status == WLC_E_STATUS_SUCCESS) {
+					wl_sd_tlv_t *tlv;
+					int i;
+
+					tlv = sd_data->tlv;
+					for (i = 0; i < sd_data->count; i++) {
+						printf("   [TLV %d]\n", i);
+						tlv->length = dtoh16(tlv->length);
+						printf("   protocol type   = %s\n",
+							tlv->protocol == 0 ? "ALL" :
+							tlv->protocol == BCM_SVC_RPOTYPE_BONJOUR ?
+								"BONJOUR" :
+							tlv->protocol == BCM_SVC_RPOTYPE_UPNP ?
+								"UPnP" :
+							tlv->protocol == BCM_SVC_RPOTYPE_WSD ?
+								"WS-Discovery" :
+							tlv->protocol == BCM_SVC_RPOTYPE_VENDOR ?
+								"Vendor specific" : "Unknown");
+						printf("   transaction id  = %u\n",
+							tlv->transaction_id);
+						printf("   status code     = %u\n",
+							tlv->status_code);
+						printf("   length          = %u\n", tlv->length);
+						wl_hexdump(tlv->data, tlv->length);
+
+						tlv = (wl_sd_tlv_t *)((void *)tlv + tlv->length +
+							OFFSETOF(wl_sd_tlv_t, data));
+					}
+				}
+				else {
+					/* fragments */
+				}
+			}
+		}
+	}
+
+	free(data);
+exit1:
+	close(fd);
+exit2:
+	return err;
+}
+#endif	/* linux */
+
+static int
+wl_p2po_gas_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int error;
+	wl_gas_config_t set;
+	wl_gas_config_t* get;
+
+	if (!argv[1]) {
+		error =  wlu_iovar_getbuf(wl, "p2po_gas_config", &set, sizeof(set),
+			buf, WLC_IOCTL_MAXLEN);
+		if (error < 0)
+			return error;
+		get = (wl_gas_config_t*) buf;
+		printf("P2P Offload GAS state machine tunable parameters:\n");
+		printf("    max_retrans=%u resp_timeout=%u\n",
+			dtoh16(get->max_retransmit), dtoh16(get->response_timeout));
+		printf("    max_comeback_delay=%u max_retries=%u\n",
+			dtoh16(get->max_comeback_delay), dtoh16(get->max_retries));
+		return BCME_OK;
+	}
+
+	if (!argv[1] || !argv[2] || !argv[3] || !argv[4]) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	set.max_retransmit = htod16(atoi(argv[1]));
+	set.response_timeout = htod16(atoi(argv[2]));
+	set.max_comeback_delay = htod16(atoi(argv[3]));
+	set.max_retries = htod16(atoi(argv[4]));
+
+	return wlu_iovar_setbuf(wl, cmd->name, &set, sizeof(set), buf, WLC_IOCTL_MEDLEN);
+}
+
+void
+wl_p2po_print_name(char *prefix, uint namelen, uint8 *name)
+{
+	char namez[32 + 1];
+
+	if (namelen > sizeof(namez) - 1)
+		namelen = sizeof(namez) - 1;
+	memcpy(namez, name, namelen);
+	namez[namelen] = '\0';
+
+	printf("%s%u,%s\n", prefix, namelen, namez);
+}
+
+static int
+wl_p2po_wfds_seek_get(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2po_wfds_seek_add_t* seek = (wl_p2po_wfds_seek_add_t*) buf;
+	wl_p2po_wfds_seek_add_t seek0;
+	int ret;
+
+	if (!argv[1]) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	memset(&seek0, 0, sizeof(seek0));
+	seek0.seek_hdl = atoi(argv[1]);
+
+	ret = wlu_iovar_getbuf(wl, cmd->name, &seek0, sizeof(seek0), seek, WLC_IOCTL_MAXLEN);
+	if (ret < 0) {
+		goto exit;
+	}
+
+	printf("Seek service hdl=%u\n", seek->seek_hdl);
+	printf("    hash=0x%02x%02x%02x%02x%02x%02x\n",
+	       seek->service_hash[0], seek->service_hash[1], seek->service_hash[2],
+	       seek->service_hash[3], seek->service_hash[4], seek->service_hash[5]);
+	printf("    mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
+	       seek->addr[0], seek->addr[1], seek->addr[2],
+	       seek->addr[3], seek->addr[4], seek->addr[5]);
+	printf("    name length=%u\n", seek->service_name_len);
+	printf("    name=%s\n", seek->service_name);
+	printf("    info_req length=%u\n", seek->service_info_req_len);
+	printf("    info_req=%s\n", seek->service_info_req);
+
+exit:
+	return ret;
+}
+
+static int
+wl_p2po_wfds_seek_add(void *wl, cmd_t *cmd, char **argv)
+{
+	int malloc_size;
+	wl_p2po_wfds_seek_add_t* seek;
+	int len;
+	int ret;
+	int iovbuf_size;
+	uint8 *iovbuf;
+
+	/* If only a seek_hdl parameter is given, read an existing seek */
+	if (!argv[2]) {
+		return wl_p2po_wfds_seek_get(wl, cmd, argv);
+	}
+
+	if (!argv[4]) {
+		fprintf(stderr, "Too few arguments for iovar SET\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	malloc_size = sizeof(*seek) + MAX_WFDS_SEEK_SVC_INFO_LEN - 1;
+	seek = malloc(malloc_size);
+	if (!seek) {
+		fprintf(stderr, "malloc error, size=%d\n", malloc_size);
+		return BCME_NOMEM;
+	}
+	memset(seek, 0, malloc_size);
+
+	/* Get <seek_hdl> argument */
+	seek->seek_hdl = atoi(argv[1]);
+
+	/* Get <service_hash> argument */
+	if (argv[2]) {
+		if (strlen(argv[2]) != 14) {
+			fprintf(stderr, "bad argument: %s\n", argv[2]);
+			fprintf(stderr, "<svc_hash> must be 6 hex bytes, eg. '0x112233aabbcc'\n");
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		len = wl_pattern_atoh(argv[2], (char*)seek->service_hash);
+		if (len != 6) {
+			fprintf(stderr, "invalid hex string: %s\n", argv[2]);
+			fprintf(stderr, "<svc_hash> must be 6 hex bytes, eg. '0x112233aabbcc'\n");
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+	}
+
+	/* Get <macaddr> argument */
+	if (!wl_ether_atoe(argv[3], (struct ether_addr*) seek->addr)) {
+		fprintf(stderr, "invalid MAC address: %s\n", argv[2]);
+		fprintf(stderr, "<macaddr> must be like '00:90:4c:7a:8b:fe'\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	/* Get <service_name> argument */
+	if (argv[4]) {
+		len = strlen(argv[4]);
+		memcpy(seek->service_name, argv[4], len);
+		seek->service_name_len = len;
+	} else {
+		memcpy(seek->service_name, "org.wi-fi.wfds", strlen("org.wi-fi.wfds"));
+		seek->service_name_len = strlen((char*)seek->service_name);
+	}
+	wl_p2po_print_name("svc_name: ", seek->service_name_len, seek->service_name);
+
+	/* Get optional [service_info] argument */
+	if (argv[5]) {
+		len = strlen(argv[5]);
+		if (len > MAX_WFDS_SEEK_SVC_INFO_LEN)
+			len = MAX_WFDS_SEEK_SVC_INFO_LEN;
+		memcpy(seek->service_info_req, argv[5], len);
+		seek->service_info_req_len = len;
+	} else {
+		seek->service_info_req_len = 0;
+	}
+	wl_p2po_print_name("svc_info_req: ", seek->service_info_req_len,
+		seek->service_info_req);
+
+	iovbuf_size = malloc_size + strlen(cmd->name) + 1;
+	iovbuf = malloc(iovbuf_size);
+	if (!iovbuf) {
+		fprintf(stderr, "malloc error, size=%d\n", iovbuf_size);
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+	ret = wlu_iovar_setbuf(wl, cmd->name, seek, malloc_size, iovbuf, iovbuf_size);
+	free(iovbuf);
+	if (ret != BCME_OK)
+		fprintf(stderr, "%s failed: %d\n", cmd->name, ret);
+exit:
+	free(seek);
+	return ret;
+}
+
+static int
+wl_p2po_wfds_seek_del(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2po_wfds_seek_del_t* del;
+	int ret;
+
+	if (!argv[1]) {
+		fprintf(stderr, "No seek_hdl is specified\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	del = malloc(sizeof(*del));
+	if (!del) {
+		fprintf(stderr, "malloc error, size=%u\n", (uint)sizeof(*del));
+		return BCME_NOMEM;
+	}
+
+	del->seek_hdl = atoi(argv[1]);
+	ret = wlu_iovar_setbuf(wl, cmd->name, del, sizeof(*del), buf, WLC_IOCTL_MAXLEN);
+
+	free(del);
+	return ret;
+}
+
+static int
+wl_p2po_wfds_advertise_get(void *wl, cmd_t *cmd, char **argv)
+{
+	int malloc_size;
+	wl_p2po_wfds_advertise_add_t* add;
+	wl_p2po_wfds_advertise_add_t add0;
+	uint16 svc_info_len;
+	int ret;
+
+	if (!argv[1]) {
+		fprintf(stderr, "Too few arguments\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	memset(&add0, 0, sizeof(add0));
+	add0.advertise_hdl = atoi(argv[1]);
+	svc_info_len = MAX_WFDS_ADV_SVC_INFO_LEN;
+
+	/* Allocate enough memory to hold the full advertisement data */
+	malloc_size = sizeof(*add) + svc_info_len + strlen(cmd->name) + 1;
+	add = malloc(malloc_size);
+	if (!add) {
+		fprintf(stderr, "malloc error, size=%d\n", malloc_size);
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+
+	ret = wlu_iovar_getbuf(wl, cmd->name, &add0, sizeof(add0), add, malloc_size);
+	if (ret < 0) {
+		goto exit;
+	}
+
+	/* Print the retrieved advertisement data */
+	printf("Advertise service hdl=%u\n", add->advertise_hdl);
+	printf("    hash=0x%02x%02x%02x%02x%02x%02x\n",
+	       add->service_hash[0], add->service_hash[1], add->service_hash[2],
+	       add->service_hash[3], add->service_hash[4], add->service_hash[5]);
+	printf("    advertisement_id=0x%x\n", add->advertisement_id);
+	printf("    config_method=0x%x\n", add->service_config_method);
+	printf("    name length=%u\n", add->service_name_len);
+	printf("    name=%s\n", add->service_name);
+	printf("    status=%u\n", add->service_status);
+	printf("    info length=%u\n", add->service_info_len);
+	printf("    info=%s\n", add->service_info);
+	goto exit;
+
+exit:
+	free(add);
+	return ret;
+}
+
+static int
+wl_p2po_wfds_advertise_add(void *wl, cmd_t *cmd, char **argv)
+{
+	int malloc_size;
+	wl_p2po_wfds_advertise_add_t* add = NULL;
+	uint16 svc_info_len = 0;
+	int gen_data_len = 0;
+	int len;
+	int ret;
+	int iovbuf_size;
+	uint8 *iovbuf;
+
+	/* If only an adv_hdl parameter is given, read an existing advertisement */
+	if (!argv[2]) {
+		return wl_p2po_wfds_advertise_get(wl, cmd, argv);
+	}
+
+	if (!argv[6]) {
+		fprintf(stderr, "Too few arguments for iovar SET\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (argv[7]) {
+		svc_info_len = strlen(argv[7]);
+		if (svc_info_len > 7 && memcmp(argv[7], "gendata", 7) == 0) {
+			gen_data_len = atoi((char*)(argv[7] + 7));
+			if (gen_data_len > MAX_WFDS_ADV_SVC_INFO_LEN) {
+				fprintf(stderr, "gendata length %d too long, max is %d\n",
+					gen_data_len, MAX_WFDS_ADV_SVC_INFO_LEN);
+		return BCME_USAGE_ERROR;
+	}
+			svc_info_len = gen_data_len;
+		}
+	}
+
+	malloc_size = sizeof(*add) + svc_info_len;
+	add = malloc(malloc_size);
+	if (!add) {
+		fprintf(stderr, "malloc error, size=%d\n", malloc_size);
+		return BCME_NOMEM;
+	}
+
+	add->advertise_hdl = atoi(argv[1]);
+
+	if (strlen(argv[2]) != 10) {
+		fprintf(stderr, "<adv_id> must be 4 hex bytes, eg. '0x8899aabb'\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	len = wl_pattern_atoh(argv[2], (char*)&add->advertisement_id);
+	if (len != 4) {
+		fprintf(stderr, "<adv_id> must be 4 hex bytes, eg. '0x8899aabb'\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (strlen(argv[3]) != 6) {
+		fprintf(stderr, "<cfg_meth> must be 2 hex bytes, eg. '0x0080'\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	len = wl_pattern_atoh(argv[3], (char*)&add->service_config_method);
+	if (len != 2) {
+		fprintf(stderr, "<cfg_meth> must be 2 hex bytes, eg. '0x0080'\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	if (strlen(argv[4]) != 14) {
+		fprintf(stderr, "Bad <hash> parameter: %s\n", argv[4]);
+		fprintf(stderr, "<hash> must be 6 hex bytes, eg. '0x1133557799aa'\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	len = wl_pattern_atoh(argv[4], (char*)&add->service_hash);
+	if (len != 6) {
+		fprintf(stderr, "Incorrect <hash> parameter: %s\n", argv[4]);
+		fprintf(stderr, "<hash> must be 6 hex bytes, eg. '0x1133557799aa'\n");
+		ret = BCME_USAGE_ERROR;
+		goto exit;
+	}
+
+	add->service_name_len = strlen(argv[5]);
+	memcpy(add->service_name, argv[5], add->service_name_len);
+
+	add->service_status = atoi(argv[6]);
+
+	if (svc_info_len) {
+		add->service_info_len = svc_info_len;
+		if (add->service_info_len > MAX_WFDS_ADV_SVC_INFO_LEN)
+			add->service_info_len = MAX_WFDS_ADV_SVC_INFO_LEN;
+		if (gen_data_len == 0)
+	memcpy(add->service_info, argv[7], add->service_info_len);
+	} else {
+		add->service_info_len = 0;
+	}
+
+
+	/* If the service info consists of a magic string of the form
+	 * "gendata<N>" then generate N bytes of service info data.
+	 * eg. "gendata2048" will generate a 2048 byte service info string
+	 * consisting of the repeated string "0123456789".
+	 */
+	if (gen_data_len > 0) {
+		int i;
+
+		fprintf(stderr, "Generating %u bytes of service info data\n",
+			add->service_info_len);
+		for (i = 0; i < add->service_info_len; i++) {
+			add->service_info[i] = '0' + (i % 10);
+		}
+	}
+
+	iovbuf_size = malloc_size + strlen(cmd->name) + 1;
+	iovbuf = malloc(iovbuf_size);
+	if (!iovbuf) {
+		fprintf(stderr, "malloc error, size=%d\n", iovbuf_size);
+		ret = BCME_NOMEM;
+		goto exit;
+	}
+	ret = wlu_iovar_setbuf(wl, cmd->name, add, malloc_size, iovbuf, iovbuf_size);
+	free(iovbuf);
+	if (ret != BCME_OK)
+		fprintf(stderr, "%s failed: %d\n", cmd->name, ret);
+exit:
+	free(add);
+	return ret;
+}
+
+static int
+wl_p2po_wfds_advertise_del(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_p2po_wfds_advertise_del_t* del;
+	unsigned int malloc_size = sizeof(*del);
+	int ret;
+
+	del = malloc(malloc_size);
+	if (!del) {
+		fprintf(stderr, "malloc error, size=%u\n", malloc_size);
+		return BCME_NOMEM;
+	}
+
+	if (!argv[1]) {
+		fprintf(stderr, "No advertise_hdl is specified\n");
+		free(del);
+		return BCME_USAGE_ERROR;
+	}
+
+	del->advertise_hdl = atoi(argv[1]);
+	ret = wlu_iovar_setbuf(wl, cmd->name, del, sizeof(*del), buf, WLC_IOCTL_MAXLEN);
+
+	free(del);
+	return ret;
+}
diff --git a/wl/src/wl/exe/wluc_pfn.c b/wl/src/wl/exe/wluc_pfn.c
new file mode 100644
index 0000000..f62844e
--- /dev/null
+++ b/wl/src/wl/exe/wluc_pfn.c
@@ -0,0 +1,2578 @@
+/*
+ * wl pfn command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_pfn.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifdef WIN32
+#define bzero(b, len)	memset((b), 0, (len))
+#endif
+
+#ifdef LINUX
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* LINUX */
+
+static cmd_func_t wl_pfn_set;
+static cmd_func_t wl_pfn_add;
+static cmd_func_t wl_pfn_ssid_param;
+static cmd_func_t wl_pfn_add_bssid;
+static cmd_func_t wl_pfn_cfg;
+static cmd_func_t wl_pfn;
+static cmd_func_t wl_pfnbest, wl_pfnbest_bssid;
+static cmd_func_t wl_pfn_suspend;
+static cmd_func_t wl_pfnlbest;
+static cmd_func_t wl_pfn_mem;
+static cmd_func_t wl_pfn_override;
+static cmd_func_t wl_pfn_macaddr;
+#if defined(linux)
+static cmd_func_t wl_pfn_event_check;
+#endif   /* linux */
+static cmd_func_t wl_event_filter;
+static cmd_func_t wl_pfn_roam_alert_thresh;
+#ifdef WL_MPF
+static cmd_func_t wl_pfn_mpfset;
+static cmd_func_t wl_mpf_map;
+static cmd_func_t wl_mpf_state;
+#endif /* WL_MPF */
+
+static cmd_t wl_pfn_cmds[] = {
+	{ "pfnset", wl_pfn_set, -1, -1,
+	"Configures preferred network offload parameter\n"
+	"\tpfnset syntax is: pfnset [scanfrq xxxxx(30 sec)] [netimeout xxxx(60 sec)]"
+	"[slowfrq xxxx(180 sec)] [bestn (2)|[1-BESTN_MAX]] [mscan (0)|[0-MSCAN_MAX]]"
+	"[bdscan (0)|1] [adapt (off)|[smart, strict, slow]]"
+	"[rssi_delta xxxx(30 dBm)] [sort (listorder)|rssi] [bkgscan (0)|1] [immediateevent (0)|1]"
+	"[immediate 0|(1)] [repeat (10)|[1-20]] [exp (2)|[1-5]] [separate 0|(1)]"
+	"[bestn_bssid (0)|1]"},
+	{ "pfnadd", wl_pfn_add, -1, -1,
+	"Adding SSID based preferred networks to monitor and connect\n"
+	"\tpfnadd syntax is: pfnadd ssid <SSID> [hidden (0)|1]"
+	"[imode (bss)|ibss] [same_network (0)|1] [imprecise (0)|1] [trig a|abg|bg]"
+	"[clear] [no_aging (0)|1]"
+	"[amode (open)|shared] [wpa_auth (wpadisabled)|wpapsk|wpa2psk|wpanone|any]"
+	"[wsec WEP|TKIP|AES|TKIPAES] [suppress (neither)|found|lost] [rssi <rssi>(0 dBm)]\n"
+	"Up to 16 SSID networks can be added together in one pfnadd\n"
+	"\tTo specify more than one WPA methods, use a number (same format as wpa_auth iovar) "
+	"as the parameter of wpa_auth (e.g. 0x84 for wpapsk and wpa2psk.)"},
+	{ "pfn_ssid_cfg", wl_pfn_ssid_param, WLC_GET_VAR, WLC_SET_VAR,
+	"Adding PFN SSID params to be used to determine FOUND when associated\n"
+	"\tpfn_ssid_cfg syntax is: pfn_ssid_cfg [min5g_rssi <rssi>(-45 dBm)]\n"
+	"\t[min2g_rssi <rssi>(-50 dBm)] [init_score_max (110)]\n"
+	"\t[cur_bssid_bonus (0)] [same_ssid_bonus (0)] [secure_bonus (0)]\n"
+	"\t[band_5g_bonus (0)] [clear]"},
+	{ "pfnadd_bssid", wl_pfn_add_bssid, -1, -1,
+	"Adding BSSID based preferred networks to monitor and connect\n"
+	"\tpfnadd_bssid syntax is: pfnadd_bssid bssid <BSSID> [suppress (neither)|found|lost]"
+	"[rssi <rssi>(0 dBm)]\n"
+	"\tUp to 150 BSSIDs can be added together in one pfnadd_bssid"},
+	{ "pfncfg", wl_pfn_cfg, -1, -1,
+	"Configures channel list and report type\n"
+	"Usage: pfncfg [channel <list>] [report <type>] [prohibited 1|0] [history_off 1|0]\n"
+	"\treport <type> is ssidonly, bssidonly, or both (default: both)\n"
+	"\tprohibited flag 1: allow and (passively) scan any channel (default 0)"},
+	{ "pfn", wl_pfn, -1, -1,
+	"Enable/disable preferred network off load monitoring\n"
+	"\tpfn syntax is: pfn 0|1"},
+	{ "pfnclear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear the preferred network list\n"
+	"\tpfnclear syntax is: pfnclear"},
+	{ "pfnbest", wl_pfnbest, -1, -1,
+	"Get the best n networks in each of up to m scans, with 16bit timestamp\n"
+	"\tpfnbest syntax is: pfnbest"},
+	{ "pfnlbest", wl_pfnlbest, -1, -1,
+	"Get the best n networks in each scan, up to m scans, with 32bit timestamp\n"
+	"\tpfnbest syntax is: pfnlbest"},
+	{ "pfnbest_bssid", wl_pfnbest_bssid, -1, -1,
+	"Get the best n networks in each of up to m scans, without ssid\n"
+	"\tpfnbest syntax is: pfnbest_bssid"},
+	{ "pfnsuspend", wl_pfn_suspend, -1, -1,
+	"Suspend/resume pno scan\n"
+	"\tpfnsuspend syntax is: pfnsuspend 0|1"},
+	{ "pfnmem", wl_pfn_mem, -1, -1,
+	"Get supported mscan with given bestn\n"
+	"\tpfnmem syntax is: pfnmscan bestn [1-BESTN_MAX]"},
+#if defined(linux)
+	{ "pfneventchk", wl_pfn_event_check, -1, -1,
+	"Listen and prints the preferred network off load event from dongle\n"
+	"\tpfneventchk syntax is: pfneventchk [ifname]"},
+#endif   /* linux */
+	{ "event_filter", wl_event_filter, -1, -1,
+	"Set/get event filter\n"
+	"\tevent_filter syntax is: event_filter [value]"},
+	{ "pfn_roam_alert_thresh", wl_pfn_roam_alert_thresh, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set PFN and roam alert threshold\n"
+	"\tUsage: wl pfn_roam_alert_thresh [pfn_alert_thresh] [roam_alert_thresh]"
+	},
+	{ "pfn_override", wl_pfn_override, WLC_GET_VAR, WLC_SET_VAR,
+	"Temporary override for PNO scan parameters:\n"
+	"    pfn_override [<start> <duration> scanfrq <secs> [netimeout <secs>]\n"
+	"                 [adapt (off | smart | strict | slow)] [repeat cnt>]\n"
+	"                 [exp <cnt>] [slowfrq <secs>]]\n"
+	"    <start> is seconds until these parameters should be activated\n"
+	"    <duration> is seconds these parameters should remain in force\n"
+	"    Unspecified parameters use the values from pfnset."},
+	{ "pfn_macaddr", wl_pfn_macaddr, WLC_GET_VAR, WLC_SET_VAR,
+	"Private MAC address to use as source for PNO scans:\n"
+	"    pfn_macaddr [<mac>]"},
+#ifdef WL_MPF
+	{ "pfn_mpfset", wl_pfn_mpfset, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set mpf-based pfn parameters\n"
+	"    pfn_mpfset <groupid> [state <state> scanfrq <secs> [netimeout <secs>]\n"
+	"                         [adapt (off | smart | strict | slow)] [repeat <cnt>]\n"
+	"                         [exp <cnt>] [slowfrq <secs>] ] ...\n"
+	"    <groupid> is 0 (SSID list) or 1 (BSSID list)\n"
+	"    <state> is 0 thru 3\n"
+	"    unspecified states or subparameters us the values from pfnset."},
+	{ "mpf_map", wl_mpf_map, WLC_GET_VAR, WLC_SET_VAR,
+	"  mpf_map [type <type>] <mask> <val>/<state>[/<name>] ...\n"
+	"    <type> must be 0 if present no (effect)\n"
+	"    <mask> and <val> are 16-bit hex values, max 1s allowed: 3\n"
+	"    <state> is a small number, 0 thru N-1 (N is # of bit combos)\n"
+	"    <name> is an optional string name for the state"},
+	{ "mpf_state", wl_mpf_state, WLC_GET_VAR, WLC_SET_VAR,
+	"  mpf_state [type <type>] [<state> | <name> | gpio ]\n"
+	"  <mpf_state [type <type>] [<state> | <name> | gpio ]\n"
+	"    <type> must be 0 if present no (effect)\n"
+	"    <state> or <name>, if specified, override current value,\n"
+	"    setting gpio returns to simply tracking hardware state"},
+#endif /* WL_MPF */
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_pfn_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register pfn commands */
+	wl_module_cmds_register(wl_pfn_cmds);
+}
+
+static int
+wl_pfn_set(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_pfn_param_t pfn_param;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* Setup default values */
+	pfn_param.version = PFN_VERSION;
+	/* Sorting based on list order, no back ground scan, no autoswitch,
+	  * no immediate event report, no adaptvie scan, but immediate scan
+	  */
+	pfn_param.flags = (PFN_LIST_ORDER << SORT_CRITERIA_BIT | ENABLE << IMMEDIATE_SCAN_BIT);
+	/* Scan frequency of 30 sec */
+	pfn_param.scan_freq = 30;
+	/* slow adapt scan is off by default */
+	pfn_param.slow_freq = 0;
+	/* RSSI margin of 30 dBm */
+	pfn_param.rssi_margin = 30;
+	/* Network timeout 60 sec */
+	pfn_param.lost_network_timeout = 60;
+	/* best n = 2 by default */
+	pfn_param.bestn = DEFAULT_BESTN;
+	/* mscan m=0 by default, so not record best networks by default */
+	pfn_param.mscan = DEFAULT_MSCAN;
+	/*  default repeat = 10 */
+	pfn_param.repeat = DEFAULT_REPEAT;
+	/* by default, maximum scan interval = 2^2*scan_freq when adaptive scan is turned on */
+	pfn_param.exp = DEFAULT_EXP;
+
+	while (*++argv) {
+		if (!stricmp(*argv, "scanfrq")) {
+			if (*++argv)
+				pfn_param.scan_freq = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing scanfrq option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "netimeout")) {
+			if (*++argv)
+				pfn_param.lost_network_timeout = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing netimeout option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "rssi_delta")) {
+			if (*++argv)
+				pfn_param.rssi_margin = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing rssi_delta option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "sort")) {
+			if (*++argv) {
+				pfn_param.flags &= ~SORT_CRITERIA_MASK;
+				if (!stricmp(*argv, "listorder"))
+					pfn_param.flags |= (PFN_LIST_ORDER << SORT_CRITERIA_BIT);
+				else if (!stricmp(*argv, "rssi"))
+					pfn_param.flags |= (PFN_RSSI << SORT_CRITERIA_BIT);
+				else {
+					fprintf(stderr, "Invalid sort option %s\n", *argv);
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				fprintf(stderr, "Missing sort option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "immediateevent")) {
+			if (*++argv) {
+				if (!stricmp(*argv, "1")) {
+					pfn_param.flags |= IMMEDIATE_EVENT_MASK;
+				} else if (!stricmp(*argv, "0")) {
+					pfn_param.flags &= ~IMMEDIATE_EVENT_MASK;
+				} else {
+					fprintf(stderr, "Invalid immediateevent option\n");
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				fprintf(stderr, "Missing immediateevent option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "bkgscan")) {
+			if (*++argv) {
+				pfn_param.flags &= ~ENABLE_BKGRD_SCAN_MASK;
+				if (atoi(*argv))
+					pfn_param.flags |= (ENABLE << ENABLE_BKGRD_SCAN_BIT);
+				else
+					pfn_param.flags |= (DISABLE << ENABLE_BKGRD_SCAN_BIT);
+			} else {
+				fprintf(stderr, "Missing bkgscan option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "immediate")) {
+			pfn_param.flags &= ~IMMEDIATE_SCAN_MASK;
+			if (*++argv) {
+				if (atoi(*argv))
+					pfn_param.flags |= (ENABLE << IMMEDIATE_SCAN_BIT);
+				else
+					pfn_param.flags |= (DISABLE << IMMEDIATE_SCAN_BIT);
+			} else {
+				fprintf(stderr, "Missing immediate option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "bdscan")) {
+			if (*++argv) {
+				pfn_param.flags &= ~ENABLE_BD_SCAN_MASK;
+				if (atoi(*argv))
+					pfn_param.flags |= (ENABLE << ENABLE_BD_SCAN_BIT);
+				else
+					pfn_param.flags |= (DISABLE << ENABLE_BD_SCAN_BIT);
+			} else {
+				fprintf(stderr, "Missing bdscan option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "separate")) {
+			if (*++argv) {
+				pfn_param.flags &= ~REPORT_SEPERATELY_MASK;
+				if (atoi(*argv))
+					pfn_param.flags |= (ENABLE << REPORT_SEPERATELY_BIT);
+				else
+					pfn_param.flags |= (DISABLE << REPORT_SEPERATELY_BIT);
+			} else {
+				fprintf(stderr, "Missing seperate option\n");
+				return -1;
+			}
+		} else if (!stricmp(*argv, "adapt")) {
+			if (*++argv) {
+				pfn_param.flags &= ~ENABLE_ADAPTSCAN_MASK;
+				if (!stricmp(*argv, "off")) {
+					pfn_param.flags |= (OFF_ADAPT << ENABLE_ADAPTSCAN_BIT);
+				} else if (!stricmp(*argv, "smart")) {
+					pfn_param.flags |= (SMART_ADAPT << ENABLE_ADAPTSCAN_BIT);
+				} else if (!stricmp(*argv, "strict")) {
+					pfn_param.flags |= (STRICT_ADAPT << ENABLE_ADAPTSCAN_BIT);
+				} else if (!stricmp(*argv, "slow")) {
+					pfn_param.flags |= (SLOW_ADAPT << ENABLE_ADAPTSCAN_BIT);
+				} else {
+					fprintf(stderr, "Invalid adaptive scan option %s\n", *argv);
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				fprintf(stderr, "Missing adaptive scan option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "bestn")) {
+			pfn_param.bestn = atoi(*++argv);
+		} else if (!stricmp(*argv, "mscan")) {
+			pfn_param.mscan = atoi(*++argv);
+		} else if (!stricmp(*argv, "repeat")) {
+			pfn_param.repeat = atoi(*++argv);
+			if (pfn_param.repeat < 1 || pfn_param.repeat > 20) {
+				fprintf(stderr, "repeat %d out of range (1-20)\n",
+					pfn_param.repeat);
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "exp")) {
+			pfn_param.exp = atoi(*++argv);
+			if (pfn_param.exp < 1 || pfn_param.exp > 5) {
+				fprintf(stderr, "exp %d out of range (1-5)\n",
+					pfn_param.exp);
+				return BCME_BADARG;
+			}
+		} else if (!stricmp(*argv, "slowfrq")) {
+			if (*++argv)
+				pfn_param.slow_freq = atoi(*argv);
+			else {
+				fprintf(stderr, "Missing slowfrq option\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "bestn_bssid")) {
+			if (*++argv) {
+				pfn_param.flags &= ~BESTN_BSSID_ONLY_MASK;
+				if (atoi(*argv))
+					pfn_param.flags |= (ENABLE << BESTN_BSSID_ONLY_BIT);
+				else
+					pfn_param.flags |= (DISABLE << BESTN_BSSID_ONLY_BIT);
+			} else {
+				fprintf(stderr, "Missing bestn_bssid option\n");
+				return BCME_USAGE_ERROR;
+			}
+		}  else {
+			fprintf(stderr, "Invalid parameter %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	if ((((pfn_param.flags & ENABLE_ADAPTSCAN_MASK) ==
+	    (SLOW_ADAPT << ENABLE_ADAPTSCAN_BIT)) &&
+	    !pfn_param.slow_freq) ||
+	    (((pfn_param.flags & ENABLE_ADAPTSCAN_MASK) !=
+	    (SLOW_ADAPT << ENABLE_ADAPTSCAN_BIT)) &&
+	    pfn_param.slow_freq)) {
+		fprintf(stderr, "SLOW_ADAPT flag and slowfrq value not match\n");
+		return BCME_BADARG;
+	}
+	pfn_param.version = htod32(pfn_param.version);
+	pfn_param.scan_freq = htod32(pfn_param.scan_freq);
+	pfn_param.lost_network_timeout = htod32(pfn_param.lost_network_timeout);
+	pfn_param.flags = htod16(pfn_param.flags);
+	pfn_param.rssi_margin = htod16(pfn_param.rssi_margin);
+	pfn_param.slow_freq = htod32(pfn_param.slow_freq);
+
+	if ((err = wlu_iovar_set(wl, "pfn_set", &pfn_param, sizeof(wl_pfn_param_t))))
+		return (err);
+
+	return (0);
+}
+
+static bool
+validate_hex(char hexchar)
+{
+	if ((hexchar >= '0' && hexchar <= '9') ||
+		(hexchar >= 'a' || hexchar <= 'z') ||
+		(hexchar >= 'A' || hexchar <= 'Z'))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static uint8
+char2hex(char hexchar)
+{
+	if (hexchar >= '0' && hexchar <= '9')
+		return (hexchar - '0');
+	else if (hexchar >= 'a' && hexchar <= 'f')
+		return (hexchar - 'a' + 10);
+	else if (hexchar >= 'A' && hexchar <= 'F')
+		return (hexchar - 'A' + 10);
+	else
+	{
+		fprintf(stderr, "non-hex\n");
+		return 0xff;
+	}
+}
+
+#define MAXNUM_SSID_PER_ADD	16
+
+static int
+wl_pfn_add(void *wl, cmd_t *cmd, char **argv)
+{
+	int         err;
+	wl_pfn_t    *p_pfn_element = NULL;
+	int         i, pfn_element_len, cnt;
+	wl_pfn_t    *pssidnet = NULL;
+	uint32       val;
+
+	UNUSED_PARAMETER(cmd);
+
+	pfn_element_len = MAXNUM_SSID_PER_ADD * sizeof(wl_pfn_t);
+	p_pfn_element = (wl_pfn_t *)malloc(pfn_element_len);
+	if (p_pfn_element == NULL) {
+		fprintf(stderr, "Failed to allocate buffer for %d bytes\n", pfn_element_len);
+		return BCME_NOMEM;
+	}
+	memset(p_pfn_element, '\0', pfn_element_len);
+
+	pssidnet = p_pfn_element;
+	for (i = 0; i < MAXNUM_SSID_PER_ADD; i++) {
+		/* Default setting, open, no WPA, no WEP and bss */
+		pssidnet->auth = DOT11_OPEN_SYSTEM;
+		pssidnet->wpa_auth = WPA_AUTH_DISABLED;
+		pssidnet->wsec = 0;
+		pssidnet->infra = 1;
+		pssidnet->flags = 0;
+		pssidnet++;
+	}
+	cnt = -1;
+	pssidnet = p_pfn_element;
+	while (*++argv) {
+		if (!stricmp(*argv, "ssid")) {
+			if (*++argv) {
+				if (++cnt >= MAXNUM_SSID_PER_ADD) {
+					fprintf(stderr, "exceed max 16 SSID per pfn_add\n");
+					err = BCME_BADARG;
+					goto error;
+				}
+				if (cnt > 0) {
+					pssidnet->flags = htod32(pssidnet->flags);
+					pssidnet++;
+				}
+				strncpy((char *)pssidnet->ssid.SSID, *argv,
+				        sizeof(pssidnet->ssid.SSID));
+				pssidnet->ssid.SSID_len =
+				   strlen((char *)pssidnet->ssid.SSID);
+				if (pssidnet->ssid.SSID_len > 32) {
+					fprintf(stderr, "SSID too long: %s\n", *argv);
+					err = BCME_BADARG;
+					goto error;
+				}
+				pssidnet->ssid.SSID_len = htod32(pssidnet->ssid.SSID_len);
+			} else {
+				fprintf(stderr, "no value for ssid\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		}
+		else if (!stricmp(*argv, "hidden")) {
+			if (pssidnet->ssid.SSID_len == 0) {
+				fprintf(stderr, "Wrong! Start with SSID\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+			if (*++argv) {
+				val = **argv - '0';
+				if (val != ENABLE && val != DISABLE) {
+					fprintf(stderr, "invalid hidden setting, use 0/1\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				pssidnet->flags |= val << WL_PFN_HIDDEN_BIT;
+			} else {
+				fprintf(stderr, "no value for hidden\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		}  else if (!stricmp(*argv, "imode")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (!stricmp(*argv, "bss")) {
+					pssidnet->infra = 1;
+				} else if (!stricmp(*argv, "ibss")) {
+					pssidnet->infra = 0;
+				} else {
+					fprintf(stderr, "Invalid imode arg %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				pssidnet->infra = htod32(pssidnet->infra);
+			} else {
+				fprintf(stderr, "Missing option for imode\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "amode")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (!stricmp(*argv, "open"))
+					pssidnet->auth = DOT11_OPEN_SYSTEM;
+				else if (!stricmp(*argv, "shared"))
+					pssidnet->auth = DOT11_SHARED_KEY;
+				else {
+					fprintf(stderr, "Invalid imode arg %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				pssidnet->auth = htod32(pssidnet->auth);
+			} else {
+				fprintf(stderr, "Missing option for amode\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "wpa_auth")) {
+			if (*++argv) {
+				uint32 wpa_auth;
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+
+				/* figure requested auth, allow "any" */
+				if (!stricmp(*argv, "wpapsk"))
+					pssidnet->wpa_auth = WPA_AUTH_PSK;
+				else if (!stricmp(*argv, "wpa2psk"))
+					pssidnet->wpa_auth = WPA2_AUTH_PSK;
+				else if (!stricmp(*argv, "wpadisabled"))
+					pssidnet->wpa_auth = WPA_AUTH_DISABLED;
+				else if (!stricmp(*argv, "any"))
+					pssidnet->wpa_auth = (uint16)WPA_AUTH_PFN_ANY;
+				else if ((wpa_auth = strtoul(*argv, 0, 0)))
+					pssidnet->wpa_auth = wpa_auth;
+				else {
+					fprintf(stderr, "Invalid wpa_auth option %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				pssidnet->wpa_auth = htod32(pssidnet->wpa_auth);
+			} else {
+				fprintf(stderr, "Missing option for wpa_auth\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "wsec")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (!stricmp(*argv, "WEP")) {
+					pssidnet->wsec = WEP_ENABLED;
+				} else if (!stricmp(*argv, "TKIP"))
+					pssidnet->wsec = TKIP_ENABLED;
+				else if (!stricmp(*argv, "AES"))
+					pssidnet->wsec = AES_ENABLED;
+				else if (!stricmp(*argv, "TKIPAES"))
+					pssidnet->wsec = TKIP_ENABLED | AES_ENABLED;
+				else {
+					fprintf(stderr, "Invalid wsec option %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				pssidnet->wsec = htod32(pssidnet->wsec);
+			} else {
+				fprintf(stderr, "Missing option for wsec\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "suppress")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (!stricmp(*argv, "found")) {
+					pssidnet->flags |= WL_PFN_SUPPRESSFOUND_MASK;
+				} else if (!stricmp(*argv, "lost")) {
+					pssidnet->flags |= WL_PFN_SUPPRESSLOST_MASK;
+				} else if (!stricmp(*argv, "neither")) {
+					pssidnet->flags &=
+					 ~(WL_PFN_SUPPRESSLOST_MASK | WL_PFN_SUPPRESSFOUND_MASK);
+				} else {
+					fprintf(stderr, "Invalid suppress option %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for suppress\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "rssi")) {
+			if (*++argv) {
+				int rssi = atoi(*argv);
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (rssi >= -128 && rssi <= 0) {
+					pssidnet->flags |= (rssi << WL_PFN_RSSI_SHIFT)
+						& WL_PFN_RSSI_MASK;
+				} else {
+					fprintf(stderr, "Invalid rssi option %s\n", *argv);
+					err = BCME_BADARG;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for rssi\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "trig")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (!stricmp(*argv, "a")) {
+					pssidnet->flags |= WL_PFN_SSID_A_BAND_TRIG;
+				} else if (!stricmp(*argv, "bg")) {
+					pssidnet->flags |= WL_PFN_SSID_BG_BAND_TRIG;
+				} else if (!stricmp(*argv, "abg")) {
+					pssidnet->flags |=
+					  (WL_PFN_SSID_A_BAND_TRIG | WL_PFN_SSID_BG_BAND_TRIG);
+				} else {
+					fprintf(stderr, "Invalid trigger option %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for trigger\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "same_network")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				val = **argv - '0';
+				if (val != ENABLE && val != DISABLE) {
+					fprintf(stderr, "invalid same_network setting, use 0/1\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (val) {
+					pssidnet->flags |= WL_PFN_SSID_SAME_NETWORK;
+				}
+			} else {
+				fprintf(stderr, "Missing option for same_network\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "no_aging")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				val = **argv - '0';
+				if (val != ENABLE && val != DISABLE) {
+					fprintf(stderr, "invalid same_network setting, use 0/1\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (val) {
+					pssidnet->flags |= WL_PFN_SUPPRESS_AGING_MASK;
+				}
+			} else {
+				fprintf(stderr, "Missing option for same_network\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "imprecise")) {
+			if (*++argv) {
+				if (pssidnet->ssid.SSID_len == 0) {
+					fprintf(stderr, "Wrong! Start with SSID\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				val = **argv - '0';
+				if (val != ENABLE && val != DISABLE) {
+					fprintf(stderr, "invalid imprecise setting, use 0/1\n");
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+				if (val) {
+					pssidnet->flags |= WL_PFN_SSID_IMPRECISE_MATCH;
+				}
+			} else {
+				fprintf(stderr, "Missing option for imprecise match\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "clear")) {
+			if (*++argv) {
+				if (cnt >= 1) {
+					fprintf(stderr, "Will only clear, ssids ignored\n");
+				}
+				cnt = 0;
+				pssidnet = p_pfn_element;
+				pssidnet->flags = WL_PFN_FLUSH_ALL_SSIDS;
+			} else {
+				fprintf(stderr, "Missing option for clear\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		}	else {
+			fprintf(stderr, "Invalid parameter %s\n", *argv);
+			err = BCME_USAGE_ERROR;
+			goto error;
+		}
+	}
+	pssidnet->flags = htod32(pssidnet->flags);
+
+	pfn_element_len = (cnt + 1) * sizeof(wl_pfn_t);
+	if ((err = wlu_iovar_set(wl, "pfn_add", p_pfn_element,
+	     pfn_element_len))) {
+		fprintf(stderr, "pfn_add fail\n");
+		goto error;
+	}
+	free(p_pfn_element);
+	return (0);
+
+error:
+	free(p_pfn_element);
+	return err;
+}
+
+#define DEFAULT_INIT_SCORE_MAX  110
+#define DEFAULT_MIN_5G_RSSI      -45
+#define DEFAULT_MIN_2G_RSSI      -50
+
+static int
+wl_pfn_ssid_param(void *wl, cmd_t *cmd, char **argv)
+{
+	int i = 0, err = BCME_OK;
+	wl_pfn_ssid_cfg_t cfg;
+	char *endptr = NULL;
+	uint16 val;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* process a GET */
+	if (!*(argv + 1)) {
+		if (cmd->get < 0)
+			return -1;
+		memset(&cfg, 0, sizeof(cfg));
+		if ((err = wlu_iovar_get(wl, "pfn_ssid_cfg", (void *)&cfg,
+		   sizeof(wl_pfn_ssid_cfg_t))) < 0) {
+			fprintf(stderr, "Failed to get pfn_ssid_cfg %d\n", err);
+			return err;
+		}
+		if (cfg.version != WL_PFN_SSID_CFG_VERSION) {
+			fprintf(stderr, "Mismatched version expected %d, got %d\n",
+				WL_PFN_SSID_CFG_VERSION, cfg.version);
+			return err;
+		}
+		fprintf(stderr, "min2G_rssi %d min5G_rssi %d init_score_max %d\n",
+			cfg.params.min2G_rssi, cfg.params.min5G_rssi,
+			dtoh16(cfg.params.init_score_max));
+		fprintf(stderr, "band_5g_bonus %d secure_bonus %d same_ssid_bonus %d\n",
+			dtoh16(cfg.params.band_5g_bonus), dtoh16(cfg.params.secure_bonus),
+			dtoh16(cfg.params.same_ssid_bonus));
+		fprintf(stderr, "cur_bssid_bonus %d\n", dtoh16(cfg.params.cur_bssid_bonus));
+		return 0;
+	}
+
+	/* process a SET */
+	cfg.version = htod16(WL_PFN_SSID_CFG_VERSION);
+	cfg.flags = 0;
+	cfg.params.band_5g_bonus = 0;
+	cfg.params.secure_bonus = 0;
+	cfg.params.same_ssid_bonus = 0;
+	cfg.params.init_score_max = htod16(DEFAULT_INIT_SCORE_MAX);
+	cfg.params.cur_bssid_bonus = 0;
+	cfg.params.min2G_rssi = DEFAULT_MIN_2G_RSSI;
+	cfg.params.min5G_rssi = DEFAULT_MIN_5G_RSSI;
+	while (*++argv) {
+		if (!stricmp(*argv, "min5g_rssi")) {
+			if (*++argv) {
+				int rssi = strtol(*argv, &endptr, 0);
+				if (*endptr != '\0')
+					return BCME_USAGE_ERROR;
+				if (rssi >= -128 && rssi <= 0) {
+					cfg.params.min5G_rssi = rssi;
+				} else {
+					fprintf(stderr, "Invalid rssi option %s\n", *argv);
+					err = BCME_BADARG;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for rssi\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+
+		} else if (!stricmp(*argv, "min2g_rssi")) {
+			if (*++argv) {
+				int rssi = strtol(*argv, &endptr, 0);
+				if (*endptr != '\0')
+					return BCME_USAGE_ERROR;
+				if (rssi >= -128 && rssi <= 0) {
+					cfg.params.min2G_rssi = rssi;
+				} else {
+					fprintf(stderr, "Invalid rssi option %s\n", *argv);
+					err = BCME_BADARG;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for rssi\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "init_score_max")) {
+			if (*++argv) {
+				val = strtoul(*argv, &endptr, 0);
+				if (*endptr != '\0')
+					return BCME_USAGE_ERROR;
+				cfg.params.init_score_max = htod16(val);
+			} else {
+				fprintf(stderr, "Missing option for init_score_max\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "cur_bssid_bonus")) {
+			if (*++argv) {
+				val = strtoul(*argv, &endptr, 0);
+				if (*endptr != '\0')
+					return BCME_USAGE_ERROR;
+				cfg.params.cur_bssid_bonus = htod16(val);
+			} else {
+				fprintf(stderr, "Missing option for cur_bssid_bonus\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+
+		} else if (!stricmp(*argv, "same_ssid_bonus")) {
+			if (*++argv) {
+				val = strtoul(*argv, &endptr, 0);
+				if (*endptr != '\0')
+					return BCME_USAGE_ERROR;
+				cfg.params.same_ssid_bonus = htod16(val);
+			} else {
+				fprintf(stderr, "Missing option for same_ssid_bonus\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+
+		} else if (!stricmp(*argv, "secure_bonus")) {
+			if (*++argv) {
+				val = strtoul(*argv, &endptr, 0);
+				if (*endptr != '\0')
+					return BCME_USAGE_ERROR;
+				cfg.params.secure_bonus = htod16(val);
+			} else {
+				fprintf(stderr, "Missing option for secure_bonus\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "band_5g_bonus")) {
+			if (*++argv) {
+				val = strtoul(*argv, &endptr, 0);
+				if (*endptr != '\0')
+					return BCME_USAGE_ERROR;
+				cfg.params.band_5g_bonus = htod16(val);
+			} else {
+				fprintf(stderr, "Missing option for band_5g_bonus\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+
+		} else if (!stricmp(*argv, "clear")) {
+			cfg.flags = WL_PFN_SSID_CFG_CLEAR;
+			if (i) {
+				fprintf(stderr, "Params will ONLY be cleared\n");
+			}
+		}
+		i++;
+	}
+	if ((err = wlu_iovar_set(wl, "pfn_ssid_cfg", &cfg,
+	   sizeof(wl_pfn_ssid_cfg_t)))) {
+		fprintf(stderr, "Failed to set pfn_ssid_cfg %d\n", err);
+	}
+error:
+	return err;
+}
+
+#define MAXNUM_BSSID_PER_ADD	180
+
+static int
+wl_pfn_add_bssid(void *wl, cmd_t *cmd, char **argv)
+{
+	int                 err;
+	uint8               *ptr;
+	int                 i, bssidlistlen, cnt;
+	wl_pfn_bssid_t      *bssidlist;
+	wl_pfn_bssid_t      *pbssid = NULL;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*(argv + 1)) {
+		fprintf(stderr, "Invalid command\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	bssidlistlen = MAXNUM_BSSID_PER_ADD * sizeof(wl_pfn_bssid_t);
+	bssidlist = (wl_pfn_bssid_t *)malloc(bssidlistlen);
+	if (bssidlist == NULL) {
+		fprintf(stderr, "Failed to allocate buffer for %d bytes\n", bssidlistlen);
+		return BCME_NOMEM;
+	}
+	memset(bssidlist, '\0', bssidlistlen);
+
+	cnt = 0;
+	while (*++argv) {
+		if (!stricmp(*argv, "bssid")) {
+			if (*++argv) {
+				if (cnt >= MAXNUM_BSSID_PER_ADD) {
+					fprintf(stderr, "exceed max %d BSSID per pfn_add_bssid\n",
+						MAXNUM_BSSID_PER_ADD);
+					err = BCME_BADARG;
+					goto error;
+				}
+				if (!cnt)
+					pbssid = bssidlist;
+				else {
+					pbssid->flags = htod16(pbssid->flags);
+					pbssid++;
+				}
+
+				ptr = (uint8 *)*argv;
+				for (i = 0; i < ETHER_ADDR_LEN; i++)
+				{
+					if (!validate_hex(*ptr) || !validate_hex(*(ptr + 1)))
+					{
+						fprintf(stderr, "non-hex in BSSID\n");
+						err = BCME_BADARG;
+						goto error;
+					}
+					pbssid->macaddr.octet[i] =
+					      char2hex(*ptr) << 4 | char2hex(*(ptr+1));
+					ptr += 3;
+				}
+				cnt++;
+			} else {
+				fprintf(stderr, "Missing option for bssid\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "suppress")) {
+			if (!pbssid || ETHER_ISNULLADDR(pbssid->macaddr.octet)) {
+				fprintf(stderr, "Wrong! Start with BSSID\n");
+				err = BCME_BADARG;
+				goto error;
+			}
+			if (*++argv) {
+				if (!stricmp(*argv, "found")) {
+					pbssid->flags |= WL_PFN_SUPPRESSFOUND_MASK;
+				} else if (!stricmp(*argv, "lost")) {
+					pbssid->flags |= WL_PFN_SUPPRESSLOST_MASK;
+				} else if (!stricmp(*argv, "neither")) {
+					pbssid->flags &=
+					 ~(WL_PFN_SUPPRESSFOUND_MASK | WL_PFN_SUPPRESSLOST_MASK);
+				} else {
+					fprintf(stderr, "Invalid suppress option %s\n", *argv);
+					err = BCME_USAGE_ERROR;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for suppress\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else if (!stricmp(*argv, "rssi")) {
+			if (*++argv) {
+				int rssi = atoi(*argv);
+				if (!pbssid || ETHER_ISNULLADDR(pbssid->macaddr.octet)) {
+					fprintf(stderr, "Wrong! Start with BSSID\n");
+					err = BCME_BADARG;
+					goto error;
+				}
+				if (rssi >= -128 && rssi <= 0) {
+					pbssid->flags |= (rssi << WL_PFN_RSSI_SHIFT)
+						& WL_PFN_RSSI_MASK;
+				} else {
+					fprintf(stderr, "Invalid rssi option %s\n", *argv);
+					err = BCME_BADARG;
+					goto error;
+				}
+			} else {
+				fprintf(stderr, "Missing option for rssi\n");
+				err = BCME_USAGE_ERROR;
+				goto error;
+			}
+		} else {
+			fprintf(stderr, "Invalid parameter %s\n", *argv);
+			err = BCME_USAGE_ERROR;
+			goto error;
+		}
+	}
+	pbssid->flags = htod16(pbssid->flags);
+
+	bssidlistlen = cnt * sizeof(wl_pfn_bssid_t);
+	if ((err = wlu_iovar_setbuf(wl, "pfn_add_bssid", bssidlist,
+	                            bssidlistlen, buf, ETHER_MAX_LEN))) {
+		fprintf(stderr, "pfn_add_bssid fail\n");
+		goto error;
+	}
+	free(bssidlist);
+	return 0;
+
+error:
+	free(bssidlist);
+	return err;
+}
+
+static int
+wl_pfn_cfg(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pfn_cfg_t pfncfg_param;
+	int          nchan = 0;
+	int          err;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(&pfncfg_param, '\0', sizeof(wl_pfn_cfg_t));
+
+	/* Setup default values */
+	pfncfg_param.reporttype = WL_PFN_REPORT_ALLNET;
+	pfncfg_param.channel_num = 0;
+
+	while (*++argv) {
+		if (!stricmp(*argv, "report")) {
+			if (*++argv) {
+				if (!stricmp(*argv, "all")) {
+					pfncfg_param.reporttype = WL_PFN_REPORT_ALLNET;
+				} else if (!stricmp(*argv, "ssidonly")) {
+					pfncfg_param.reporttype = WL_PFN_REPORT_SSIDNET;
+				} else if (!stricmp(*argv, "bssidonly")) {
+					pfncfg_param.reporttype = WL_PFN_REPORT_BSSIDNET;
+				} else {
+					fprintf(stderr, "Invalid report option %s\n", *argv);
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				fprintf(stderr, "no value for report\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "channel")) {
+			if (*++argv) {
+				nchan = wl_parse_channel_list(*argv, pfncfg_param.channel_list,
+				                              WL_NUMCHANNELS);
+				if (nchan < 0) {
+					fprintf(stderr, "error parsing channel\n");
+					return BCME_BADARG;
+				}
+			} else {
+				fprintf(stderr, "Missing option for channel\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "prohibited")) {
+			if (*++argv) {
+				pfncfg_param.flags &= ~WL_PFN_CFG_FLAGS_PROHIBITED;
+				if (atoi(*argv))
+					pfncfg_param.flags |= WL_PFN_CFG_FLAGS_PROHIBITED;
+			} else {
+				fprintf(stderr, "Missing prohibited option value\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (!stricmp(*argv, "history_off")) {
+			if (*++argv) {
+				pfncfg_param.flags &= ~WL_PFN_CFG_FLAGS_HISTORY_OFF;
+				if (atoi(*argv))
+					pfncfg_param.flags |= WL_PFN_CFG_FLAGS_HISTORY_OFF;
+			} else {
+				fprintf(stderr, "Missing history_off option value\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else {
+			fprintf(stderr, "Invalid parameter %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	pfncfg_param.reporttype = htod32(pfncfg_param.reporttype);
+	pfncfg_param.channel_num = htod32(nchan);
+	pfncfg_param.flags = htod32(pfncfg_param.flags);
+
+	if ((err = wlu_iovar_set(wl, "pfn_cfg", &pfncfg_param,
+	     sizeof(wl_pfn_cfg_t)))) {
+		fprintf(stderr, "pfn_cfg fail\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int
+wl_pfn(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		val = atoi(*argv);
+		err = wlu_iovar_setint(wl, "pfn", (val ? 1 : 0));
+	} else {
+		err = wlu_iovar_getint(wl, "pfn", &val);
+		if (!err)
+			wl_printint(val);
+	}
+
+	return err;
+}
+
+/* Use MEDLEN for efficient read, pre-calculate maximum possible nets for later checks */
+#define WL_MAX_BESTNET_V1 ((WLC_IOCTL_MEDLEN - OFFSETOF(wl_pfn_scanresults_v1_t, netinfo)) \
+			   / sizeof(wl_pfn_net_info_v1_t))
+#define WL_MAX_BESTNET_V2 ((WLC_IOCTL_MEDLEN - OFFSETOF(wl_pfn_scanresults_v2_t, netinfo)) \
+			   / sizeof(wl_pfn_net_info_v2_t))
+
+static int
+wl_pfnbest(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err;
+	wl_pfn_scanresults_v1_t *bestnet_v1;
+	wl_pfn_net_info_v1_t *netinfo_v1;
+	wl_pfn_scanresults_v2_t *bestnet_v2;
+	wl_pfn_net_info_v2_t *netinfo_v2;
+	uint status;
+	uint32 i, j;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		fprintf(stderr, "Invalid parameter %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Use generic buffer to read and parse results */
+	bestnet_v1 = (wl_pfn_scanresults_v1_t *)buf;
+	bestnet_v2 = (wl_pfn_scanresults_v2_t *)buf;
+
+	/* Read results until completion indicated */
+	do {
+		bzero(buf, WLC_IOCTL_MEDLEN);
+
+		if ((err = wlu_iovar_get(wl, "pfnbest", (void*)buf, WLC_IOCTL_MEDLEN))) {
+			fprintf(stderr, "pfnbest fail\n");
+			return err;
+		}
+
+		if (bestnet_v2->version == PFN_SCANRESULTS_VERSION_V2) {
+			/* Use version 2 variables for processing */
+			status = bestnet_v2->status;
+			if (bestnet_v2->count > WL_MAX_BESTNET_V2) {
+				fprintf(stderr, "Invalid data, count %d exceeds max buflen\n",
+					bestnet_v2->count);
+				return BCME_ERROR;
+			}
+
+			printf("ver %d, status %d, count %d\n",
+				bestnet_v2->version, bestnet_v2->status, bestnet_v2->count);
+			netinfo_v2 = bestnet_v2->netinfo;
+			for (i = 0; i < bestnet_v2->count; i++) {
+				for (j = 0; j < netinfo_v2->pfnsubnet.SSID_len; j++)
+					printf("%c", netinfo_v2->pfnsubnet.u.SSID[j]);
+				printf("\n");
+				printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+						netinfo_v2->pfnsubnet.BSSID.octet[0],
+						netinfo_v2->pfnsubnet.BSSID.octet[1],
+						netinfo_v2->pfnsubnet.BSSID.octet[2],
+						netinfo_v2->pfnsubnet.BSSID.octet[3],
+						netinfo_v2->pfnsubnet.BSSID.octet[4],
+						netinfo_v2->pfnsubnet.BSSID.octet[5]);
+				printf("channel: %d, RSSI: %d, timestamp: %d\n",
+					netinfo_v2->pfnsubnet.channel, netinfo_v2->RSSI,
+					netinfo_v2->timestamp);
+				netinfo_v2++;
+			}
+		} else if (bestnet_v1->version == PFN_SCANRESULTS_VERSION_V1) {
+			/* Use version 1 variables for processing */
+			status = bestnet_v1->status;
+			if (bestnet_v1->count > WL_MAX_BESTNET_V1) {
+				fprintf(stderr, "Invalid data, count %d exceeds max buflen\n",
+				        bestnet_v1->count);
+				return BCME_ERROR;
+			}
+
+			printf("ver %d, status %d, count %d\n",
+			       bestnet_v1->version, bestnet_v1->status, bestnet_v1->count);
+			netinfo_v1 = bestnet_v1->netinfo;
+			for (i = 0; i < bestnet_v1->count; i++) {
+				for (j = 0; j < netinfo_v1->pfnsubnet.SSID_len; j++)
+					printf("%c", netinfo_v1->pfnsubnet.SSID[j]);
+				printf("\n");
+				printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+						netinfo_v1->pfnsubnet.BSSID.octet[0],
+						netinfo_v1->pfnsubnet.BSSID.octet[1],
+						netinfo_v1->pfnsubnet.BSSID.octet[2],
+						netinfo_v1->pfnsubnet.BSSID.octet[3],
+						netinfo_v1->pfnsubnet.BSSID.octet[4],
+						netinfo_v1->pfnsubnet.BSSID.octet[5]);
+				printf("channel: %d, RSSI: %d, timestamp: %d\n",
+					netinfo_v1->pfnsubnet.channel, netinfo_v1->RSSI,
+					netinfo_v1->timestamp);
+				netinfo_v1++;
+			}
+		} else {
+			fprintf(stderr, "Unrecognized version %d\n", bestnet_v1->version);
+			return BCME_ERROR;
+		}
+	} while (status != PFN_COMPLETE);
+
+	return 0;
+}
+
+/* Use MEDLEN for efficient read, pre-calculate maximum possible nets for later checks */
+#define WL_MAX_LBESTNET_V1 ((WLC_IOCTL_MEDLEN - OFFSETOF(wl_pfn_lscanresults_v1_t, netinfo)) \
+			    / sizeof(wl_pfn_net_info_v1_t))
+#define WL_MAX_LBESTNET_V2 ((WLC_IOCTL_MEDLEN - OFFSETOF(wl_pfn_lscanresults_v2_t, netinfo)) \
+			    / sizeof(wl_pfn_lnet_info_v2_t))
+
+static int
+wl_pfnlbest(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err;
+	wl_pfn_lscanresults_v1_t *bestnet_v1;
+	wl_pfn_lnet_info_v1_t *netinfo_v1;
+	wl_pfn_lscanresults_v2_t *bestnet_v2;
+	wl_pfn_lnet_info_v2_t *netinfo_v2;
+	uint status;
+	uint32 i, j;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		fprintf(stderr, "Invalid parameter %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Use generic buffer to read and parse results */
+	bestnet_v1 = (wl_pfn_lscanresults_v1_t *)buf;
+	bestnet_v2 = (wl_pfn_lscanresults_v2_t *)buf;
+
+	/* Read results until completion indicated */
+	do {
+		bzero(buf, WLC_IOCTL_MEDLEN);
+
+		if ((err = wlu_iovar_get(wl, "pfnlbest", (void *)buf, WLC_IOCTL_MEDLEN))) {
+			fprintf(stderr, "pfnlbest fail\n");
+			return err;
+		}
+
+		if (bestnet_v2->version == PFN_LBEST_SCAN_RESULT_VERSION_V2) {
+			/* Use version 2 variables for processing */
+			status = bestnet_v2->status;
+			if (bestnet_v2->count > WL_MAX_LBESTNET_V2) {
+				fprintf(stderr, "Invalid data, count %d exceeds max buflen\n",
+					bestnet_v2->count);
+				return BCME_ERROR;
+			}
+
+			printf("ver %d, status %d, count %d\n",
+				bestnet_v2->version, bestnet_v2->status, bestnet_v2->count);
+			netinfo_v2 = bestnet_v2->netinfo;
+			for (i = 0; i < bestnet_v2->count; i++) {
+				for (j = 0; j < netinfo_v2->pfnsubnet.SSID_len; j++)
+					printf("%c", netinfo_v2->pfnsubnet.u.SSID[j]);
+				printf("\n");
+				printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+						netinfo_v2->pfnsubnet.BSSID.octet[0],
+						netinfo_v2->pfnsubnet.BSSID.octet[1],
+						netinfo_v2->pfnsubnet.BSSID.octet[2],
+						netinfo_v2->pfnsubnet.BSSID.octet[3],
+						netinfo_v2->pfnsubnet.BSSID.octet[4],
+						netinfo_v2->pfnsubnet.BSSID.octet[5]);
+				printf("channel: %d, flags: %d, RSSI: %d, timestamp: %d\n",
+						netinfo_v2->pfnsubnet.channel, netinfo_v2->flags,
+						netinfo_v2->RSSI, netinfo_v2->timestamp);
+				printf("RTT0: %d, RTT1: %d\n", netinfo_v2->rtt0, netinfo_v2->rtt1);
+				netinfo_v2++;
+			}
+		} else if (bestnet_v1->version == PFN_LBEST_SCAN_RESULT_VERSION_V1) {
+			/* Use version 1 variables for processing */
+			status = bestnet_v1->status;
+			if (bestnet_v1->count > WL_MAX_LBESTNET_V1) {
+				fprintf(stderr, "Invalid data, count %d exceeds max buflen\n",
+				        bestnet_v1->count);
+				return BCME_ERROR;
+			}
+
+			printf("ver %d, status %d, count %d\n",
+			       bestnet_v1->version, bestnet_v1->status, bestnet_v1->count);
+			netinfo_v1 = bestnet_v1->netinfo;
+			for (i = 0; i < bestnet_v1->count; i++) {
+				for (j = 0; j < netinfo_v1->pfnsubnet.SSID_len; j++)
+					printf("%c", netinfo_v1->pfnsubnet.SSID[j]);
+				printf("\n");
+				printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+						netinfo_v1->pfnsubnet.BSSID.octet[0],
+						netinfo_v1->pfnsubnet.BSSID.octet[1],
+						netinfo_v1->pfnsubnet.BSSID.octet[2],
+						netinfo_v1->pfnsubnet.BSSID.octet[3],
+						netinfo_v1->pfnsubnet.BSSID.octet[4],
+						netinfo_v1->pfnsubnet.BSSID.octet[5]);
+				printf("channel: %d, flags: %d, RSSI: %d, timestamp: %d\n",
+						netinfo_v1->pfnsubnet.channel, netinfo_v1->flags,
+						netinfo_v1->RSSI, netinfo_v1->timestamp);
+				printf("RTT0: %d, RTT1: %d\n", netinfo_v1->rtt0, netinfo_v1->rtt1);
+				netinfo_v1++;
+			}
+		} else {
+			fprintf(stderr, "Unrecognized version %d\n", bestnet_v1->version);
+			return BCME_ERROR;
+		}
+	} while (status == PFN_INCOMPLETE);
+
+	return 0;
+}
+
+static int
+wl_pfnbest_bssid(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err;
+	wl_pfn_scanhist_bssid_t *bestnet;
+	wl_pfn_net_info_bssid_t *netinfo;
+	uint32 i;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		fprintf(stderr, "Invalid parameter %s\n", *argv);
+		return BCME_ERROR;
+	}
+
+	/* Use generic buffer to read and parse results */
+	bestnet = (wl_pfn_scanhist_bssid_t *)buf;
+
+	do {
+		memset(bestnet, 0, WLC_IOCTL_MEDLEN);
+
+		if ((err = wlu_iovar_get(wl, "pfnbest_bssid",
+		                         (void *)bestnet, WLC_IOCTL_MEDLEN))) {
+			fprintf(stderr, "pfnbest_bssid fail\n");
+			return err;
+		}
+
+		printf("ver %d, status %d, count %d\n",
+		       bestnet->version, bestnet->status, bestnet->count);
+		netinfo = bestnet->netinfo;
+		for (i = 0; i < bestnet->count; i++) {
+			printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
+			        netinfo->BSSID.octet[0],
+			        netinfo->BSSID.octet[1],
+			        netinfo->BSSID.octet[2],
+			        netinfo->BSSID.octet[3],
+			        netinfo->BSSID.octet[4],
+			        netinfo->BSSID.octet[5]);
+			printf("channel: %d, RSSI: %d, timestamp: %d\n",
+			       netinfo->channel, netinfo->RSSI, netinfo->timestamp);
+			netinfo++;
+		}
+	} while (bestnet->status != PFN_COMPLETE);
+
+	return 0;
+}
+
+static int
+wl_pfn_suspend(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err, val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		val = atoi(*argv);
+		err = wlu_iovar_setint(wl, "pfn_suspend", (val ? 1 : 0));
+	} else {
+		err = wlu_iovar_getint(wl, "pfn_suspend", &val);
+		if (!err)
+			wl_printint(val);
+	}
+
+	return err;
+}
+
+static int
+wl_pfn_mem(void *wl, cmd_t *cmd, char **argv)
+{
+	int	err, val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv && !stricmp(*argv, "bestn")) {
+		if (*++argv)
+			val = atoi(*argv);
+		else {
+			fprintf(stderr, "Missing bestn value\n");
+			return -1;
+		}
+	} else {
+		fprintf(stderr, "Missing bestn option\n");
+		return -1;
+	}
+
+	err = wlu_iovar_setint(wl, "pfnmem", val);
+	if (err) {
+		fprintf(stderr, "pfnmem set wrong!\n");
+		return err;
+	}
+
+	err = wlu_iovar_getint(wl, "pfnmem", &val);
+	if (!err)
+		wl_printint(val);
+	else
+		fprintf(stderr, "pfnmem get wrong!\n");
+	return err;
+}
+
+#if defined(linux)
+static void
+wl_pfn_printnet(void *ptr, int event_type)
+{
+	wl_pfn_net_info_v1_t *netinfo_v1;
+	wl_pfn_net_info_v2_t *netinfo_v2;
+	uint32 i, j;
+
+	if (WLC_E_PFN_NET_FOUND == event_type) {
+		printf("WLC_E_PFN_NET_FOUND:\n");
+	} else if (WLC_E_PFN_NET_LOST == event_type) {
+		printf("WLC_E_PFN_NET_LOST:\n");
+	} else if (WLC_E_PFN_BSSID_NET_FOUND == event_type) {
+		printf("WLC_E_PFN_BSSID_NET_FOUND:\n");
+	} else if (WLC_E_PFN_BSSID_NET_LOST == event_type) {
+		printf("WLC_E_PFN_BSSID_NET_LOST:\n");
+	} else {
+		return;
+	}
+
+	if (((wl_pfn_scanresults_v2_t *)ptr)->version == PFN_SCANRESULTS_VERSION_V2) {
+		netinfo_v2 = ((wl_pfn_scanresults_v2_t *)ptr)->netinfo;
+		printf("ver %d, status %d, count %d\n",
+			((wl_pfn_scanresults_v2_t *)ptr)->version,
+			((wl_pfn_scanresults_v2_t *)ptr)->status,
+			((wl_pfn_scanresults_v2_t *)ptr)->count);
+		for (i = 0; i < ((wl_pfn_scanresults_v2_t *)ptr)->count; i++) {
+			printf("%d. ", i + 1);
+			for (j = 0; j < netinfo_v2->pfnsubnet.SSID_len; j++)
+				printf("%c", netinfo_v2->pfnsubnet.u.SSID[j]);
+			printf("\n");
+			printf("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+					netinfo_v2->pfnsubnet.BSSID.octet[0],
+					netinfo_v2->pfnsubnet.BSSID.octet[1],
+					netinfo_v2->pfnsubnet.BSSID.octet[2],
+					netinfo_v2->pfnsubnet.BSSID.octet[3],
+					netinfo_v2->pfnsubnet.BSSID.octet[4],
+					netinfo_v2->pfnsubnet.BSSID.octet[5]);
+			printf("channel %d, RSSI %d, timestamp %d\n",
+			       netinfo_v2->pfnsubnet.channel, netinfo_v2->RSSI,
+			       netinfo_v2->timestamp);
+			netinfo_v2++;
+		}
+	} else  if (((wl_pfn_scanresults_v1_t *)ptr)->version == PFN_SCANRESULTS_VERSION_V1) {
+		netinfo_v1 = ((wl_pfn_scanresults_v1_t *)ptr)->netinfo;
+		printf("ver %d, status %d, count %d\n",
+			((wl_pfn_scanresults_v1_t *)ptr)->version,
+			((wl_pfn_scanresults_v1_t *)ptr)->status,
+			((wl_pfn_scanresults_v1_t *)ptr)->count);
+		for (i = 0; i < ((wl_pfn_scanresults_v1_t *)ptr)->count; i++) {
+			printf("%d. ", i + 1);
+			for (j = 0; j < netinfo_v1->pfnsubnet.SSID_len; j++)
+				printf("%c", netinfo_v1->pfnsubnet.SSID[j]);
+			printf("\n");
+			printf("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+					netinfo_v1->pfnsubnet.BSSID.octet[0],
+					netinfo_v1->pfnsubnet.BSSID.octet[1],
+					netinfo_v1->pfnsubnet.BSSID.octet[2],
+					netinfo_v1->pfnsubnet.BSSID.octet[3],
+					netinfo_v1->pfnsubnet.BSSID.octet[4],
+					netinfo_v1->pfnsubnet.BSSID.octet[5]);
+			printf("channel %d, RSSI %d, timestamp %d\n",
+			       netinfo_v1->pfnsubnet.channel, netinfo_v1->RSSI,
+			       netinfo_v1->timestamp);
+
+			netinfo_v1++;
+		}
+	}
+}
+
+static int
+wl_pfn_event_check(void *wl, cmd_t *cmd, char **argv)
+{
+	int                 fd, err;
+	struct sockaddr_ll	sll;
+	struct ifreq        ifr;
+	char                ifnames[IFNAMSIZ] = {"eth1"};
+	bcm_event_t         * event;
+	char                data[512];
+	int                 event_type;
+	struct ether_addr   *addr;
+	char                eabuf[ETHER_ADDR_STR_LEN];
+	wl_pfn_scanresults_v1_t *ptr_v1;
+	wl_pfn_net_info_v1_t   *info_v1;
+	wl_pfn_scanresults_v2_t *ptr_v2;
+	wl_pfn_net_info_v2_t	*info_v2;
+	uint32              i, j;
+	uint32              foundcnt, lostcnt;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	/* Override default ifname explicitly or implicitly */
+	if (*++argv) {
+		if (strlen(*argv) >= IFNAMSIZ) {
+			printf("Interface name %s too long\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		strncpy(ifnames, *argv, IFNAMSIZ);
+	} else {
+		strncpy(ifnames, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	}
+
+	ifnames[IFNAMSIZ - 1] = '\0';
+
+	memset(&ifr, 0, sizeof(ifr));
+	strncpy(ifr.ifr_name, ifnames, IFNAMSIZ);
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		return BCME_ERROR;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		close(fd);
+		return BCME_ERROR;
+	}
+
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		close(fd);
+		return BCME_ERROR;
+	}
+
+	/* Pre-set the results pointers for any data we might receive */
+	ptr_v1 = (wl_pfn_scanresults_v1_t *)(data + sizeof(bcm_event_t));
+	ptr_v2 = (wl_pfn_scanresults_v2_t *)(data + sizeof(bcm_event_t));
+
+	while (1) {
+		recv(fd, data, sizeof(data), 0);
+		event = (bcm_event_t *)data;
+		addr = (struct ether_addr *)&(event->event.addr);
+
+		event_type = ntoh32(event->event.event_type);
+
+		if (addr != NULL) {
+			sprintf(eabuf, "%02x:%02x:%02x:%02x:%02x:%02x",
+				(uchar)addr->octet[0]&0xff,
+				(uchar)addr->octet[1]&0xff,
+				(uchar)addr->octet[2]&0xff,
+				(uchar)addr->octet[3]&0xff,
+				(uchar)addr->octet[4]&0xff,
+				(uchar)addr->octet[5]&0xff);
+		}
+
+		if (ntoh32(event->event.datalen)) {
+			if (WLC_E_PFN_SCAN_COMPLETE == event_type) {
+				/* Version check for PFN */
+				if (ptr_v2->version == PFN_SCANRESULTS_VERSION_V2) {
+					info_v2 = ptr_v2->netinfo;
+					foundcnt = ptr_v2->count & 0xffff;
+					lostcnt = ptr_v2->count >> 16;
+					printf("ver %d, status %d, found %d, lost %d\n",
+						ptr_v2->version, ptr_v2->status,
+					       foundcnt, lostcnt);
+					if (foundcnt)
+						printf("Network found:\n");
+					for (i = 0; i < foundcnt; i++) {
+						printf("%d. ", i + 1);
+						for (j = 0; j < info_v2->pfnsubnet.SSID_len; j++)
+							printf("%c", info_v2->pfnsubnet.u.SSID[j]);
+						printf("\n");
+						printf("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+								info_v2->pfnsubnet.BSSID.octet[0],
+								info_v2->pfnsubnet.BSSID.octet[1],
+								info_v2->pfnsubnet.BSSID.octet[2],
+								info_v2->pfnsubnet.BSSID.octet[3],
+								info_v2->pfnsubnet.BSSID.octet[4],
+								info_v2->pfnsubnet.BSSID.octet[5]);
+						printf("channel %d, RSSI %d, timestamp %d\n",
+							info_v2->pfnsubnet.channel, info_v2->RSSI,
+							info_v2->timestamp);
+						info_v2++;
+					}
+					if (lostcnt)
+						printf("Network lost:\n");
+					for (i = 0; i < lostcnt; i++) {
+						printf("%d. ", i + 1);
+						for (j = 0; j < info_v2->pfnsubnet.SSID_len; j++)
+							printf("%c", info_v2->pfnsubnet.u.SSID[j]);
+						printf("\n");
+						printf("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+								info_v2->pfnsubnet.BSSID.octet[0],
+								info_v2->pfnsubnet.BSSID.octet[1],
+								info_v2->pfnsubnet.BSSID.octet[2],
+								info_v2->pfnsubnet.BSSID.octet[3],
+								info_v2->pfnsubnet.BSSID.octet[4],
+								info_v2->pfnsubnet.BSSID.octet[5]);
+						printf("channel %d, RSSI %d, timestamp %d\n",
+							info_v2->pfnsubnet.channel, info_v2->RSSI,
+							info_v2->timestamp);
+						info_v2++;
+					}
+				} else if (ptr_v1->version == PFN_SCANRESULTS_VERSION_V1) {
+					info_v1 = ptr_v1->netinfo;
+					foundcnt = ptr_v1->count & 0xffff;
+					lostcnt = ptr_v1->count >> 16;
+					printf("ver %d, status %d, found %d, lost %d\n",
+						ptr_v1->version, ptr_v1->status,
+					       foundcnt, lostcnt);
+					if (foundcnt)
+						printf("Network found:\n");
+					for (i = 0; i < foundcnt; i++) {
+						printf("%d. ", i + 1);
+						for (j = 0; j < info_v1->pfnsubnet.SSID_len; j++)
+							printf("%c", info_v1->pfnsubnet.SSID[j]);
+						printf("\n");
+						printf("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+								info_v1->pfnsubnet.BSSID.octet[0],
+								info_v1->pfnsubnet.BSSID.octet[1],
+								info_v1->pfnsubnet.BSSID.octet[2],
+								info_v1->pfnsubnet.BSSID.octet[3],
+								info_v1->pfnsubnet.BSSID.octet[4],
+								info_v1->pfnsubnet.BSSID.octet[5]);
+						printf("channel %d, RSSI %d, timestamp %d\n",
+							info_v1->pfnsubnet.channel, info_v1->RSSI,
+							info_v1->timestamp);
+						info_v1++;
+					}
+					if (lostcnt)
+						printf("Network lost:\n");
+					for (i = 0; i < lostcnt; i++) {
+						printf("%d. ", i + 1);
+						for (j = 0; j < info_v1->pfnsubnet.SSID_len; j++)
+							printf("%c", info_v1->pfnsubnet.SSID[j]);
+						printf("\n");
+						printf("BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
+								info_v1->pfnsubnet.BSSID.octet[0],
+								info_v1->pfnsubnet.BSSID.octet[1],
+								info_v1->pfnsubnet.BSSID.octet[2],
+								info_v1->pfnsubnet.BSSID.octet[3],
+								info_v1->pfnsubnet.BSSID.octet[4],
+								info_v1->pfnsubnet.BSSID.octet[5]);
+						printf("channel %d, RSSI %d, timestamp %d\n",
+							info_v1->pfnsubnet.channel, info_v1->RSSI,
+							info_v1->timestamp);
+						info_v1++;
+					}
+				} else {
+					fprintf(stderr, "Unrecognized version %d\n",
+					        ptr_v1->version);
+					return BCME_ERROR;
+				}
+			} else if ((WLC_E_PFN_NET_FOUND == event_type) ||
+			           (WLC_E_PFN_NET_LOST == event_type) ||
+			           (WLC_E_PFN_BSSID_NET_FOUND == event_type) ||
+			           (WLC_E_PFN_BSSID_NET_LOST == event_type)) {
+				wl_pfn_printnet((void *)(data + sizeof(bcm_event_t)), event_type);
+			}
+
+			if (WLC_E_LINK == event_type || WLC_E_NDIS_LINK == event_type) {
+				if (ntoh16(event->event.flags) & WLC_EVENT_MSG_LINK)
+					printf("MACEVENT Link up :%s\n", eabuf);
+				else
+					printf("MACEVENT Link down :%s\n", eabuf);
+			}
+		} else {
+			if (WLC_E_PFN_SCAN_NONE == event_type) {
+				printf("Got WLC_E_PFN_SCAN_NONE\n");
+			}
+			if (WLC_E_PFN_SCAN_ALLGONE == event_type) {
+				printf("Got WLC_E_PFN_SCAN_ALLGONE\n");
+			}
+			if (WLC_E_PFN_BEST_BATCHING == event_type) {
+				printf("Got WLC_E_PFN_BEST_BATCHING\n");
+			}
+		}
+	}
+
+	close(fd);
+	return (0);
+}
+#endif /* linux */
+
+static int
+wl_event_filter(void *wl, cmd_t *cmd, char **argv)
+{
+	int     err;
+	uint8   event_inds_mask[WL_EVENTING_MASK_LEN];  /* event bit mask */
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	memset(event_inds_mask, '\0', WL_EVENTING_MASK_LEN);
+
+	/* Register for following event for pfn */
+	event_inds_mask[WLC_E_LINK / 8] |= 1 << (WLC_E_LINK % 8);
+	event_inds_mask[WLC_E_PFN_NET_FOUND / 8] |= 1 << (WLC_E_PFN_NET_FOUND % 8);
+	event_inds_mask[WLC_E_PFN_NET_LOST / 8] |= 1 << (WLC_E_PFN_NET_LOST % 8);
+	event_inds_mask[WLC_E_PFN_SCAN_NONE/ 8] |= 1 << (WLC_E_PFN_SCAN_NONE % 8);
+	event_inds_mask[WLC_E_PFN_SCAN_ALLGONE/ 8] |= 1 << (WLC_E_PFN_SCAN_ALLGONE % 8);
+
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		return (err);
+
+	return (0);
+}
+
+static int
+wl_pfn_roam_alert_thresh(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_pfn_roam_thresh_t *pfn_roam_alert;
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	if (*++(argv) == NULL) {
+		buf[buflen] = '\0';
+		err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+		if (err < 0)
+			return err;
+
+		pfn_roam_alert = (wl_pfn_roam_thresh_t *)buf;
+		printf("pfn_alert_thresh %u\n", pfn_roam_alert->pfn_alert_thresh);
+		printf("roam_alert_thresh %u\n", pfn_roam_alert->roam_alert_thresh);
+		return 0;
+
+	} else {
+		pfn_roam_alert = (wl_pfn_roam_thresh_t *) (buf + buflen);
+		buflen += sizeof(wl_pfn_roam_thresh_t);
+
+		pfn_roam_alert->pfn_alert_thresh = (uint32) strtoul(*argv, NULL, 0);
+
+		if (*++(argv) == NULL) {
+			printf("Incorrect number of arguments\n");
+			return BCME_ERROR;
+		}
+		pfn_roam_alert->roam_alert_thresh = (uint32) strtoul(*argv, NULL, 0);
+
+		if (*++(argv)) {
+			printf("extra arguments\n");
+			return BCME_ERROR;
+		}
+		err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+		return err;
+	}
+	return 0;
+}
+
+static char *adaptname[] = { "off", "smart", "strict", "slow" };
+
+static int
+wl_pfn_override(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_pfn_override_param_t pfnov_params;
+	wl_pfn_override_param_t *pfnov_paramp;
+	wl_pfn_mpf_state_params_t *statep;
+	char *endptr;
+
+	uint16 start, duration;
+
+	/* Initialize the structure (both set and get) */
+	memset(&pfnov_params, 0, sizeof(pfnov_params));
+	pfnov_params.version = dtoh16(WL_PFN_OVERRIDE_VERSION);
+
+	if (*++argv == NULL) {
+		/* No arguments: do a GET and display results */
+		err = wlu_iovar_getbuf(wl, cmd->name,
+		                       &pfnov_params, sizeof(pfnov_params),
+		                       buf, WLC_IOCTL_MAXLEN);
+		if (err >= 0) {
+			pfnov_paramp = (wl_pfn_override_param_t *)buf;
+			if (dtoh16(pfnov_paramp->version) != WL_PFN_OVERRIDE_VERSION) {
+				fprintf(stderr, "Incorrect version (%d != %d).\n",
+				        dtoh16(pfnov_paramp->version), WL_PFN_OVERRIDE_VERSION);
+				return -1;
+			}
+			start = dtoh16(pfnov_paramp->start_offset);
+			duration = dtoh16(pfnov_paramp->duration);
+
+			if (duration) {
+				if (start == 0)
+					printf("Active, remaining duration %d\n", duration);
+				else
+					printf("Scheduled in %d, duration %d\n", start, duration);
+
+				/* Disaply the actual parameters */
+				statep = &pfnov_paramp->override;
+				statep->scan_freq = dtoh32(statep->scan_freq);
+				statep->lost_network_timeout =
+				        dtoh32(statep->lost_network_timeout);
+				statep->flags = dtoh16(statep->flags);
+				statep->slow_freq = dtoh32(statep->slow_freq);
+
+				printf("Scan frequency: %d\n", statep->scan_freq);
+				if (statep->lost_network_timeout)
+					printf("Net timeout: %d\n",
+					       dtoh32(statep->lost_network_timeout));
+				if (statep->flags & WL_PFN_MPF_ADAPT_ON_MASK) {
+					uint atype;
+					atype = statep->flags & WL_PFN_MPF_ADAPTSCAN_MASK;
+					atype = atype >> WL_PFN_MPF_ADAPTSCAN_BIT;
+					printf("Adapt: %s\n", adaptname[atype]);
+				}
+				if (statep->exp)
+					printf("  Exp: %d\n", statep->exp);
+				if (statep->repeat)
+					printf("  Repeat: %d\n", statep->repeat);
+				if (statep->slow_freq)
+					printf("  Slow: %d\n", statep->slow_freq);
+			} else {
+				printf("Override not configured\n");
+			}
+		}
+	} else {
+		/* Additional arguments: parse and do a set */
+
+		/* Start field (required) */
+		start = strtoul(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "Non-numeric start value %s\n", *argv);
+			return -1;
+		}
+
+		/* Duration field (required) */
+		if (*++argv == NULL) {
+			fprintf(stderr, "Duration required\n");
+			return -1;
+		}
+		duration = strtoul(*argv, &endptr, 0);
+		argv++;
+
+		/* Allow duration and start both 0 to mean cancel, otherwise
+		 * zero duration is meaningless.  A nonzero duration requires
+		 * a scan frequency at a minimum
+		 */
+		if (!duration) {
+			if (start) {
+				fprintf(stderr, "Start with no duration invalid\n");
+				return -1;
+			}
+		} else {
+			/* Read the actual timing parameters */
+			statep = &pfnov_params.override;
+			if ((*argv == NULL) || strcmp(*argv, "scanfrq")) {
+				fprintf(stderr, "scanfrq required as first parameter\n");
+				return -1;
+			}
+
+			if (argv[1] == NULL) {
+				fprintf(stderr, "Missing value for '%s'\n", *argv);
+				return -1;
+			}
+			argv++;
+			statep->scan_freq = strtoul(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				fprintf(stderr, "Non-numeric scanfrq %s\n", *argv);
+				return -1;
+			}
+			argv++;
+
+			/* As long as there was a scan_freq, pick up other options */
+			while (*argv && statep->scan_freq) {
+				if (*argv && !strcmp(*argv, "netimeout")) {
+					if (argv[1] == NULL) {
+						fprintf(stderr,
+						        "Missing value for '%s'\n", *argv);
+						return -1;
+					}
+					argv++;
+					statep->lost_network_timeout = strtoul(*argv, &endptr, 0);
+					if (*endptr != '\0') {
+						fprintf(stderr,
+						        "Non-numeric netimeout %s\n", *argv);
+						return -1;
+					}
+					argv++;
+				} else if (*argv && !strcmp(*argv, "adapt")) {
+					if (argv[1] == NULL) {
+						fprintf(stderr,
+						        "Missing value for '%s'\n", *argv);
+						return -1;
+					}
+					argv++;
+					if (!strcmp(*argv, "off")) {
+						statep->flags |=
+						        (OFF_ADAPT << WL_PFN_MPF_ADAPTSCAN_BIT);
+					} else if (!strcmp(*argv, "smart")) {
+						statep->flags |=
+						        (SMART_ADAPT << WL_PFN_MPF_ADAPTSCAN_BIT);
+					} else if (!strcmp(*argv, "strict")) {
+						statep->flags |=
+						        (STRICT_ADAPT << WL_PFN_MPF_ADAPTSCAN_BIT);
+					} else if (!strcmp(*argv, "slow")) {
+						statep->flags |=
+						        (SLOW_ADAPT << WL_PFN_MPF_ADAPTSCAN_BIT);
+					} else {
+						fprintf(stderr,
+						        "Invalid adaptive scan option %s\n",
+						        *argv);
+						return -1;
+					}
+					statep->flags |= WL_PFN_MPF_ADAPT_ON_MASK;
+					argv++;
+				} else if (*argv && !strcmp(*argv, "repeat")) {
+					if (argv[1] == NULL) {
+						fprintf(stderr,
+						        "Missing value for '%s'\n", *argv);
+						return -1;
+					}
+					argv++;
+					statep->repeat = strtoul(*argv, &endptr, 0);
+					if (*endptr != '\0') {
+						fprintf(stderr,
+						        "Non-numeric repeat value %s\n", *argv);
+						return -1;
+					}
+					argv++;
+				} else if (*argv && !strcmp(*argv, "exp")) {
+					if (argv[1] == NULL) {
+						fprintf(stderr,
+						        "Missing value for '%s'\n", *argv);
+						return -1;
+					}
+					argv++;
+					statep->exp = strtoul(*argv, &endptr, 0);
+					if (*endptr != '\0') {
+						fprintf(stderr,
+						        "Non-numeric exp value %s\n", *argv);
+						return -1;
+					}
+					argv++;
+				} else if (*argv && !strcmp(*argv, "slowfrq")) {
+					if (argv[1] == NULL) {
+						fprintf(stderr,
+						        "Missing value for '%s'\n", *argv);
+						return -1;
+					}
+					argv++;
+					statep->slow_freq = strtoul(*argv, &endptr, 0);
+					if (*endptr != '\0') {
+						fprintf(stderr,
+						        "Non-numeric slowfrq value %s\n", *argv);
+						return -1;
+					}
+					argv++;
+				} else {
+					/* Not a recognized option, exit loop */
+					break;
+				}
+			}
+
+			statep->scan_freq = htod32(statep->scan_freq);
+			statep->lost_network_timeout = htod32(statep->lost_network_timeout);
+			statep->flags = htod16(statep->flags);
+			statep->slow_freq = htod32(statep->slow_freq);
+		}
+
+		/* Should be no leftover args at this point */
+		if (*argv) {
+			fprintf(stderr, "Input error at %s\n", *argv);
+			return -1;
+		}
+
+		/* Fill in the start and duration fields */
+		pfnov_params.start_offset = htod16(start);
+		pfnov_params.duration = htod16(duration);
+
+		/* Now do the set */
+		err = wlu_iovar_setbuf(wl, cmd->name,
+		                       &pfnov_params, sizeof(pfnov_params), buf, WLC_IOCTL_MAXLEN);
+	}
+
+	return err;
+}
+
+static int
+wl_pfn_macaddr(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_OK;
+	wl_pfn_macaddr_cfg_t pfn_mac;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(&pfn_mac, 0, sizeof(pfn_mac));
+	pfn_mac.version = WL_PFN_MACADDR_CFG_VER;
+
+	if (argv[1] != NULL) {
+		if (!wl_ether_atoe(argv[1], &pfn_mac.macaddr)) {
+			fprintf(stderr, "Invalid MAC address %s\n", *argv);
+			return -1;
+		}
+
+		return wlu_iovar_set(wl, "pfn_macaddr", &pfn_mac, sizeof(pfn_mac));
+	} else {
+		if ((ret = wlu_iovar_get(wl, "pfn_macaddr", &pfn_mac, sizeof(pfn_mac))) < 0)
+			return ret;
+
+		printf("%s\n", wl_ether_etoa(&pfn_mac.macaddr));
+	}
+
+	return ret;
+}
+
+#ifdef WL_MPF
+static int
+wl_pfn_mpfset(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_pfn_mpf_param_t mpf_params;
+	wl_pfn_mpf_param_t *mpf_paramp;
+	wl_pfn_mpf_state_params_t *statep;
+	char *endptr;
+	uint state;
+
+	if (*++argv == NULL) {
+		fprintf(stderr, "Requires at least <groupid>\n");
+		return -1;
+	}
+
+	/* Initialize the structure (both set and get) */
+	memset(&mpf_params, 0, sizeof(mpf_params));
+	mpf_params.version = dtoh16(WL_PFN_MPF_VERSION);
+	mpf_params.groupid = dtoh16(strtoul(*argv, &endptr, 0));
+	if (*endptr != '\0') {
+		fprintf(stderr, "Non-numeric groupid %s\n", *argv);
+		return -1;
+	}
+
+	if (*++argv == NULL) {
+		/* No arguments beyond groupid: do a GET and display results */
+		err = wlu_iovar_getbuf(wl, cmd->name,
+		                       &mpf_params, OFFSETOF(wl_pfn_mpf_param_t, state),
+		                       buf, WLC_IOCTL_MAXLEN);
+		if (err >= 0) {
+			mpf_paramp = (wl_pfn_mpf_param_t *)buf;
+			if (dtoh16(mpf_paramp->version) != WL_PFN_MPF_VERSION) {
+				fprintf(stderr, "Incorrect version (%d != %d).\n",
+				        dtoh16(mpf_paramp->version), WL_PFN_MPF_VERSION);
+				return -1;
+			}
+			if (mpf_paramp->groupid != mpf_params.groupid) {
+				fprintf(stderr, "Groupid modified (%d -> %d)?\n",
+				        dtoh16(mpf_params.groupid), dtoh16(mpf_paramp->groupid));
+				return -1;
+			}
+
+			for (state = 0, statep = mpf_paramp->state;
+			     state < WL_PFN_MPF_STATES_MAX; state++, statep++) {
+				if (!statep->scan_freq)
+					continue;
+
+				statep->scan_freq = dtoh32(statep->scan_freq);
+				statep->lost_network_timeout =
+				        dtoh32(statep->lost_network_timeout);
+				statep->flags = dtoh16(statep->flags);
+				statep->slow_freq = dtoh32(statep->slow_freq);
+
+				printf("State %d:\n"
+				       "  Scan frequency: %d\n",
+				       state, statep->scan_freq);
+				if (statep->lost_network_timeout)
+					printf("  Net timeout: %d\n",
+					       dtoh32(statep->lost_network_timeout));
+				if (statep->flags & WL_PFN_MPF_ADAPT_ON_MASK) {
+					uint atype;
+					atype = statep->flags & WL_PFN_MPF_ADAPTSCAN_MASK;
+					atype = atype >> WL_PFN_MPF_ADAPTSCAN_BIT;
+					printf("  Adapt: %s\n", adaptname[atype]);
+				}
+				if (statep->exp)
+					printf("  Exp: %d\n", statep->exp);
+				if (statep->repeat)
+					printf("  Repeat: %d\n", statep->repeat);
+				if (statep->slow_freq)
+					printf("  Slow: %d\n", statep->slow_freq);
+			}
+		}
+	} else {
+		/* Additional arguments: parse and do a set */
+		while (*argv && !strcmp(*argv, "state")) {
+			if (argv[1] == NULL) {
+				fprintf(stderr, "Missing value for '%s'\n", *argv);
+				return -1;
+			}
+			argv++;
+			state = strtoul(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				fprintf(stderr, "Non-numeric state %s\n", *argv);
+				return -1;
+			}
+			if (state >= WL_PFN_MPF_STATES_MAX) {
+				fprintf(stderr, "Invalid state %d\n", state);
+				return -1;
+			}
+			argv++;
+
+			/* Set up for this state and get the scan frequency */
+			statep = &mpf_params.state[state];
+			if (statep->scan_freq) {
+				fprintf(stderr, "Repeated state (%d)\n", state);
+				return -1;
+			}
+
+			if (*argv && !strcmp(*argv, "scanfrq")) {
+				if (argv[1] == NULL) {
+					fprintf(stderr, "Missing value for '%s'\n", *argv);
+					return -1;
+				}
+				argv++;
+				statep->scan_freq = strtoul(*argv, &endptr, 0);
+				if (*endptr != '\0') {
+					fprintf(stderr, "Non-numeric scanfrq %s\n", *argv);
+					return -1;
+				}
+			} else {
+				fprintf(stderr, "State requires scanfrq\n");
+				return -1;
+			}
+			argv++;
+
+			/* If scan_freq is 0, don't allow other options */
+			if (!statep->scan_freq)
+				continue;
+
+			/* Pick up any other options */
+			while (*argv) {
+				if (*argv && !strcmp(*argv, "netimeout")) {
+					if (argv[1] == NULL) {
+						fprintf(stderr,
+						        "Missing value for '%s'\n", *argv);
+						return -1;
+					}
+					argv++;
+					statep->lost_network_timeout = strtoul(*argv, &endptr, 0);
+					if (*endptr != '\0') {
+						fprintf(stderr,
+						        "Non-numeric netimeout %s\n", *argv);
+						return -1;
+					}
+					argv++;
+				} else if (*argv && !strcmp(*argv, "adapt")) {
+					if (argv[1] == NULL) {
+						fprintf(stderr,
+						        "Missing value for '%s'\n", *argv);
+						return -1;
+					}
+					argv++;
+					if (!strcmp(*argv, "off")) {
+						statep->flags |=
+						        (OFF_ADAPT << WL_PFN_MPF_ADAPTSCAN_BIT);
+					} else if (!strcmp(*argv, "smart")) {
+						statep->flags |=
+						        (SMART_ADAPT << WL_PFN_MPF_ADAPTSCAN_BIT);
+					} else if (!strcmp(*argv, "strict")) {
+						statep->flags |=
+						        (STRICT_ADAPT << WL_PFN_MPF_ADAPTSCAN_BIT);
+					} else if (!strcmp(*argv, "slow")) {
+						statep->flags |=
+						        (SLOW_ADAPT << WL_PFN_MPF_ADAPTSCAN_BIT);
+					} else {
+						fprintf(stderr,
+						        "Invalid adaptive scan option %s\n",
+						        *argv);
+						return -1;
+					}
+					statep->flags |= WL_PFN_MPF_ADAPT_ON_MASK;
+					argv++;
+				} else if (*argv && !strcmp(*argv, "repeat")) {
+					if (argv[1] == NULL) {
+						fprintf(stderr,
+						        "Missing value for '%s'\n", *argv);
+						return -1;
+					}
+					argv++;
+					statep->repeat = strtoul(*argv, &endptr, 0);
+					if (*endptr != '\0') {
+						fprintf(stderr,
+						        "Non-numeric repeat value %s\n", *argv);
+						return -1;
+					}
+					argv++;
+				} else if (*argv && !strcmp(*argv, "exp")) {
+					if (argv[1] == NULL) {
+						fprintf(stderr,
+						        "Missing value for '%s'\n", *argv);
+						return -1;
+					}
+					argv++;
+					statep->exp = strtoul(*argv, &endptr, 0);
+					if (*endptr != '\0') {
+						fprintf(stderr,
+						        "Non-numeric exp value %s\n", *argv);
+						return -1;
+					}
+					argv++;
+				} else if (*argv && !strcmp(*argv, "slowfrq")) {
+					if (argv[1] == NULL) {
+						fprintf(stderr,
+						        "Missing value for '%s'\n", *argv);
+						return -1;
+					}
+					argv++;
+					statep->slow_freq = strtoul(*argv, &endptr, 0);
+					if (*endptr != '\0') {
+						fprintf(stderr,
+						        "Non-numeric slowfrq value %s\n", *argv);
+						return -1;
+					}
+					argv++;
+				} else {
+					/* Not a recognized option, exit inner loop */
+					break;
+				}
+			}
+
+			statep->scan_freq = htod32(statep->scan_freq);
+			statep->lost_network_timeout = htod32(statep->lost_network_timeout);
+			statep->flags = htod16(statep->flags);
+			statep->slow_freq = htod32(statep->slow_freq);
+		}
+
+		/* Should be no leftover args at this point */
+		if (*argv) {
+			fprintf(stderr, "Input error at %s\n", *argv);
+			return -1;
+		}
+
+		/* Now do the set */
+		err = wlu_iovar_setbuf(wl, cmd->name,
+		                       &mpf_params, sizeof(mpf_params), buf, WLC_IOCTL_MAXLEN);
+	}
+
+	return err;
+}
+
+static int
+wl_mpf_map(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_mpf_map_t map;
+	wl_mpf_map_t *mapp;
+	wl_mpf_val_t *valp, *valp2;
+	uint16 mask, val, state, type = 0;
+	uint8 count;
+	char *endptr;
+	uint bitcount;
+
+	argv++;
+
+	memset(&map, 0, sizeof(map));
+	map.version = dtoh16(WL_MPF_VERSION);
+
+	if (*argv && !strcmp(*argv, "type")) {
+		argv++;
+		if (*argv == NULL) {
+			fprintf(stderr, "No type value specified\n");
+			return -1;
+		}
+		type = strtoul(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "Non-numeric type value %s\n", *argv);
+			return -1;
+		}
+		if (type != 0) {
+			fprintf(stderr, "Nonzero type not yet implemented\n");
+			return -1;
+		}
+		/* If/when nonzero allowed, swap/assign it here */
+		argv++;
+	}
+
+	if (*argv == NULL) {
+		/* No arguments beyond type, do a GET and display results */
+		err = wlu_iovar_getbuf(wl, cmd->name,
+		                       &map, OFFSETOF(wl_mpf_map_t, mask), buf, WLC_IOCTL_MAXLEN);
+		if (err >= 0) {
+			mapp = (wl_mpf_map_t *)buf;
+			if (dtoh16(mapp->version) != WL_MPF_VERSION) {
+				fprintf(stderr, "Incorrect version (%d != %d).\n",
+				        dtoh16(mapp->version), WL_MPF_VERSION);
+				return -1;
+			}
+			printf("Type %d, mask %04x, %d state mappings:\n",
+			       dtoh16(mapp->type), dtoh16(mapp->mask), mapp->count);
+			bitcount = bcm_bitcount((uint8*)&mapp->mask, sizeof(mapp->mask));
+			if (bitcount > WL_MPF_MAX_BITS) {
+				fprintf(stderr, "Invalid mask: more than %d bits\n",
+				        WL_MPF_MAX_BITS);
+				return -1;
+			}
+
+			count = dtoh16(mapp->count);
+			if (!count && !bitcount) {
+				printf("No map configured\n");
+			} else {
+				if (count != (1 << bitcount)) {
+					fprintf(stderr, "Bit/count mismatch (%d != %d)\n",
+					        bitcount, count);
+					return -1;
+				}
+			}
+
+			for (valp = mapp->vals; count; count--, valp++) {
+				if (valp->name[WL_MPF_STATE_NAME_MAX-1]) {
+					char c = valp->name[WL_MPF_STATE_NAME_MAX-1];
+					valp->name[WL_MPF_STATE_NAME_MAX-1] = 0;
+					fprintf(stderr, "Invalid name: %s%c\n",
+					        valp->name, c);
+					return -1;
+				}
+
+				printf(" Value: %04x  State: %d  (%s)\n",
+				       dtoh16(valp->val), dtoh16(valp->state), valp->name);
+			}
+		}
+	} else {
+		/* Additional arguments: parse and do a set */
+		mask = strtoul(*argv, &endptr, 16);
+		if (*endptr != '\0') {
+			fprintf(stderr, "Cannot parse mask %s\n", *argv);
+			return -1;
+		}
+		bitcount = bcm_bitcount((uint8*)&mask, sizeof(mask));
+		if (bitcount > WL_MPF_MAX_BITS) {
+			fprintf(stderr, "Invalid mask: more than %d bits\n",
+			        WL_MPF_MAX_BITS);
+			return -1;
+		}
+		map.mask = htod16(mask);
+		argv++;
+
+		count = 1 << bitcount;
+		map.count = count;
+
+		for (valp = map.vals; count && *argv; count--, argv++, valp++) {
+			val = strtoul(*argv, &endptr, 16);
+			if (endptr == *argv || *endptr != '/') {
+				fprintf(stderr, "Invalid value, or missing /state: %s\n", *argv);
+				return -1;
+			}
+			if (val & ~mask) {
+				fprintf(stderr, "Value bits outside mask: %04x/%04x -> %04x\n",
+				        val, mask, val & ~mask);
+				return -1;
+			}
+			val = htod16(val);
+			for (valp2 = map.vals; valp2 < valp; valp2++) {
+				if (val == valp2->val) {
+					fprintf(stderr, "Invalid repeated value: %04x\n",
+					        dtoh16(val));
+					return -1;
+				}
+			}
+			valp->val = val;
+
+			endptr++;
+			if (*endptr == '\0' || *endptr == '/') {
+				fprintf(stderr, "Missing required /<state>: %s\n", *argv);
+				return -1;
+			}
+			state = strtoul(endptr, &endptr, 0);
+			if (*endptr != '\0' && *endptr != '/') {
+				fprintf(stderr, "Non-numeric state value %s\n", endptr);
+				return -1;
+			}
+			if (state >= map.count) {
+				fprintf(stderr, "Invalid state %d, must be 0-%d\n",
+				        state, map.count - 1);
+				return -1;
+			}
+			valp->state = htod16(state);
+
+			if (*endptr++ == '/') {
+				if (strlen(endptr) >= WL_MPF_STATE_NAME_MAX - 1) {
+					fprintf(stderr, "Name %s too long, limit %d chars\n",
+					        endptr, WL_MPF_STATE_NAME_MAX - 2);
+					return -1;
+				}
+				if (isdigit(*endptr)) {
+					fprintf(stderr, "Names cannot start with a digit: %s\n",
+					        endptr);
+					return -1;
+				}
+				if (!strcmp(endptr, "gpio")) {
+					fprintf(stderr, "Name 'gpio' is reserved\n");
+					return -1;
+				}
+				strcpy(valp->name, endptr);
+			}
+		}
+
+		/* Closing overall checks */
+		if (count) {
+			fprintf(stderr, "Specify all %d possible values, missing %d\n",
+			        map.count, count);
+			return -1;
+		} else if (*argv) {
+			fprintf(stderr, "Too many arguments for %d possible states at %s\n",
+			        map.count, *argv);
+			return -1;
+		}
+
+		/* All ok, do the set */
+		err = wlu_iovar_setbuf(wl, cmd->name,
+		                       &map, sizeof(map), buf, WLC_IOCTL_MAXLEN);
+	}
+
+	return err;
+}
+
+static int
+wl_mpf_state(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_mpf_state_t mpstate;
+	wl_mpf_state_t *mpstatep;
+	uint16 state, type = 0;
+	char *endptr;
+
+	argv++;
+
+	memset(&mpstate, 0, sizeof(mpstate));
+	mpstate.version = dtoh16(WL_MPF_VERSION);
+
+	if (*argv && !strcmp(*argv, "type")) {
+		argv++;
+		if (*argv == NULL) {
+			fprintf(stderr, "No type value specified\n");
+			return -1;
+		}
+		type = strtoul(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			fprintf(stderr, "Non-numeric type value %s\n", *argv);
+			return -1;
+		}
+		if (type != 0) {
+			fprintf(stderr, "Nonzero type not yet implemented\n");
+			return -1;
+		}
+		/* If/when nonzero allowed, swap/assign it here */
+		argv++;
+	}
+
+	if (*argv == NULL) {
+		/* No arguments beyond type, do a GET and display results */
+		err = wlu_iovar_getbuf(wl, cmd->name,
+		                       &mpstate, OFFSETOF(wl_mpf_state_t, state),
+		                       buf, WLC_IOCTL_MAXLEN);
+		if (err >= 0) {
+			mpstatep = (wl_mpf_state_t *)buf;
+			if (dtoh16(mpstatep->version) != WL_MPF_VERSION) {
+				fprintf(stderr, "Incorrect version (%d != %d).\n",
+				        dtoh16(mpstatep->version), WL_MPF_VERSION);
+				return -1;
+			}
+			if (mpstatep->name[WL_MPF_STATE_NAME_MAX-1]) {
+				fprintf(stderr, "Invalid name\n");
+				mpstatep->name[WL_MPF_STATE_NAME_MAX-1] = '\0';
+			}
+			printf("Type %d: state %d, name %s (%s)\n",
+			       dtoh16(mpstatep->type), dtoh16(mpstatep->state),
+			       (mpstatep->name ? mpstatep->name : "(unknown)"),
+			       ((mpstatep->force) ? "forced" : "auto"));
+		}
+	} else {
+		/* Should be one argument, but need to determine what kind */
+		if (isdigit(**argv)) {
+			state = strtoul(*argv, &endptr, 0);
+			if (*endptr != '\0') {
+				fprintf(stderr, "Non-numeric state: %s\n", *argv);
+				return -1;
+			}
+			mpstate.state = htod16(state);
+			mpstate.force = 1;
+		} else if (!strcmp(*argv, "gpio")) {
+			mpstate.force = 0;
+		} else {
+			if (strlen(*argv) >= WL_MPF_STATE_NAME_MAX-1) {
+				fprintf(stderr, "Name %s too long, limit %d chars\n",
+				        *argv, WL_MPF_STATE_NAME_MAX - 2);
+				return -1;
+			}
+			strcpy(mpstate.name, *argv);
+			mpstate.force = 1;
+		}
+		argv++;
+
+		if (*argv) {
+			fprintf(stderr, "Too many arguments at %s\n", *argv);
+			return -1;
+		}
+
+		/* All ok, do the set */
+		err = wlu_iovar_setbuf(wl, cmd->name,
+		                       &mpstate, sizeof(mpstate), buf, WLC_IOCTL_MAXLEN);
+	}
+
+	return err;
+}
+#endif /* WL_MPF */
diff --git a/wl/src/wl/exe/wluc_phy.c b/wl/src/wl/exe/wluc_phy.c
new file mode 100644
index 0000000..1fc4841
--- /dev/null
+++ b/wl/src/wl/exe/wluc_phy.c
@@ -0,0 +1,5494 @@
+/*
+ * wl phy command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_phy.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <bcmsrom_fmt.h>
+#include <bcmsrom_tbl.h>
+#include <bcmdevs.h>
+#include "wlu_common.h"
+#include "wlu.h"
+#include <miniopt.h>
+
+/* For backwards compatibility, the absense of the define 'NO_FILESYSTEM_SUPPORT'
+ * implies that a filesystem is supported.
+ */
+#if !defined(BWL_NO_FILESYSTEM_SUPPORT)
+#define BWL_FILESYSTEM_SUPPORT
+#endif
+
+static cmd_func_t wl_pkteng, wl_pkteng_stats, wl_phy_txpwrindex, wl_pkteng_status;
+static cmd_func_t wl_sample_collect;
+static cmd_func_t wl_phy_force_crsmin;
+static cmd_func_t wl_phy_rssi_ant;
+static cmd_func_t wl_phy_snr_ant;
+static cmd_func_t wl_tssi, wl_atten, wl_evm;
+static cmd_func_t wl_interfere, wl_interfere_override;
+static cmd_func_t wl_get_instant_power;
+static cmd_func_t wl_phymsglevel;
+#if defined(BCMDBG)
+static cmd_func_t wl_phy_debug_cmd;
+#endif
+static cmd_func_t wl_rifs;
+static cmd_func_t wl_rifs_advert;
+static cmd_func_t wl_test_tssi, wl_test_tssi_offs, wl_phy_rssiant, wl_rxiq;
+static cmd_func_t wl_rxiq_sweep;
+static cmd_func_t wl_test_idletssi;
+static cmd_func_t wlu_afeoverride;
+static cmd_func_t wl_phy_papdepstbl;
+static cmd_func_t wl_phy_txiqcc, wl_phy_txlocc;
+static cmd_func_t wl_rssi_cal_freq_grp_2g;
+static cmd_func_t wl_phy_rssi_gain_delta_2g, wl_phy_rssi_gain_delta_5g;
+static cmd_func_t wl_phy_rssi_gain_delta_2g_sub;
+static cmd_func_t wl_phy_rxgainerr_2g, wl_phy_rxgainerr_5g;
+static cmd_func_t wl_phytable, wl_phy_pavars, wl_phy_povars;
+static cmd_func_t wl_phy_fem, wl_phy_maxpower;
+static cmd_func_t wl_phy_rpcalvars;
+static cmd_func_t wl_phy_rpcalphasevars;
+static cmd_func_t wl_phy_force_vsdb_chans;
+static cmd_func_t wl_radar_args, wl_radar_thrs, wl_radar_thrs2;
+static cmd_func_t wl_phy_dyn_switch_th;
+static cmd_func_t wl_btcoex_desense_rxgain;
+
+static cmd_func_t wl_phy_tpc_av, wl_phy_tpc_vmid;
+
+
+/* txcal iovars */
+static cmd_func_t wl_txcal_gainsweep;
+static cmd_func_t wl_txcal_gainsweep_meas;
+static cmd_func_t wl_txcal_pwr_tssi_tbl;
+static cmd_func_t wl_olpc_anchoridx;
+static cmd_func_t wl_read_estpwrlut;
+static cmd_func_t wl_olpc_offset;
+
+typedef struct {
+	uint value;
+	const char *string;
+} phy_msg_t;
+
+static cmd_t wl_phy_cmds[] = {
+	{ "restart", wl_void, -1, WLC_RESTART,
+	"Restart driver.  Driver must already be down."},
+	{ "phymsglevel", wl_phymsglevel, WLC_GET_VAR, WLC_SET_VAR,
+	"set phy debugging message bitvector\n"
+	"\ttype \'wl phymsglevel ?\' for values" },
+	{ "tssi", wl_tssi, WLC_GET_TSSI, -1,
+	"Get the tssi value from radio" },
+	{ "txpathpwr", wl_int, WLC_GET_TX_PATH_PWR, WLC_SET_TX_PATH_PWR,
+	"Turn the tx path power on or off on 2050 radios" },
+	{ "powerindex", wl_int, WLC_GET_PWRIDX, WLC_SET_PWRIDX,
+	"Set the transmit power for A band(0-63).\n"
+	"\t-1 - default value" },
+	{ "atten", wl_atten, WLC_GET_ATTEN, WLC_SET_ATTEN,
+	"Set the transmit attenuation for B band. Args: bb radio txctl1.\n"
+	"\tauto to revert to automatic control\n"
+	"\tmanual to supspend automatic control" },
+	{ "phyreg", wl_reg, WLC_GET_PHYREG, WLC_SET_PHYREG,
+	"Get/Set a phy register:\n"
+	"\toffset [ value ] [ band ]" },
+	{ "radioreg", wl_reg, WLC_GET_RADIOREG, WLC_SET_RADIOREG,
+	"Get/Set a radio register:\n"
+	"\toffset [ value ] [ band/core ]\n"
+	"HTPHY:\n"
+	"\tGet a radio register: wl radioreg [ offset ] [ cr0/cr1/cr2 ]\n"
+	"\tSet a radio register: wl radioreg [ offset ] [ value ] [ cr0/cr1/cr2/all ]\n"
+	"ACPHY:\n"
+	"\tGet a radio register: wl radioreg [ offset ] [ cr0/cr1/cr2/pll/pll0/pll1 ]\n"
+	"\tSet a radio register: wl radioreg [ offset ] [ value ]"
+	" [ cr0/cr1/cr2/pll/pll0/pll1/all ]"},
+	{ "phy_afeoverride", wlu_afeoverride, WLC_GET_VAR, WLC_SET_VAR, "g/set AFE override"},
+	{ "pcieserdesreg", wlu_reg3args, WLC_GET_VAR, WLC_SET_VAR,
+	"g/set SERDES registers: dev offset [val]"},
+	{ "txinstpwr", wl_get_instant_power, WLC_GET_VAR, -1,
+	"Return tx power based on instant TSSI "},
+	{ "evm", wl_evm, -1, WLC_EVM,
+	"Start an EVM test on the given channel, or stop EVM test.\n"
+	"\tArg 1 is channel number 1-14, or \"off\" or 0 to stop the test.\n"
+	"\tArg 2 is optional rate (1, 2, 5.5 or 11)"},
+	{ "noise", wl_int, WLC_GET_PHY_NOISE, -1,
+	"Get noise (moving average) right after tx in dBm" },
+	{ "fqacurcy", wl_int, -1, WLC_FREQ_ACCURACY,
+	"Manufacturing test: set frequency accuracy mode.\n"
+	"\tfreqacuracy syntax is: fqacurcy <channel>\n"
+	"\tArg is channel number 1-14, or 0 to stop the test." },
+	{ "crsuprs", wl_int, -1, WLC_CARRIER_SUPPRESS,
+	"Manufacturing test: set carrier suppression mode.\n"
+	"\tcarriersuprs syntax is: crsuprs <channel>\n"
+	"\tArg is channel number 1-14, or 0 to stop the test." },
+	{ "longtrain", wl_int, -1, WLC_LONGTRAIN,
+	"Manufacturing test: set longtraining mode.\n"
+	"\tlongtrain syntax is: longtrain <channel>\n"
+	"\tArg is A band channel number or 0 to stop the test." },
+	{ "interference", wl_interfere, WLC_GET_INTERFERENCE_MODE, WLC_SET_INTERFERENCE_MODE,
+	"NON-ACPHY. Get/Set interference mitigation mode. Choices are:\n"
+	"\t0 = none\n"
+	"\t1 = non wlan\n"
+	"\t2 = wlan manual\n"
+	"\t3 = wlan automatic\n"
+	"\t4 = wlan automatic with noise reduction"
+	"\n\n\tACPHY. Get/Set interference mitigation mode. Bit-Mask:\n"
+	"\t0 = desense based on glitches\n"
+	"\t1 = limit pktgain based on hwaci (high pwr aci)\n"
+	"\t2 = limit pktgain based on w2/nb (high pwr aci)\n"
+	"\t3 = enable preemption\n"
+	"\t4 = enable HWACI based mitigation\n"
+	"\t5 = enable low power detect preemption (requires bit 3 - preemption - to be set too)\n"
+	"\tSo a value of 63 would enable all six\n"},
+	{ "interference_override", wl_interfere_override,
+	WLC_GET_INTERFERENCE_OVERRIDE_MODE,
+	WLC_SET_INTERFERENCE_OVERRIDE_MODE,
+	"NON-ACPHY. Get/Set interference mitigation override. Choices are:\n"
+	"\t0 = no interference mitigation\n"
+	"\t1 = non wlan\n"
+	"\t2 = wlan manual\n"
+	"\t3 = wlan automatic\n"
+	"\t4 = wlan automatic with noise reduction\n"
+	"\t-1 = remove override, override disabled"
+	"\n\n\tACPHY. Get/Set interference mitigation mode. Bit-Mask:\n"
+	"\t-1 = remove override, override disabled\n"
+	"\t0 = desense based on glitches\n"
+	"\t1 = limit pktgain based on hwaci (high pwr aci)\n"
+	"\t2 = limit pktgain based on w2/nb (high pwr aci)\n"
+	"\t3 = enable preemption\n"
+	"\t4 = enable HWACI based mitigation\n"
+	"\t5 = enable low power detect preemption (requires bit 3 - preemption - to be set too)\n"
+	"\tSo a value of 63 would enable all six\n"},
+	{ "phy_txpwrindex", wl_phy_txpwrindex, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: (set) phy_txpwrindex core0_idx core1_idx core2_idx core3_idx"
+	"       (get) phy_txpwrindex, return format: core0_idx core1_idx core2_idx core3_idx"
+	"Set/Get txpwrindex"
+	},
+	{ "rssi_cal_freq_grp_2g", wl_rssi_cal_freq_grp_2g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: wl_rssi_cal_freq_grp_2g [chan_1_2,chan_3_4,...,chan_13_14]\n"
+	"Each of the variables like - chan_1_2 is a byte"
+	"Upper nibble of this byte is for chan1 and lower for chan2"
+	"MSB of the nibble tells if the channel is used for calibration"
+	"3 LSB's tell which group the channel falls in"
+	"Set/get rssi calibration frequency grouping"
+	},
+	{ "phy_rssi_gain_delta_2gb0", wl_phy_rssi_gain_delta_2g_sub, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2gb0 [val0 val1 ....]\n"
+	"Number of arguments can be - "
+	"\t 8 for single core (4345 and 4350)"
+	"\t 9 by specifying core_num followed by 8 arguments (4345 and 4350)"
+	"\t 16 for both cores (4350)"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_2gb1", wl_phy_rssi_gain_delta_2g_sub, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2gb1 [val0 val1 ....]\n"
+	"Number of arguments can be - "
+	"\t 8 for single core (4345 and 4350)"
+	"\t 9 by specifying core_num followed by 8 arguments (4345 and 4350)"
+	"\t 16 for both cores (4350)"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_2gb2", wl_phy_rssi_gain_delta_2g_sub, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2gb2 [val0 val1 ....]\n"
+	"Number of arguments can be - "
+	"\t 8 for single core (4345 and 4350)"
+	"\t 9 by specifying core_num followed by 8 arguments (4345 and 4350)"
+	"\t 16 for both cores (4350)"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_2gb3", wl_phy_rssi_gain_delta_2g_sub, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2gb3 [val0 val1 ....]\n"
+	"Number of arguments can be - "
+	"\t 8 for single core (4345 and 4350)"
+	"\t 9 by specifying core_num followed by 8 arguments (4345 and 4350)"
+	"\t 16 for both cores (4350)"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_2gb4", wl_phy_rssi_gain_delta_2g_sub, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2gb4 [val0 val1 ....]\n"
+	"Number of arguments can be - "
+	"\t 8 for single core (4345 and 4350)"
+	"\t 9 by specifying core_num followed by 8 arguments (4345 and 4350)"
+	"\t 16 for both cores (4350)"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_2g", wl_phy_rssi_gain_delta_2g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_2g [val0 val1 ....]\n"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_5gl", wl_phy_rssi_gain_delta_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_5gl [val0 val1 ....]\n"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_5gml", wl_phy_rssi_gain_delta_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_5gml [val0 val1 ....]\n"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_5gmu", wl_phy_rssi_gain_delta_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_5gmu [val0 val1 ....]\n"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rssi_gain_delta_5gh", wl_phy_rssi_gain_delta_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rssi_gain_delta_5gh [val0 val1 ....]\n"
+	"Set/get rssi gain delta values"
+	},
+	{ "phy_rxgainerr_2g", wl_phy_rxgainerr_2g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rxgainerr_2g [val0 val1 ....]\n"
+	"Set/get rx gain delta values"
+	},
+	{ "phy_rxgainerr_5gl", wl_phy_rxgainerr_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rxgainerr_5gl [val0 val1 ....]\n"
+	"Set/get rx gain delta values"
+	},
+	{ "phy_rxgainerr_5gm", wl_phy_rxgainerr_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rxgainerr_5gml [val0 val1 ....]\n"
+	"Set/get rx gain delta values"
+	},
+	{ "phy_rxgainerr_5gh", wl_phy_rxgainerr_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rxgainerr_5gmu [val0 val1 ....]\n"
+	"Set/get rx gain delta values"
+	},
+	{ "phy_rxgainerr_5gu", wl_phy_rxgainerr_5g, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_rxgainerr_5gh [val0 val1 ....]\n"
+	"Set/get rx gain delta values"
+	},
+	{ "phy_test_tssi", wl_test_tssi, WLC_GET_VAR, -1,
+	"wl phy_test_tssi val"},
+	{ "phy_test_tssi_offs", wl_test_tssi_offs, WLC_GET_VAR, -1,
+	"wl phy_test_tssi_offs val"},
+	{ "phy_rssiant", wl_phy_rssiant, WLC_GET_VAR, -1,
+	"wl phy_rssiant antindex(0-3)"},
+	{ "phy_rssi_ant", wl_phy_rssi_ant, WLC_GET_VAR, WLC_SET_VAR,
+	"Get RSSI per antenna (only gives RSSI of current antenna for SISO PHY)"},
+	{ "phy_test_idletssi", wl_test_idletssi, WLC_GET_VAR, -1,
+	"get idletssi for the given core; wl phy_test_idletssi corenum"},
+	{ "phy_setrptbl", wl_var_void, -1, WLC_SET_VAR,
+	"populate the reciprocity compensation table based on SROM cal content\n\n"
+	"\tusage: wl phy_setrptbl"},
+	{ "phy_forceimpbf", wl_var_void, -1, WLC_SET_VAR,
+	"force the beamformer into implicit TXBF mode and ready to construct steering matrix\n\n"
+	"\tusage: wl phy_forceimpbf"},
+	{ "phy_forcesteer", wl_var_setint, -1, WLC_SET_VAR,
+	"force the beamformer to apply steering matrix when TXBF is turned on\n\n"
+	"\tusage: wl phy_forcesteer 1/0"},
+#if defined(BCMDBG)
+	{ "phy_force_gainlevel", wl_phy_debug_cmd, WLC_GET_VAR, WLC_SET_VAR,
+	"Force rxgain level \n"
+	"\t 0 : force to init gain\n"
+	"\t 1 : force to clip hi gain\n"
+	"\t 2 : force to clip md gain\n"
+	"\t 3 : force to clip lo gain\n"
+	"\t 4 : force to adc clip gain\n"
+	"\t 5 : force to nb clip gain\n"
+	"\t 6 : force to wb clip gain\n"
+	"\t -1 : disable\n"
+	"\t usage: wl phy_force_gainlevel <int32 var>"
+	},
+#endif
+#if defined(BCMDBG)
+	{ "phy_force_fdiqi", wl_phy_debug_cmd, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/disable FDIQI Cal/Comp \n"
+	"\t 0 : disable\n"
+	"\t 1 : enable\n"
+	"\t usage: wl phy_force_fdiqi <int32 var>"
+	},
+#endif
+#if defined(BCMDBG)
+	{ "phy_btcoex_desense", wl_phy_debug_cmd, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/disable btcoex desense\n"
+	"\t 0 : disable\n"
+	"\t 1 : mode 1\n"
+	"\t usage: wl phy_btcoex_desense <int32 var>"
+	},
+#endif
+	{ "phy_btcoex_desense_rxgain", wl_btcoex_desense_rxgain, WLC_GET_VAR, WLC_SET_VAR,
+	"Set the phy btcoex desence rxgain values \n"
+	"\t usage: wl phy_btcoex_desense_rxgain band num_cores value1 value2 ..\n"
+	"Get the phy btcoex desence rxgain values \n"
+	"\t usage: wl phy_btcoex_desense_rxgain ..\n"
+	},
+	{ "lcnphy_papdepstbl", wl_phy_papdepstbl, -1, WLC_GET_VAR,
+	"print papd eps table; Usage: wl lcnphy_papdepstbl"
+	},
+	{ "rifs", wl_rifs, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the rifs status; usage: wl rifs <1/0> (On/Off)"
+	},
+	{ "rifs_advert", wl_rifs_advert, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get the rifs mode advertisement status; usage: wl rifs_advert <-1/0> (Auto/Off)"
+	},
+	{ "phy_rxiqest", wl_rxiq, WLC_GET_VAR, -1,
+	"Get phy RX IQ noise in dBm:\n"
+	"\t-s # of samples (2^n)\n"
+	"\t-a antenna select, 0,1,2 or 3\n"
+	  "\t-r resolution select, 0 (coarse) or 1 (fine)\n"
+	  "\t-f lpf hpc override select, 0 (hpc unchanged) or 1 (overridden to ltrn mode)\n"
+	  "\t-w dig lpf override select, 0 (lpf unchanged) or 1 (overridden to ltrn_lpf mode)"
+	  "\t or 2 (bypass)\n"
+	  "\t-g gain-correction select, 0 (disable), 1(enable full correction) \n"
+	  "\t	2 (enable temperature correction) or 3(verify rssi_gain_delta)\n"
+	  "\t-e extra INITgain in dB on top of default. Valid values = {0, 3, 6, .., 21, 24}\n"
+	  "\t-i gain mode select, 0 (default gain), 1 (fixed high gain) or 4 (fixed low gain)."
+	  "\t-n number of averaging iterations.\n"
+	  "\t-d delay in usecs between iterations - default 10usecs.\n"
+	},
+	{ "phy_rxiqest_sweep", wl_rxiq_sweep, WLC_GET_VAR, -1,
+	"Get phy RX IQ noise in dBm for requested channels:\n"
+	"\t-c\n"
+	"\t\tall - All channels"
+	"\t\tcomma separated list of channels (e.g. 1,2,4,136)"
+	"\t-s # of samples (2^n)\n"
+	"\t-a antenna select, 0,1 or 3\n"
+	"\t-r resolution select, 0 (coarse) or 1 (fine)\n"
+	"\t-f lpf hpc override select, 0 (hpc unchanged) or 1 (overridden to ltrn mode)\n"
+	"\t-w dig lpf override select, 0 (lpf unchanged) or 1 (overridden to ltrn_lpf mode)"
+	"\t or 2 (bypass)\n"
+	"\t-g gain-correction select, 0 (disable), 1(enable full correction) \n"
+	"\t     2 (enable temperature correction) or 3(verify rssi_gain_delta)\n"
+	"\t-e extra INITgain in dB on top of default. Valid values = {0, 3, 6, .., 21, 24}\n"
+	"\t-i gain mode select, 0 (default gain), 1 (fixed high gain) or 4 (fixed low gain). \n"
+	"\t-n number of averaging iterations. Max 5 iterations for a sweep of 10 channels or more\n"
+	"\t-d delay in usecs between iterations - default 10usecs.\n"
+	},
+	{ "phy_txiqcc", wl_phy_txiqcc, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_txiqcc [a b]\n"
+	"Set/get the iqcc a, b values"
+	},
+	{ "phy_txlocc", wl_phy_txlocc, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: phy_txlocc [di dq ei eq fi fq]\n"
+	"Set/get locc di dq ei eq fi fq values"
+	},
+	{ "phytable", wl_phytable, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: wl phytable table_id offset width_of_table_element [table_element]\n"
+	"Set/get table element of a table with the given ID at the given offset\n"
+	"Note that table width supplied should be 8, 16, 32, 48 or 64\n"
+	"table ID, table offset can not be negative"
+	},
+	{ "force_vsdb_chans", wl_phy_force_vsdb_chans, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/get  channels for forced vsdb mode\n"
+	"usage: wl force_vsdb_chans chan1 chan2\n"
+	"Note: Give chan in the same format as chanspec: eg force_vsdb_chans 1l 48u"
+	},
+	{ "pavars", wl_phy_pavars, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/get temp PA parameters\n"
+	"usage: wl down\n"
+	"       wl pavars pa2gw0a0=0x1 pa2gw1a0=0x2 pa2gw2a0=0x3 ... \n"
+	"       wl pavars\n"
+	"       wl up\n"
+	"  override the PA parameters after driver attach(srom read), before diver up\n"
+	"  These override values will be propogated to HW when driver goes up\n"
+	"  PA parameters in one band range (2g, 5gl, 5g, 5gh) must all present if\n"
+	"  one of them is specified in the command, otherwise it will be filled with 0"
+	},
+	{ "povars", wl_phy_povars, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/get temp power offset\n"
+	"usage: wl down\n"
+	"       wl povars cck2gpo=0x1 ofdm2gpo=0x2 mcs2gpo=0x3 ... \n"
+	"       wl povars\n"
+	"       wl up\n"
+	"  override the power offset after driver attach(srom read), before diver up\n"
+	"  These override values will be propogated to HW when driver goes up\n"
+	"  power offsets in one band range (2g, 5gl, 5g, 5gh) must all present if\n"
+	"  one of them is specified in the command, otherwise it will be filled with 0"
+	"  cck(2g only), ofdm, and mcs(0-7) for NPHY are supported "
+	},
+	{ "rpcalvars", wl_phy_rpcalvars, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/get temp RPCAL parameters\n"
+	"usage: wl down\n"
+	"       wl rpcalvars rpcal2g=0x1 \n"
+	"       wl rpcalvars\n"
+	"       wl up\n"
+	"  override the RPCAL parameters after driver attach(srom read), before diver up\n"
+	"  These override values will be propogated to HW when driver goes up\n"
+	"  Only the RPCAL parameter specified in the command is updated, the rest is untouched"
+	},
+	{ "rpcalphasevars", wl_phy_rpcalphasevars, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/get temp RPCAL PHASE parameters\n"
+	"usage: wl down\n"
+	"       wl rpcalphasevars rpcal_phase2g=0x1 \n"
+	"       wl rpcalphasevars\n"
+	"       wl up\n"
+	"  override the RPCAL PHASE parameters after driver attach(srom read), before diver up\n"
+	"  These override values will be propogated to HW when driver goes up\n"
+	"  Only the RPCALPHASE parameter specified in command is updated, the rest is untouched"
+	},
+	{ "fem", wl_phy_fem, WLC_GET_VAR, WLC_SET_VAR,
+	"Set temp fem2g/5g value\n"
+	"usage: wl fem (tssipos2g=0x1 extpagain2g=0x2 pdetrange2g=0x1 triso2g=0x1 antswctl2g=0)\n"
+	"	(tssipos5g=0x1 extpagain5g=0x2 pdetrange5g=0x1 triso5g=0x1 antswctl5g=0)"
+	},
+	{ "maxpower", wl_phy_maxpower, WLC_GET_VAR, WLC_SET_VAR,
+	"Set temp maxp2g(5g)a0(a1) value\n"
+	"usage: wl maxpower maxp2ga0=0x1 maxp2ga1=0x2 maxp5ga0=0xff maxp5ga1=0xff\n"
+	"       maxp5gla0=0x3 maxp5gla1=0x4 maxp5gha0=0x5 maxp5gha1=0x6"
+	},
+	{ "sample_collect", wl_sample_collect, WLC_PHY_SAMPLE_COLLECT, -1,
+	"Optional parameters ACPHY/HTPHY/(NPHY with NREV >= 7) are:\n"
+	"\t-f File name to dump the sample buffer (default \"sample_collect.dat\")\n"
+	"\t-t Trigger condition (default now)\n"
+	"\t\t now, good_fcs, bad_fcs, bad_plcp, crs, crs_glitch, crs_deassert\n"
+	"\t-b PreTrigger duration in us (default 10)\n"
+	"\t-a PostTrigger duration in us (default 10) \n"
+	"\t-m Sample collect mode (default 1) \n"
+	  "\t\tSC_MODE_0_sd_adc\t\t\t0\n"
+	  "\t\tSC_MODE_1_sd_adc_5bits\t\t\t1\n"
+	  "\t\tSC_MODE_2_cic0\t\t\t\t2\n"
+	  "\t\tSC_MODE_3_cic1\t\t\t\t3\n"
+	  "\t\tSC_MODE_4s_rx_farrow_1core\t\t4\n"
+	  "\t\tSC_MODE_4m_rx_farrow\t\t\t5\n"
+	  "\t\tSC_MODE_5_iq_comp\t\t\t6\n"
+	  "\t\tSC_MODE_6_dc_filt\t\t\t7\n"
+	  "\t\tSC_MODE_7_rx_filt\t\t\t8\n"
+	  "\t\tSC_MODE_8_rssi\t\t\t\t9\n"
+	  "\t\tSC_MODE_9_rssi_all\t\t\t10\n"
+	  "\t\tSC_MODE_10_tx_farrow\t\t\t11\n"
+	  "\t\tSC_MODE_11_gpio\t\t\t\t12\n"
+	  "\t\tSC_MODE_12_gpio_trans\t\t\t13\n"
+	  "\t\tSC_MODE_14_spect_ana\t\t\t14\n"
+	  "\t\tSC_MODE_5s_iq_comp\t\t\t15\n"
+	  "\t\tSC_MODE_6s_dc_filt\t\t\t16\n"
+	  "\t\tSC_MODE_7s_rx_filt\t\t\t17\n"
+	  "\t\t HTPHY: 0=adc, 1..3=adc+rssi, 4=gpio\n"
+	"\t\t NPHY: 1=Dual-Core adc[9:2], 2=Core0 adc[9:0], 3=Core1 adc[9:0], gpio=gpio\n"
+	"\t-g GPIO mux select (default 0)\n"
+	"\t\t use only for gpio mode\n"
+	"\t-k GPIO capture mask. For ACPHY written to gpioCapMaskHigh/gpioCapMaskLow\n"
+	"\t\t use only for gpio mode (default 0xFFFFFFFF)\n"
+	"\t-d Downsample enable (default 0)\n"
+	"\t\t use only for HTPHY\n"
+	"\t-e BeDeaf enable (default 0)\n"
+	"\t-i Timeout in units of 10us. (ACPHY is in 10ms unit) (default 1000)\n"
+	"Optional parameters (NPHY with NREV < 7) are:\n"
+	"\t-u Sample collect duration in us (default 60)\n"
+	"\t-c Cores to do sample collect, only if BW=40MHz (default both)\n"
+	"Optional parameters LCN40PHY are:\n"
+	"\t-s Trigger State (default 0)\n"
+	"\t-x Module_Sel1 (default 2)\n"
+	"\t-y Module_Sel2 (default 6)\n"
+	"\t-n Number of samples (Max 2048, default 2048)\n"
+	"For (NREV < 7), the NPHY buffer returned has the format:\n"
+	"\tIn 20MHz [(uint16)num_bytes, <I(core0), Q(core0), I(core1), Q(core1)>]\n"
+	"\tIn 40MHz [(uint16)num_bytes(core0), <I(core0), Q(core0)>,\n"
+	"\t\t(uint16)num_bytes(core1), <I(core1), Q(core1)>]"},
+	{ "pkteng_start", wl_pkteng, -1, WLC_SET_VAR,
+	"start packet engine tx usage: wl pkteng_start <xx:xx:xx:xx:xx:xx>"
+	" <tx|txwithack> [(async)|sync |sync_unblk] [ipg] [len] [nframes] [src]\n"
+	"\tstart packet engine rx usage: wl pkteng_start <xx:xx:xx:xx:xx:xx>"
+	" <rx|rxwithack> [(async)|sync] [rxframes] [rxtimeout]\n"
+	"\tsync: synchronous mode\n"
+	"\tsync_unblk: synchronous unblock mode\n"
+	"\tipg: inter packet gap in us\n"
+	"\tlen: packet length\n"
+	"\tnframes: number of frames; 0 indicates continuous tx test\n"
+	"\tsrc: source mac address\n"
+	"\trxframes: number of receive frames (sync mode only)\n"
+	"\trxtimeout: maximum timout in msec (sync mode only)"},
+	{ "pkteng_stop", wl_pkteng, -1, WLC_SET_VAR,
+	"stop packet engine; usage: wl pkteng_stop <tx|rx>"},
+	{ "pkteng_stats", wl_pkteng_stats, -1, WLC_GET_VAR,
+	"packet engine stats; usage: wl pkteng_stats:\n"
+	"\t-g temperature correction mode, 0 (enabled by default), 1 (disable)"},
+	{ "pkteng_status", wl_pkteng_status, -1, WLC_GET_VAR,
+	"packet engine status; usage: wl pkteng_status"},
+	{"phy_force_crsmin", wl_phy_force_crsmin, -1, WLC_SET_VAR,
+	"Auto crsmin: \n"
+	"       phy_force_crsmin -1\n"
+	"Default crsmin value\n\n"
+	"       phy_force_crsmin 0\n"
+	"Set the crsmin value\n"
+	"       phy_force_crsmin core0_th core1_offset core2_offset\n"
+	"\n"
+	"Threshold values = 2.5 x NoisePwr_dBm + intercept\n"
+	"       where\n"
+	"              NoisePwr_dBm ~= -36/-33/-30dBm for 20/40/80MHz, respectively\n"
+	"              Intercept = 132/125/119 for 20/40/80MHz, respectively"
+	},
+	{ "radarargs", wl_radar_args, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set Radar parameters in \n"
+	"\torder as version, npulses, ncontig, min_pw, max_pw, thresh0, thresh1,\n"
+	"\tblank, fmdemodcfg, npulses_lp, min_pw_lp, max_pw_lp,\n"
+	"\tmin_fm_lp, max_span_lp, min_deltat, max_deltat,\n"
+	"\tautocorr, st_level_time, t2_min, fra_pulse_err, npulses_fra,\n"
+	"\tnpulses_stg2, npulses_stg3, percal_mask, quant, \n"
+	"\tmin_burst_intv_lp, max_burst_intv_lp, nskip_rst_lp, max_pw_tol, feature_mask, \n"
+	"\tthresh0_sc, thresh1_sc"},
+	{ "radarargs40", wl_radar_args, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set Radar parameters for 40Mhz channel in \n"
+	"\torder as version, npulses, ncontig, min_pw, max_pw, thresh0, thresh1,\n"
+	"\tthresh0_sc, thresh1_sc, blank, fmdemodcfg, npulses_lp, min_pw_lp, max_pw_lp,\n"
+	"\tmin_fm_lp, max_span_lp, min_deltat, max_deltat,\n"
+	"\tautocorr, st_level_time, t2_min, fra_pulse_err, npulses_fra,\n"
+	"\tnpulses_stg2, npulses_stg3, percal_mask, quant, \n"
+	"\tmin_burst_intv_lp, max_burst_intv_lp, nskip_rst_lp, max_pw_tol, feature_mask,\n"
+	"\tthresh0_sc, thresh1_sc"},
+	{ "radarthrs", wl_radar_thrs, -1, WLC_SET_VAR,
+	"Set Radar threshold for both 20 & 40MHz & 80MHz BW:\n"
+	"\torder as thresh0_20_lo, thresh1_20_lo, thresh0_40_lo, thresh1_40_lo\n"
+	"\tthresh0_80_lo, thresh1_80_lo, thresh0_20_hi, thresh1_20_hi\n"
+	"\tthresh0_40_hi, thresh1_40_hi, thresh0_80_hi, thresh1_80_hi\n"
+	#ifdef WL11AC160
+	"\tthresh0_160_lo, thresh1_160_lo, thresh0_160_hi, thresh1_160_hi"
+	#endif
+	},
+	{ "radarthrs2", wl_radar_thrs2, WLC_GET_VAR, WLC_SET_VAR,
+	"Set Radar threshold for both 20 & 40MHz & 80MHz BW:\n"
+	"\tthresh0_sc_20_lo, thresh1_sc_20_lo, thresh0_sc_40_lo, thresh1_sc_40_lo\n"
+	"\tthresh0_sc_80_lo, thresh1_sc_80_lo, thresh0_sc_20_hi, thresh1_sc_20_hi\n"
+	"\tthresh0_sc_40_hi, thresh1_sc_40_hi, thresh0_sc_80_hi, thresh1_sc_80_hi\n"
+	"\tfc_varth_sb, fc_varth_bin5_sb, notradar_enb, max_notradar_lp, max_notradar,\n"
+	"\tmax_notradar_lp_sc, max_notradar_sc, highpow_war_enb, highpow_sp_ratio"},
+	{ "phy_dyn_switch_th", wl_phy_dyn_switch_th, WLC_GET_VAR, WLC_SET_VAR,
+	"Set wighting number for dynamic switch:\n"
+	"\trssi_gain_80_3, rssi_gain_80_2, rssi_gain_80_1, rssi_gain_80_0\n"
+	"\trssi_gain_160_3, rssi_gain_160_2, rssi_gain_160_1, rssi_gain_160_0\n"
+	"\trssi_th_2, rssi_th_1, rssi_th_0"},
+	{ "phy_tpc_av", wl_phy_tpc_av, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: \n\t(set) phy_tpc_av <core> <sub-band> <av-value>"
+	"       \n\t(get) phy_tpc_av <core> <sub-band>"
+	"\n\tSet/Get Av for the given core and sub-band"
+	"\n\tsub-band, 0 for 2G"
+	"\n\tsub-band, 1 for 5G-ll"
+	"\n\tsub-band, 2 for 5G-lu"
+	"\n\tsub-band, 3 for 5G-ul"
+	"\n\tsub-band, 4 for 5G-uu"
+	"\n\tav-value, 0 to 7"
+	},
+	{ "phy_tpc_vmid", wl_phy_tpc_vmid, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: \n\t(set) phy_tpc_vmid <core> <sub-band> <vmid-value>"
+	"       \n\t(get) phy_tpc_vmid <core> <sub-band>"
+	"\n\tSet/Get Vmid for the given core and sub-band"
+	"\n\tsub-band, 0 for 2G"
+	"\n\tsub-band, 1 for 5G-ll"
+	"\n\tsub-band, 2 for 5G-lu"
+	"\n\tsub-band, 3 for 5G-ul"
+	"\n\tsub-band, 4 for 5G-uu"
+	"\n\tvmid-value, 0 to 255"
+	},
+	/* TXCAL IOVARS */
+	{"phy_read_estpwrlut", wl_read_estpwrlut, WLC_GET_VAR, -1,
+	"Read EstPwr LUT: wl phy_read_estpwrlut core"},
+	{ "txcal_gainsweep", wl_txcal_gainsweep, -1, WLC_SET_VAR,
+	"start Gain Sweep for TX Cal: wl txcal_gainsweep <xx:xx:xx:xx:xx:xx>"
+	" [ipg] [len] [nframes] [gidx_start:step:gidx_stop]\n"
+	"\tipg: inter packet gap in us\n"
+	"\tlen: packet length\n"
+	"\tnframes: number of frames; 0 indicates continuous tx test\n"
+	"\tgidx_start: Starting TX gain Index\n"
+	"\tgidx_stop: Stopping TX gain Index\n"
+	"\tstep:step size for tx gain index increment"},
+	{ "txcal_gainsweep_meas", wl_txcal_gainsweep_meas, WLC_GET_VAR, WLC_SET_VAR,
+	"Get TSSI/PWR measurments from last TX Cal Gain Sweep: wl txcal_gainsweep_meas\n"
+	"Set PWR measurements for TX Cal Gain Sweep: wl txcal_gainsweep_meas core p0 p1 ... p127"},
+	{"txcal_pwr_tssi_tbl", wl_txcal_pwr_tssi_tbl, WLC_GET_VAR, WLC_SET_VAR,
+	"Get the saved consolidated TSSI/PWR table: wl txcal_pwr_tssi_tbl <core> <chan>\n"
+	"\tGenerate consolidated TSSI/PWR table from last TX Cal Gain Sweep:"
+	" wl txcal_pwr_tssi_tbl <core> <Ps> <N> <Ch>\n"
+	"\t\tPs: Starting Power in 6.3 format\n"
+	"\t\tN: Number of entries in the table covering the power range (Ps : (Ps+N-1))\n"
+	"\tSet the cosolidated TSSI/PWR table: "
+	"wl txcal_pwr_tssi_tbl <core> <Ps> <N> <Ch> <Tssi_Ps Tssi_Ps+1 .. Tssi_Ps+N-1>\n"
+	"\t\tPs: Starting Power in 6.3 format\n"
+	"\t\tN: Number of entries in the table covering the power range (Ps : (Ps+N-1))\n"
+	"\t\tCh: Channel Number\n"
+	"\t\tTssi_X: Adjusted TSSI corresponding to Power X\n"
+	"\tMax number of channel data allowed: 32\n"},
+	{"olpc_anchoridx", wl_olpc_anchoridx, WLC_GET_VAR, WLC_SET_VAR,
+	"Get the saved tx power idx and temperature at the olpc anchor power level:\n"
+	"wl olpc_anchoridx <core> <chan>\n"
+	"Set the temperature and tx power idx at the olpc anchor power level:\n"
+	"wl olpc_anchoridx <core> <chan> <idx> <temp>\n"
+	"olpc anchor power level is specified via nvram paramter or iovar.\n"},
+	{"olpc_offset", wl_olpc_offset, WLC_GET_VAR, WLC_SET_VAR,
+	"Get the offset to tx idx to be applied for baseindex calculation in LUT based OLPC\n"
+	"wl olpc_offset \n"
+	"Set the offset to tx idx to be applied for baseindex calculation in LUT based OLPC\n"
+	"wl olpc_offset 2G 5GLow 5GMid 5Ghigh 5GX1\n"},
+	{ "phy_snr_ant", wl_phy_snr_ant, WLC_GET_VAR, WLC_SET_VAR,
+	"Get SNR per antenna (only gives SNR of current antenna for SISO PHY)"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_phy_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register phy commands */
+	wl_module_cmds_register(wl_phy_cmds);
+}
+
+static int
+wl_phy_rssi_ant(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	uint i;
+	wl_rssi_ant_t *rssi_ant_p;
+	struct ether_addr ea;
+	struct ether_addr *ea_p;
+	int ea_l;
+	void *ptr = NULL;
+
+	if (!*++argv) {
+		ea_p = NULL;
+		ea_l = 0;
+	}
+	else if (wl_ether_atoe(*argv, &ea)) {
+		ea_p = &ea;
+		ea_l = ETHER_ADDR_LEN;
+	}
+	else {
+		fprintf(stderr, " ERROR: no valid ether addr provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((ret = wlu_var_getbuf(wl, cmd->name, ea_p, ea_l, &ptr)) < 0)
+		return ret;
+
+	rssi_ant_p = (wl_rssi_ant_t *)ptr;
+	rssi_ant_p->version = dtoh32(rssi_ant_p->version);
+	rssi_ant_p->count = dtoh32(rssi_ant_p->count);
+
+	if (rssi_ant_p->count == 0) {
+		printf("not supported on this chip\n");
+	} else {
+		for (i = 0; i < rssi_ant_p->count; i++)
+			printf("rssi[%d] %d  ", i, rssi_ant_p->rssi_ant[i]);
+		printf("\n");
+	}
+	return ret;
+}
+
+static int
+wl_phy_snr_ant(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	uint i;
+	wl_snr_ant_t *snr_ant_p;
+	struct ether_addr ea;
+	struct ether_addr *ea_p;
+	int ea_l;
+	void *ptr = NULL;
+
+	if (!*++argv) {
+		ea_p = NULL;
+		ea_l = 0;
+	}
+	else if (wl_ether_atoe(*argv, &ea)) {
+		ea_p = &ea;
+		ea_l = ETHER_ADDR_LEN;
+	}
+	else {
+		fprintf(stderr, " ERROR: no valid ether addr provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((ret = wlu_var_getbuf_sm(wl, cmd->name, ea_p, ea_l, &ptr)) < 0)
+		return ret;
+
+	snr_ant_p = (wl_snr_ant_t *)ptr;
+	snr_ant_p->version = dtoh32(snr_ant_p->version);
+	snr_ant_p->count = dtoh32(snr_ant_p->count);
+
+	if (snr_ant_p->count == 0) {
+		printf("not supported on this chip\n");
+	} else {
+		for (i = 0; i < snr_ant_p->count; i++)
+			printf("snr[%d] %d  ", i, snr_ant_p->snr_ant[i]);
+		printf("\n");
+	}
+	return ret;
+}
+
+
+#include <devctrl_if/phyioctl_defs.h>
+
+static phy_msg_t wl_phy_msgs[] = {
+	{PHYHAL_ERROR,	"error"},
+	{PHYHAL_ERROR, 	"err"},
+	{PHYHAL_TRACE,	"trace"},
+	{PHYHAL_INFORM,	"inform"},
+	{PHYHAL_TMP,	"tmp"},
+	{PHYHAL_TXPWR,	"txpwr"},
+	{PHYHAL_CAL,	"cal"},
+	{PHYHAL_RADAR,	"radar"},
+	{PHYHAL_THERMAL, "thermal"},
+	{PHYHAL_PAPD,	"papd"},
+	{PHYHAL_RXIQ,	"rxiq"},
+	{PHYHAL_FCBS,	"fcbs"},
+	{PHYHAL_CHANLOG, "chanlog"},
+	{0,		NULL}
+	};
+
+static int
+wl_phymsglevel(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint val = 0, last_val = 0;
+	uint phymsglevel = 0, phymsglevel_add = 0, phymsglevel_del = 0;
+	char *endptr;
+	phy_msg_t *phy_msg = wl_phy_msgs;
+	const char *cmdname = "phymsglevel";
+
+	UNUSED_PARAMETER(cmd);
+	if ((ret = wlu_iovar_getint(wl, cmdname, (int *)&phymsglevel) < 0)) {
+		return ret;
+	}
+	phymsglevel = dtoh32(phymsglevel);
+	if (!*++argv) {
+		printf("0x%x ", phymsglevel);
+		for (i = 0; (val = phy_msg[i].value); i++) {
+			if ((phymsglevel & val) && (val != last_val))
+				printf(" %s", phy_msg[i].string);
+			last_val = val;
+		}
+		printf("\n");
+		return (0);
+	}
+	while (*argv) {
+		char *s = *argv;
+		if (*s == '+' || *s == '-')
+			s++;
+		else
+			phymsglevel_del = ~0; /* make the whole list absolute */
+		val = strtoul(s, &endptr, 0);
+		if (val == 0xFFFFFFFF) {
+			fprintf(stderr,
+				"Bits >32 are not supported on this driver version\n");
+			val = 1;
+		}
+		/* not an integer if not all the string was parsed by strtoul */
+		if (*endptr != '\0') {
+			for (i = 0; (val = phy_msg[i].value); i++)
+				if (stricmp(phy_msg[i].string, s) == 0)
+					break;
+				if (!val)
+					goto usage;
+		}
+		if (**argv == '-')
+			phymsglevel_del |= val;
+		else
+			phymsglevel_add |= val;
+		++argv;
+	}
+	phymsglevel &= ~phymsglevel_del;
+	phymsglevel |= phymsglevel_add;
+	phymsglevel = htod32(phymsglevel);
+	return (wlu_iovar_setint(wl, cmdname, (int)phymsglevel));
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+	for (i = 0; (val = phy_msg[i].value); i++) {
+		if (val != last_val)
+			fprintf(stderr, "\n0x%04x %s", val, phy_msg[i].string);
+		else
+			fprintf(stderr, ", %s", phy_msg[i].string);
+		last_val = val;
+	}
+	return 0;
+}
+static int
+wl_get_instant_power(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	tx_inst_power_t *power;
+	uint band_list[3];
+
+	UNUSED_PARAMETER(cmd);
+	UNUSED_PARAMETER(argv);
+
+	strcpy(buf, "txinstpwr");
+	if ((ret = wlu_get(wl, WLC_GET_VAR, &buf[0], WLC_IOCTL_MAXLEN)) < 0) {
+		return ret;
+	}
+
+	power = (tx_inst_power_t *)buf;
+	/* Make the most of the info returned in band_list!
+	 * b/g and a
+	 * b/g-uni
+	 * a-uni
+	 * NOTE: NO a and b/g case ...
+	 */
+	if ((ret = wlu_get(wl, WLC_GET_BANDLIST, band_list, sizeof(band_list))) < 0)
+		return (ret);
+	band_list[0] = dtoh32(band_list[0]);
+	band_list[1] = dtoh32(band_list[1]);
+	band_list[2] = dtoh32(band_list[2]);
+
+	/* If B/G is present it's always the lower index */
+	if (band_list[1] == WLC_BAND_2G) {
+			printf("Last B phy CCK est. power:\t%2d.%d dBm\n",
+			       DIV_QUO(power->txpwr_est_Pout[0], 4),
+			       DIV_REM(power->txpwr_est_Pout[0], 4));
+			printf("Last B phy OFDM est. power:\t%2d.%d dBm\n",
+			       DIV_QUO(power->txpwr_est_Pout_gofdm, 4),
+			       DIV_REM(power->txpwr_est_Pout_gofdm, 4));
+
+			printf("\n");
+	}
+
+	/* A band */
+	if (band_list[1] == WLC_BAND_5G || (band_list[0] > 1 && band_list[2] == WLC_BAND_5G)) {
+		printf("Last A phy est. power:\t\t%2d.%d dBm\n",
+		       DIV_QUO(power->txpwr_est_Pout[1], 4),
+		       DIV_REM(power->txpwr_est_Pout[1], 4));
+	}
+
+	return ret;
+}
+
+static int
+wl_evm(void *wl, cmd_t *cmd, char **argv)
+{
+	int val[3];
+
+	/* Get channel */
+	if (!*++argv) {
+		fprintf(stderr, "Need to specify at least one parameter\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!stricmp(*argv, "off"))
+		val[0] = 0;
+	else
+		val[0] = atoi(*argv);
+
+	/* set optional parameters to default */
+	val[1] = 4;	/* rate in 500Kb units */
+	val[2] = 0;	/* This is ignored */
+
+	/* Get optional rate and convert to 500Kb units */
+	if (*++argv)
+		val[1] = rate_string2int(*argv);
+
+	val[0] = htod32(val[0]);
+	val[1] = htod32(val[1]);
+	val[2] = htod32(val[2]);
+	return wlu_set(wl, cmd->set, val, sizeof(val));
+}
+
+static int
+wl_tssi(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+
+	UNUSED_PARAMETER(argv);
+
+	if (cmd->get < 0)
+		return -1;
+	if ((ret = wlu_get(wl, cmd->get, &val, sizeof(int))) < 0)
+		return ret;
+
+	val = dtoh32(val);
+	printf("CCK %d OFDM %d\n", (val & 0xff), (val >> 8) & 0xff);
+	return 0;
+}
+
+static int
+wl_atten(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	atten_t atten;
+	char *endptr;
+
+	memset(&atten, 0, sizeof(atten_t));
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+
+		if ((ret = wlu_get(wl, cmd->get, &atten, sizeof(atten_t))) < 0)
+			return ret;
+
+		printf("tx %s bb/radio/ctl1 %d/%d/%d\n",
+		       (dtoh16(atten.auto_ctrl) ? "auto" : ""),
+			dtoh16(atten.bb), dtoh16(atten.radio), dtoh16(atten.txctl1));
+
+		return 0;
+	} else {
+		if (cmd->set < 0)
+			return -1;
+
+		if (!stricmp(*argv, "auto")) {
+			atten.auto_ctrl = WL_ATTEN_PCL_ON;
+			atten.auto_ctrl = htod16(atten.auto_ctrl);
+		}
+		else if (!stricmp(*argv, "manual")) {
+			atten.auto_ctrl = WL_ATTEN_PCL_OFF;
+			atten.auto_ctrl = htod16(atten.auto_ctrl);
+		}
+		else {
+			atten.auto_ctrl = WL_ATTEN_APP_INPUT_PCL_OFF;
+			atten.auto_ctrl = htod16(atten.auto_ctrl);
+
+			atten.bb = (uint16)strtoul(*argv, &endptr, 0);
+			atten.bb = htod16(atten.bb);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+
+			atten.radio = (uint16)strtoul(*argv, &endptr, 0);
+			atten.radio = htod16(atten.radio);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+
+			atten.txctl1 = (uint16)strtoul(*argv, &endptr, 0);
+			atten.txctl1 = htod16(atten.txctl1);
+			if (*endptr != '\0') {
+				/* not all the value string was parsed by strtol */
+				return BCME_USAGE_ERROR;
+			}
+
+		}
+
+		return wlu_set(wl, cmd->set, &atten, sizeof(atten_t));
+	}
+}
+
+static int
+wl_interfere(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char *endptr = NULL;
+	int mode;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((ret = wlu_get(wl, cmd->get, &mode, sizeof(mode))) < 0)
+			return ret;
+		mode = dtoh32(mode);
+		if (phytype == WLC_PHY_TYPE_AC) {
+			mode &= 0x7f;
+			if (mode == INTERFERE_NONE) {
+				printf("All interference mitigation is disabled. (mode 0)\n");
+			} else {
+				printf("\nMode = %d. Following ACI modes are enabled:\n", mode);
+				if (mode & ACPHY_ACI_GLITCHBASED_DESENSE)
+					printf("\tbit-mask %d:  Reciever Desense based on glitch "
+					       "count\n",
+					       ACPHY_ACI_GLITCHBASED_DESENSE);
+				if (mode & ACPHY_ACI_HWACI_PKTGAINLMT)
+					printf("\tbit-mask %d:  Limit pktgain based on hwaci "
+					       "(high pwr aci)\n",
+					       ACPHY_ACI_HWACI_PKTGAINLMT);
+				if (mode & ACPHY_ACI_W2NB_PKTGAINLMT)
+					printf("\tbit-mask %d:  Limit pktgain based on w2/nb "
+					       "(high pwr aci)\n",
+					       ACPHY_ACI_W2NB_PKTGAINLMT);
+				if (mode & ACPHY_ACI_PREEMPTION)
+					printf("\tbit-mask %d:  Preemption is enabled\n",
+					       ACPHY_ACI_PREEMPTION);
+				if (mode & ACPHY_HWACI_MITIGATION)
+					printf("\tbit-mask %d: HW ACI Detection + Mitigation\n",
+					       ACPHY_HWACI_MITIGATION);
+				if (mode & ACPHY_LPD_PREEMPTION)
+					printf("\tbit-mask %d: Low Power Detect Preemption\n",
+					       ACPHY_LPD_PREEMPTION);
+				if (mode & ACPHY_HWOBSS_MITIGATION)
+					printf("\tbit-mask %d: HW OBSS Detection + Mitigation\n",
+					       ACPHY_HWOBSS_MITIGATION);
+			}
+			printf("\n");
+		} else {
+			switch (mode & 0x7f) {
+			case INTERFERE_NONE:
+				printf("All interference mitigation is disabled. (mode 0)\n");
+				break;
+			case NON_WLAN:
+				printf("Non-wireless LAN Interference mitigation is enabled."
+					" (mode 1)\n");
+				break;
+			case WLAN_MANUAL:
+				printf("Wireless LAN Interference mitigation is enabled."
+					" (mode 2)\n");
+				break;
+			case WLAN_AUTO:
+				printf("Auto Wireless LAN Interference mitigation is enabled and ");
+				if (mode & AUTO_ACTIVE)
+					printf("active. (mode 3)\n");
+				else
+					printf("not active. (mode 3)\n");
+
+				break;
+			case WLAN_AUTO_W_NOISE:
+				printf("Auto Wireless LAN Interference mitigation is enabled and ");
+				if (mode & AUTO_ACTIVE)
+					printf("active, ");
+				else
+					printf("not active, ");
+
+				printf("and noise reduction is enabled. (mode 4)\n");
+				break;
+			}
+		}
+		return 0;
+	} else {
+		mode = INTERFERE_NONE;
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+		if (phytype == WLC_PHY_TYPE_AC) {
+			if (val > ACPHY_ACI_MAX_MODE) {
+				printf("ACPHY Interference mode > ACPHY_ACI_MAX_MODE!\n");
+				return -1;
+			} else if ((val & ACPHY_LPD_PREEMPTION) && !(val & ACPHY_ACI_PREEMPTION)) {
+				fprintf(stderr, "Low Power Detect Preemption (bit 5)"
+						" requires Preemption (bit3) to be enabled\n");
+				return BCME_USAGE_ERROR;
+			} else {
+				mode = val;
+			}
+		} else {
+			switch (val) {
+			case 0:
+				mode = INTERFERE_NONE;
+				break;
+			case 1:
+				mode = NON_WLAN;
+				break;
+			case 2:
+				mode = WLAN_MANUAL;
+				break;
+			case 3:
+				mode = WLAN_AUTO;
+				break;
+			case 4:
+				mode = WLAN_AUTO_W_NOISE;
+				break;
+			default:
+				return BCME_BADARG;
+			}
+		}
+
+		mode = htod32(mode);
+		return wlu_set(wl, cmd->set, &mode, sizeof(mode));
+	}
+}
+
+static int
+wl_interfere_override(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char *endptr;
+	int mode;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (!*++argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((ret = wlu_get(wl, cmd->get, &mode, sizeof(mode))) < 0) {
+			return ret;
+		}
+		printf("\nMode = %d. Following ACI modes :\n", mode);
+		mode = dtoh32(mode);
+		if (phytype == WLC_PHY_TYPE_AC) {
+			if (mode == INTERFERE_OVRRIDE_OFF)
+				printf("Interference override disabled.\n");
+			else if (mode == INTERFERE_NONE)
+				printf("Interference override NONE, "
+				       "all mitigation disabled. (mode 0)\n");
+			else {
+				printf("\nInterference override mode = %d. Following ACI modes "
+				       "are enabled:\n", mode);
+				if (mode & ACPHY_ACI_GLITCHBASED_DESENSE)
+					printf("\tbit-mask %d:  Reciever Desense based on glitch "
+					       "count\n",
+					       ACPHY_ACI_GLITCHBASED_DESENSE);
+				if (mode & ACPHY_ACI_HWACI_PKTGAINLMT)
+					printf("\tbit-mask %d:  Limit pktgain based on hwaci "
+					       "(high pwr aci)\n",
+					       ACPHY_ACI_HWACI_PKTGAINLMT);
+				if (mode & ACPHY_ACI_W2NB_PKTGAINLMT)
+					printf("\tbit-mask %d:  Limit pktgain based on w2/nb "
+					       "(high pwr aci)\n",
+					       ACPHY_ACI_W2NB_PKTGAINLMT);
+				if (mode & ACPHY_ACI_PREEMPTION)
+					printf("\tbit-mask %d:  Preemption is enabled\n",
+					       ACPHY_ACI_PREEMPTION);
+				if (mode & ACPHY_HWACI_MITIGATION)
+					printf("\tbit-mask %d: HW ACI Detection + Mitigation\n",
+					       ACPHY_HWACI_MITIGATION);
+				if (mode & ACPHY_LPD_PREEMPTION)
+					printf("\tbit-mask %d: Low Power Detect Preemption\n",
+					       ACPHY_LPD_PREEMPTION);
+				if (mode & ACPHY_HWOBSS_MITIGATION)
+					printf("\tbit-mask %d: HW OBSS Detection + Mitigation\n",
+					       ACPHY_HWOBSS_MITIGATION);
+			}
+			printf("\n");
+		} else {
+			switch (mode & 0x7f) {
+			case INTERFERE_NONE:
+				printf("Interference override NONE, "
+				"all mitigation disabled. (mode 0)\n");
+				break;
+			case NON_WLAN:
+				printf("Interference override enabled. "
+					" Non-wireless LAN Interference mitigation is enabled."
+					" (mode 1)\n");
+				break;
+			case WLAN_MANUAL:
+				printf("Interference override enabled.  "
+					" Wireless LAN Interference mitigation is enabled."
+					" (mode 2)\n");
+				break;
+			case WLAN_AUTO:
+				printf("Interference override enabled. "
+					" Interference mitigation is enabled and ");
+				if (mode & AUTO_ACTIVE)
+					printf("active. (mode 3)\n");
+				else
+					printf("not active. (mode 3)\n");
+				break;
+			case WLAN_AUTO_W_NOISE:
+				printf("Interference override enabled. "
+					" Interference mitigation is enabled and ");
+				if (mode & AUTO_ACTIVE)
+					printf("active, ");
+				else
+					printf("not active, ");
+				printf("and noise reduction is enabled. (mode 4)\n");
+				break;
+			case INTERFERE_OVRRIDE_OFF:
+				printf("Interference override disabled. \n");
+				break;
+			}
+		}
+		return 0;
+	} else {
+		mode = INTERFERE_NONE;
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+		if (phytype == WLC_PHY_TYPE_AC) {
+			if (val > ACPHY_ACI_MAX_MODE) {
+				return -1;
+			} else if ((val & ACPHY_LPD_PREEMPTION) && !(val & ACPHY_ACI_PREEMPTION)) {
+				fprintf(stderr, "Low Power Detect Preemption (bit 5)"
+						" requires Preemption (bit3) to be enabled\n");
+				return BCME_USAGE_ERROR;
+			} else {
+				mode = val;
+			}
+		} else {
+			switch (val) {
+			case 0:
+				mode = INTERFERE_NONE;
+				break;
+			case 1:
+				mode = NON_WLAN;
+				break;
+			case 2:
+				mode = WLAN_MANUAL;
+				break;
+			case 3:
+				mode = WLAN_AUTO;
+				break;
+			case 4:
+				mode = WLAN_AUTO_W_NOISE;
+				break;
+			case INTERFERE_OVRRIDE_OFF:
+				mode = INTERFERE_OVRRIDE_OFF;
+				break;
+			default:
+				return BCME_BADARG;
+			}
+		}
+
+		mode = htod32(mode);
+		return wlu_set(wl, cmd->set, &mode, sizeof(mode));
+	}
+}
+
+#define ACI_SPIN	"spin"
+#define ACI_ENTER	"enter"
+#define ACI_EXIT	"exit"
+#define ACI_GLITCH	"glitch"
+
+#define NPHY_ACI_ADCPWR_ENTER "adcpwr_enter"
+#define NPHY_ACI_ADCPWR_EXIT "adcpwr_exit"
+#define NPHY_ACI_REPEAT_CTR "repeat"
+#define NPHY_ACI_NUM_SAMPLES "samples"
+#define NPHY_ACI_UNDETECT "undetect_sz"
+#define NPHY_ACI_LOPWR "loaci"
+#define NPHY_ACI_MDPWR "mdaci"
+#define NPHY_ACI_HIPWR "hiaci"
+#define NPHY_ACI_NOISE_NOASSOC_GLITCH_TH_UP "nphy_noise_noassoc_glitch_th_up"
+#define NPHY_ACI_NOISE_NOASSOC_GLITCH_TH_DN "nphy_noise_noassoc_glitch_th_dn"
+#define NPHY_ACI_NOISE_ASSOC_GLITCH_TH_UP "nphy_noise_assoc_glitch_th_up"
+#define NPHY_ACI_NOISE_ASSOC_GLITCH_TH_DN "nphy_noise_assoc_glitch_th_dn"
+#define NPHY_ACI_NOISE_ASSOC_ACI_GLITCH_TH_UP "nphy_noise_assoc_aci_glitch_th_up"
+#define NPHY_ACI_NOISE_ASSOC_ACI_GLITCH_TH_DN "nphy_noise_assoc_aci_glitch_th_dn"
+#define NPHY_ACI_NOISE_NOASSOC_ENTER_TH "nphy_noise_noassoc_enter_th"
+#define NPHY_ACI_NOISE_ASSOC_ENTER_TH "nphy_noise_assoc_enter_th"
+#define NPHY_ACI_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH \
+"nphy_noise_assoc_rx_glitch_badplcp_enter_th"
+#define NPHY_ACI_NOISE_ASSOC_CRSIDX_INCR "nphy_noise_assoc_crsidx_incr"
+#define NPHY_ACI_NOISE_NOASSOC_CRSIDX_INCR "nphy_noise_noassoc_crsidx_incr"
+#define NPHY_ACI_NOISE_CRSIDX_DECR "nphy_noise_crsidx_decr"
+
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+#if !defined(DONGLEBUILD)
+static int
+wl_do_samplecollect_lcn40(void *wl, wl_samplecollect_args_t *collect, uint8 *buff, FILE *fp)
+{
+	uint32 cnt;
+	int ret = 0;
+	uint32 *data;
+	int16 IData, QData;
+	uint16 wordlength = 14;
+	uint16 mask = ((0x1 << wordlength) - 1);
+	uint16 wrap = (0x1 << (wordlength - 1));
+	uint16 maxd = (0x1 << wordlength);
+
+	ret = wlu_iovar_getbuf(wl, "sample_collect", collect, sizeof(wl_samplecollect_args_t),
+		buff, WLC_SAMPLECOLLECT_MAXLEN);
+
+	if (ret)
+		return ret;
+
+	data = (uint32*)buff;
+	for (cnt = 0; cnt < collect->nsamps; cnt++) {
+
+		IData = data[cnt] & mask;
+		QData = ((data[cnt] >> 16) & mask);
+
+		if (IData >= wrap) {
+			IData = IData - maxd;
+		}
+		if (QData >= wrap) {
+			QData = QData - maxd;
+		}
+		fprintf(fp, "%d %d\n", IData, QData);
+	}
+	return cnt;
+}
+static int
+wl_do_samplecollect_n(void *wl, wl_samplecollect_args_t *collect, uint8 *buff, FILE *fp)
+{
+	uint16 nbytes;
+	int ret = 0;
+
+	ret = wlu_iovar_getbuf(wl, "sample_collect", collect, sizeof(wl_samplecollect_args_t),
+		buff, WLC_SAMPLECOLLECT_MAXLEN);
+
+	if (ret)
+		return ret;
+
+	/* bytes 1:0 indicate capture length */
+	while ((nbytes = ltoh16_ua(buff))) {
+		nbytes += 2;
+		ret = fwrite(buff, 1, nbytes, fp);
+		if (ret != nbytes) {
+			fprintf(stderr, "Error writing %d bytes to file, rc %d!\n",
+				nbytes, ret);
+			ret = -1;
+			break;
+		} else {
+			fprintf(stderr, "Wrote %d bytes\n", nbytes);
+		}
+		buff += nbytes;
+	}
+	return (ret);
+}
+#endif 
+#endif /* defined(BWL_FILESYSTEM_SUPPORT) */
+
+#if defined(BWL_FILESYSTEM_SUPPORT)
+#if !defined(DONGLEBUILD)
+static int
+wl_do_samplecollect(void *wl, wl_samplecollect_args_t *collect, int sampledata_version,
+	uint32 *buff, FILE *fp)
+{
+	uint16 nbytes, tag;
+	uint32 flag, *header, sync;
+	uint8 *ptr;
+	int err;
+	wl_sampledata_t *sample_collect;
+	wl_sampledata_t sample_data, *psample;
+
+	err = wlu_iovar_getbuf(wl, "sample_collect", collect, sizeof(wl_samplecollect_args_t),
+		buff, WLC_SAMPLECOLLECT_MAXLEN);
+
+	if (err)
+		return err;
+
+	sample_collect = (wl_sampledata_t *)buff;
+	header = (uint32 *)&sample_collect[1];
+	tag = ltoh16_ua(&sample_collect->tag);
+	if (tag != WL_SAMPLEDATA_HEADER_TYPE) {
+		fprintf(stderr, "Expect SampleData Header type %d, receive type %d\n",
+			WL_SAMPLEDATA_HEADER_TYPE, tag);
+		return -1;
+	}
+
+	nbytes = ltoh16_ua(&sample_collect->length);
+	flag = ltoh32_ua(&sample_collect->flag);
+	sync = ltoh32_ua(&header[0]);
+	if (sync != 0xACDC2009) {
+		fprintf(stderr, "Header sync word mismatch (0x%08x)\n", sync);
+		return -1;
+	}
+
+	err = fwrite((uint8 *)header, 1, nbytes, fp);
+	if (err != (int)nbytes)
+		  fprintf(stderr, "Failed write file-header to file %d\n", err);
+
+	memset(&sample_data, 0, sizeof(wl_sampledata_t));
+	sample_data.version = sampledata_version;
+	sample_data.size = htol16(sizeof(wl_sampledata_t));
+	flag = 0;
+	/* new format, used in htphy */
+	do {
+		sample_data.tag = htol16(WL_SAMPLEDATA_TYPE);
+		sample_data.length = htol16(WLC_SAMPLECOLLECT_MAXLEN);
+		/* mask seq# */
+	        sample_data.flag = htol32((flag & 0xff));
+
+		err = wlu_iovar_getbuf(wl, "sample_data", &sample_data, sizeof(wl_sampledata_t),
+			buff, WLC_SAMPLECOLLECT_MAXLEN);
+		if (err) {
+			fprintf(stderr, "Error reading back sample collected data\n");
+			err = -1;
+			break;
+		}
+
+		ptr = (uint8 *)buff + sizeof(wl_sampledata_t);
+		psample = (wl_sampledata_t *)buff;
+		tag = ltoh16_ua(&psample->tag);
+		nbytes = ltoh16_ua(&psample->length);
+		flag = ltoh32_ua(&psample->flag);
+		if (tag != WL_SAMPLEDATA_TYPE) {
+			fprintf(stderr, "Expect SampleData type %d, receive type %d\n",
+				WL_SAMPLEDATA_TYPE, tag);
+			err = -1;
+			break;
+		}
+		if (nbytes == 0) {
+			fprintf(stderr, "Done retrieving sample data\n");
+			err = -1;
+			break;
+		}
+
+		err = fwrite(ptr, 1, nbytes, fp);
+		if (err != (int)nbytes) {
+			fprintf(stderr, "Error writing %d bytes to file, rc %d!\n",
+				(int)nbytes, err);
+			err = -1;
+			break;
+		} else {
+			printf("Wrote %d bytes\n", err);
+			err = 0;
+		}
+	} while (flag & WL_SAMPLEDATA_MORE_DATA);
+	return err;
+}
+#endif 
+#endif /* defined(BWL_FILESYSTEM_SUPPORT) */
+
+static int
+wl_sample_collect(void *wl, cmd_t *cmd, char **argv)
+{
+#if !defined(BWL_FILESYSTEM_SUPPORT)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return (-1);
+#elif defined(DONGLEBUILD)
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd); UNUSED_PARAMETER(argv);
+	return 0;
+#else
+	int ret = -1;
+	uint8 *buff = NULL;
+	wl_samplecollect_args_t collect;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint32 phyrev;
+	const char *fname = "sample_collect.dat";
+	FILE *fp = NULL;
+
+	/* Default setting for sampledata_version */
+	int sampledata_version = htol16(WL_SAMPLEDATA_T_VERSION);
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	if ((ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+		return ret;
+
+	phytype = dtoh32(revinfo.phytype);
+	phyrev = dtoh32(revinfo.phyrev);
+
+	/* Assign some default params first */
+	/* 60us is roughly the max we can store (for NPHY with NREV < 7). */
+	collect.coll_us = 60;
+	collect.cores = -1;
+	collect.bitStart = -1;
+	/* extended settings */
+	collect.trigger = TRIGGER_NOW;
+	collect.mode = 1;
+	collect.post_dur = 10;
+	collect.pre_dur = 10;
+	collect.gpio_sel = 0;
+	collect.gpioCapMask = (uint32)-1;
+	collect.downsamp = FALSE;
+	collect.be_deaf = FALSE;
+	collect.timeout = 1000;
+	collect.agc = FALSE;
+	collect.filter = FALSE;
+	collect.trigger_state = 0;
+	collect.module_sel1 = 2;
+	collect.module_sel2 = 6;
+	collect.nsamps = 2048;
+	collect.version = WL_SAMPLECOLLECT_T_VERSION;
+	collect.length = sizeof(wl_samplecollect_args_t);
+
+	/* Skip the command name */
+	argv++;
+	ret = -1;
+	while (*argv) {
+		char *s = *argv;
+
+		if (argv[1] == NULL) {
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		if (!strcmp(s, "-f")) {
+			fname = argv[1];
+		} else if (!strcmp(s, "-u"))
+			collect.coll_us = atoi(argv[1]);
+		else if (!strcmp(s, "-c"))
+			collect.cores = atoi(argv[1]);
+		/* extended settings */
+		else if (!strcmp(s, "-t")) {
+			/* event trigger */
+			if (!strcmp(argv[1], "crs"))
+				collect.trigger = TRIGGER_CRS;
+			else if (!strcmp(argv[1], "crs_deassert"))
+				collect.trigger = TRIGGER_CRSDEASSERT;
+			else if (!strcmp(argv[1], "good_fcs"))
+				collect.trigger = TRIGGER_GOODFCS;
+			else if (!strcmp(argv[1], "bad_fcs"))
+				collect.trigger = TRIGGER_BADFCS;
+			else if (!strcmp(argv[1], "bad_plcp"))
+				collect.trigger = TRIGGER_BADPLCP;
+			else if (!strcmp(argv[1], "crs_glitch"))
+				collect.trigger = TRIGGER_CRSGLITCH;
+		}
+		else if (!strcmp(s, "-m")) {
+			if (!strcmp(argv[1], "gpio")) {
+				if (phytype == WLC_PHY_TYPE_HT) {
+					collect.mode = 4;
+				} else {
+					/* MIMOPHY */
+					collect.mode = 0xff;
+				}
+			} else {
+			collect.mode = atoi(argv[1]);
+			}
+		}
+		else if (!strcmp(s, "-k"))
+			collect.gpioCapMask = atoi(argv[1]);
+		else if (!strcmp(s, "-s"))
+			collect.bitStart = atoi(argv[1]);
+		else if (!strcmp(s, "-b"))
+			collect.pre_dur = atoi(argv[1]);
+		else if (!strcmp(s, "-a"))
+			collect.post_dur = atoi(argv[1]);
+		else if (!strcmp(s, "-g"))
+			collect.gpio_sel = atoi(argv[1]);
+		else if (!strcmp(s, "-d"))
+			collect.downsamp = atoi(argv[1]);
+		else if (!strcmp(s, "-e"))
+			collect.be_deaf = atoi(argv[1]);
+		else if (!strcmp(s, "-i"))
+			collect.timeout = atoi(argv[1]);
+		else if (!strcmp(s, "--agc")) {
+			/* perform software agc for sample collect */
+			collect.agc = atoi(argv[1]);
+		}
+		else if (!strcmp(s, "--filter")) {
+			/* Set HPC for LPF to lowest possible value (0x1) */
+			collect.filter = atoi(argv[1]);
+		}
+		else if (!strcmp(s, "-v"))
+			 sampledata_version = atoi(argv[1]);
+		else if (!strcmp(s, "-s"))
+			collect.trigger_state = atoi(argv[1]);
+		else if (!strcmp(s, "-x"))
+			collect.module_sel1 = atoi(argv[1]);
+		else if (!strcmp(s, "-y"))
+			collect.module_sel2 = atoi(argv[1]);
+		else if (!strcmp(s, "-n"))
+			collect.nsamps = atoi(argv[1]);
+		else {
+			ret = BCME_USAGE_ERROR;
+			goto exit;
+		}
+
+		argv += 2;
+	}
+
+	buff = malloc(WLC_SAMPLECOLLECT_MAXLEN);
+	if (buff == NULL) {
+		fprintf(stderr, "Failed to allocate dump buffer of %d bytes\n",
+			WLC_SAMPLECOLLECT_MAXLEN);
+		return BCME_NOMEM;
+	}
+	memset(buff, 0, WLC_SAMPLECOLLECT_MAXLEN);
+
+	if ((fp = fopen(fname, "wb")) == NULL) {
+		fprintf(stderr, "Problem opening file %s\n", fname);
+		ret = BCME_BADARG;
+		goto exit;
+	}
+
+	if ((phytype == WLC_PHY_TYPE_HT) || (phytype == WLC_PHY_TYPE_AC)) {
+		ret = wl_do_samplecollect(wl, &collect, sampledata_version, (uint32 *)buff, fp);
+	}
+	else if (phytype == WLC_PHY_TYPE_N) {
+		if (phyrev < 7) {
+		ret = wl_do_samplecollect_n(wl, &collect, buff, fp);
+		} else {
+			ret = wl_do_samplecollect(wl, &collect, sampledata_version,
+				(uint32 *)buff, fp);
+		}
+	} else if (phytype == WLC_PHY_TYPE_LCN40) {
+		if (collect.nsamps > (WLC_SAMPLECOLLECT_MAXLEN >> 2)) {
+			fprintf(stderr, "Max number of samples supported = %d\n",
+				WLC_SAMPLECOLLECT_MAXLEN >> 2);
+			ret = -1;
+			goto exit;
+		}
+		ret = wl_do_samplecollect_lcn40(wl, &collect, buff, fp);
+	}
+exit:
+	if (buff) free(buff);
+#ifndef ATE_BUILD
+	if (fp) fclose(fp);
+#endif
+	return ret;
+#endif /* !BWL_FILESYSTEM_SUPPORT */
+}
+
+static int
+wl_test_tssi(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char* endptr = NULL;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	val = htod32(strtol(*argv, &endptr, 0));
+	if (*endptr != '\0') {
+		/* not all the value string was parsed by strtol */
+		printf("set: error parsing value \"%s\" as an integer\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	ret = wlu_iovar_getbuf(wl, cmd->name, &val, sizeof(val),
+	                      buf, WLC_IOCTL_MAXLEN);
+
+	if (ret)
+		return ret;
+
+	val = dtoh32(*(int*)buf);
+
+	wl_printint(val);
+
+	return ret;
+}
+
+static int
+wl_test_tssi_offs(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char* endptr = NULL;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	val = htod32(strtol(*argv, &endptr, 0));
+	if (*endptr != '\0') {
+		/* not all the value string was parsed by strtol */
+		printf("set: error parsing value \"%s\" as an integer\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	ret = wlu_iovar_getbuf(wl, cmd->name, &val, sizeof(val),
+	                      buf, WLC_IOCTL_MAXLEN);
+
+	if (ret)
+		return ret;
+
+	val = dtoh32(*(int*)buf);
+
+	wl_printint(val);
+
+	return ret;
+}
+
+static int
+wl_test_idletssi(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	int val;
+	char* endptr = NULL;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	val = htod32(strtol(*argv, &endptr, 0));
+	if (*endptr != '\0') {
+		/* not all the value string was parsed by strtol */
+		printf("set: error parsing value \"%s\" as an integer\n", *argv);
+		return -1;
+	}
+
+	if ((ret = wlu_iovar_getbuf(wl, cmd->name, &val, sizeof(val),
+		buf, WLC_IOCTL_MAXLEN)) >= 0) {
+		val = dtoh32(*(int*)buf);
+		wl_printint(val);
+	}
+
+	return ret;
+}
+
+static int
+wl_phy_rssiant(void *wl, cmd_t *cmd, char **argv)
+{
+	uint32 antindex;
+	int buflen, err;
+	char *param;
+	int16 antrssi;
+
+	if (!*++argv) {
+		printf(" Usage: %s antenna_index[0-3]\n", cmd->name);
+		return BCME_USAGE_ERROR;
+	}
+
+	antindex = htod32(atoi(*argv));
+
+	strcpy(buf, "nphy_rssiant");
+	buflen = strlen(buf) + 1;
+	param = (char *)(buf + buflen);
+	memcpy(param, (char*)&antindex, sizeof(antindex));
+
+	if ((err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	antindex = dtoh32(antindex);
+	antrssi = dtoh16(*(int16 *)buf);
+	printf("\nnphy_rssiant ant%d = %d\n", antindex, antrssi);
+
+	return (0);
+}
+
+static int
+wl_pkteng_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pkteng_stats_t *stats;
+	void *ptr = NULL;
+	int err, argc, opt_err;
+	uint16 *pktstats;
+	int i, j;
+	miniopt_t to;
+	uint8 gain_correct = 0;
+	const char* fn_name = "wl_pkteng_stats";
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	if (argc != 0) {
+		miniopt_init(&to, fn_name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			if (opt_err == 1) {
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			argv += to.consumed;
+
+			if (to.opt == 'g') {
+				if (!to.good_int) {
+					fprintf(stderr,
+						"%s: could not parse \"%s\" as an int"
+						" for gain-correction (0, 1)\n",
+						fn_name, to.valstr);
+
+					err = BCME_BADARG;
+					goto exit;
+				}
+				if ((to.val < 0) || (to.val > 1)) {
+					fprintf(stderr, "%s: invalid gain-correction select %d"
+						" (0,1)\n", fn_name, to.val);
+					err = BCME_BADARG;
+					goto exit;
+				}
+				gain_correct = to.val & 0xf;
+			}
+		}
+	}
+
+	if ((err = wlu_var_getbuf_sm(wl, cmd->name, &gain_correct, 1, &ptr)) < 0)
+		return err;
+
+	stats = ptr;
+	printf("Lost frame count %d\n", dtoh32(stats->lostfrmcnt));
+	printf("RSSI %d\n", dtoh32(stats->rssi));
+	printf("Signal to noise ratio %d\n", dtoh32(stats->snr));
+	printf("rx1mbps %d rx2mbps %d rx5mbps5 %d\n"
+		"rx6mbps %d rx9mbps %d, rx11mbps %d\n"
+		"rx12mbps %d rx18mbps %d rx24mbps %d\n"
+		"rx36mbps %d rx48mbps %d rx54mbps %d\n",
+		stats->rxpktcnt[3], stats->rxpktcnt[1], stats->rxpktcnt[2],
+		stats->rxpktcnt[7], stats->rxpktcnt[11], stats->rxpktcnt[0],
+		stats->rxpktcnt[6], stats->rxpktcnt[10], stats->rxpktcnt[5],
+		stats->rxpktcnt[9], stats->rxpktcnt[4], stats->rxpktcnt[8]);
+	pktstats = &stats->rxpktcnt[NUM_80211b_RATES+NUM_80211ag_RATES];
+	for (i = 0; i < NUM_80211n_RATES/4; i++) {
+		for (j = 0; j < 4; j++) {
+			printf("rxmcs%d %d ", j+4*i, pktstats[j+4*i]);
+		}
+		printf("\n");
+	}
+	printf("rxmcsother %d\n", stats->rxpktcnt[NUM_80211_RATES]);
+	return 0;
+
+exit:
+	return err;
+}
+
+static int
+wl_pkteng_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int status = 0;
+
+	BCM_REFERENCE(argv);
+	if ((err = wlu_iovar_get(wl, cmd->name, &status, sizeof(status))) < 0) {
+		return err;
+	}
+
+	printf("pkteng_status : %d \n", status);
+	return 0;
+}
+
+#define LPPHY_PAPD_EPS_TBL_SIZE 64
+static int
+wl_phy_papdepstbl(void *wl, cmd_t *cmd, char **argv)
+{
+	int32 eps_real, eps_imag;
+	int i;
+	uint32 eps_tbl[LPPHY_PAPD_EPS_TBL_SIZE];
+	int err;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((err = wlu_iovar_get(wl, cmd->name, &eps_tbl, sizeof(eps_tbl))) < 0)
+		return err;
+
+	for (i = 0; i < LPPHY_PAPD_EPS_TBL_SIZE; i++) {
+		if ((eps_real = (int32)(eps_tbl[i] >> 12)) > 0x7ff)
+				eps_real -= 0x1000; /* Sign extend */
+		if ((eps_imag = (int32)(eps_tbl[i] & 0xfff)) > 0x7ff)
+				eps_imag -= 0x1000; /* Sign extend */
+		printf("%d %d\n", eps_real, eps_imag);
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_txiqcc(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err;
+	int32 iqccValues[4];
+	int32 value;
+	char *endptr;
+	int32 a, b, a1, b1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	if ((err = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+		return err;
+
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_N) {
+		if (!*++argv) {
+			if ((err = wlu_iovar_get(wl, cmd->name, iqccValues, 2*sizeof(int32))) < 0)
+				return err;
+			a = (int16)iqccValues[0];
+			b = (int16)iqccValues[1];
+			/* sign extend a, b from 10 bit signed value to 32 bit signed value */
+			a = ((a << 22) >> 22);
+			b = ((b << 22) >> 22);
+			printf("%d  %d\n", a, b);
+		}
+		else
+		{
+			for (i = 0; i < 2; i++) {
+				value = strtol(*argv++, &endptr, 0);
+				if (value > 511 || value < -512) {
+					return BCME_BADARG;
+				}
+				iqccValues[i] = value;
+			}
+
+		if ((err = wlu_var_setbuf(wl, cmd->name, iqccValues, 2*sizeof(int32))) < 0)
+			return err;
+		}
+	} else {
+		if (!*++argv) {
+			if ((err = wlu_iovar_get(wl, cmd->name, iqccValues, 4*sizeof(int32))) < 0)
+				return err;
+			a = (int16)iqccValues[0];
+			b = (int16)iqccValues[1];
+			a1 = (int16)iqccValues[2];
+			b1 = (int16)iqccValues[3];
+			/* sign extend a, b from 10 bit signed value to 32 bit signed value */
+			a = ((a << 22) >> 22);
+			b = ((b << 22) >> 22);
+			a1 = ((a1 << 22) >> 22);
+			b1 = ((b1 << 22) >> 22);
+			printf("%d  %d  %d  %d\n", a, b, a1, b1);
+		}
+		else
+		{
+			for (i = 0; i < 4; i++) {
+				value = strtol(*argv++, &endptr, 0);
+				if (value > 511 || value < -512) {
+					return BCME_BADARG;
+				}
+				iqccValues[i] = value;
+			}
+
+			if ((err = wlu_var_setbuf(wl, cmd->name, iqccValues, 4*sizeof(int32))) < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_txlocc(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err;
+	int8 loccValues[12];
+	int32 value;
+	char *endptr;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	if ((err = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+		return err;
+
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_N) {
+		if (!*++argv) {
+			if ((err = wlu_iovar_get(wl, cmd->name, loccValues,
+				sizeof(loccValues))) < 0)
+				return err;
+
+			/* sign extend the loccValues */
+			loccValues[2] = (loccValues[2] << 3) >> 3;
+			loccValues[3] = (loccValues[3] << 3) >> 3;
+			loccValues[4] = (loccValues[4] << 3) >> 3;
+			loccValues[5] = (loccValues[5] << 3) >> 3;
+
+			printf("%d  %d  %d  %d  %d  %d\n", loccValues[0],
+				loccValues[1], loccValues[2], loccValues[3],
+				loccValues[4], loccValues[5]);
+		}
+		else
+		{
+			for (i = 0; i < 6; i++) {
+				value = strtol(*argv++, &endptr, 0);
+				if ((i >= 2) && (value > 15 || value < -15)) {
+					return BCME_BADARG;
+				}
+				loccValues[i] = (int8)value;
+			}
+
+			if ((err = wlu_var_setbuf(wl, cmd->name, loccValues, 6*sizeof(int8))) < 0)
+				return err;
+		}
+	} else {
+		if (!*++argv) {
+			if ((err = wlu_iovar_get(wl, cmd->name, loccValues,
+				sizeof(loccValues))) < 0)
+				return err;
+
+			/* sign extend the loccValues */
+			loccValues[2] = (loccValues[2] << 3) >> 3;
+			loccValues[3] = (loccValues[3] << 3) >> 3;
+			loccValues[4] = (loccValues[4] << 3) >> 3;
+			loccValues[5] = (loccValues[5] << 3) >> 3;
+			loccValues[8] = (loccValues[8] << 3) >> 3;
+			loccValues[9] = (loccValues[9] << 3) >> 3;
+			loccValues[10] = (loccValues[10] << 3) >> 3;
+			loccValues[11] = (loccValues[11] << 3) >> 3;
+
+			printf("%d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d  %d\n", loccValues[0],
+				loccValues[1], loccValues[2], loccValues[3], loccValues[4],
+				loccValues[5], loccValues[6], loccValues[7], loccValues[8],
+				loccValues[9], loccValues[10], loccValues[11]);
+		}
+		else
+		{
+			for (i = 0; i < 12; i++) {
+				value = strtol(*argv++, &endptr, 0);
+				if (((i < 2) && (value > 63 || value < -64)) ||
+					((i >= 2) && (value > 15 || value < -15))) {
+					return BCME_BADARG;
+				}
+				loccValues[i] = (int8)value;
+			}
+
+			if ((err = wlu_var_setbuf(wl, cmd->name, loccValues, 12*sizeof(int8))) < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static int
+wl_rssi_cal_freq_grp_2g(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	uint8 nvramValues[14];
+	char *endptr;
+	uint8 N = 0;
+
+	if (!*++argv) {
+		/* Reading the NVRAM variable */
+		if ((err = wlu_iovar_get(wl, cmd->name, nvramValues, sizeof(nvramValues))) < 0)
+			return err;
+
+		N = 14; /* 14 corresponds to number of channels in 2g */
+
+		for (i = 0; i < N-2; i++) {
+			printf("0x%x%x,", nvramValues[i], nvramValues[i+1]);
+			i++;
+		}
+		printf("0x%x%x\n", nvramValues[i], nvramValues[i+1]);
+	} else {
+		/* Writing to NVRAM variable */
+
+		char *splt;
+		int8 tmp;
+		splt = strtok(*argv, ",");
+
+		/* N = 14 corresponds to number of channels in 2g */
+		/* N = N /2 to package 2 channel's nibbles into 1 byte */
+		N = 7;
+
+		i = 0;
+		while (splt != NULL) {
+			/* Splitting the input based on charecter ','
+			 * Further each byte is divided into 2 nibbles
+			 * and saved into 2 elements of array.
+			 */
+			tmp = strtol(splt, &endptr, 0);
+			nvramValues[i] = (tmp >> 4) & 0xf;
+			i++;
+			nvramValues[i] = tmp & 0xf;
+			splt = strtok(NULL, ",");
+			i++;
+		}
+		if (i != 14) {
+			printf("Insufficient arguments \n");
+			return BCME_BADARG;
+		}
+		if ((err = wlu_var_setbuf(wl, cmd->name, nvramValues, N*2*sizeof(int8))) < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_rssi_gain_delta_2g_sub(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	int8 deltaValues[28];
+	int32 value;
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint8 N = 0;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+			N = 27; /* 9 entries per core, 43602WLCSP - 27 MAX entried;
+					 * 4350 - 18 MAX entries; 4345 9 MAX entries
+					 */
+			for (i = 0; i < N; i++) {
+			if (i%9 == 0 && i > 0) {
+				printf("\n");
+				if (deltaValues[i] == -1) break;
+			}
+
+				printf("%d ", deltaValues[i]);
+		}
+		if (i == N)
+			printf("\n");
+	} else {
+		int argc = 0;
+		int index = 0;
+		while (argv[argc])
+			argc++;
+
+		/* ACPHY : 8/9 entries for a core; core 0 delta's can be
+		 * given with or with out core_num as first element
+		 */
+		N = argc;
+
+		if (!(N == 9 || N == 8 || N == 16 || N == 24)) {
+		  printf("Incorrect number of arguments.\n");
+		  return 0;
+		}
+
+		for (i = 0; i < N; i++) {
+			value = strtol(*argv++, &endptr, 0);
+			if ((value > 63 || value < -64)) {
+				return BCME_BADARG;
+			}
+			if (argc == 9) {
+				/* If number of arguments is 9, then core
+				 * number has been provided.
+				 * And 8 elements related to 2
+				 * (BWs - 20 n 40) and 4 gain settings
+				 * (elna_on, elna_off, rout_1, rout_2) are
+				 * provided. So, 2 * 4 = 8 + 1 core_num = 9
+				 */
+				deltaValues[i] = (int8)value;
+			} else {
+				/* If the number of elements is not eq to 9,
+				 * then, core number was not provided.
+				 * So, if only 8 elements are provided, only
+				 * core 0's info is given. So, for i = 0,
+				 * deltaValues element is 0 (core_num). If 16
+				 * elements are provided, then core 0 and 1's info is
+				 * provided. So, i =0 element has core_num = 0,
+				 * then, next 8 elements are core 0's
+				 * deltas. For i = 8, core 1's core_num = 1
+				 * is inserted into deltaValues array.
+				 * Similarly for third core data.
+				 */
+				if (i == 0) {
+					deltaValues[index] = 0;
+					index++;
+				} else if (i == 8) {
+					deltaValues[index] = 1;
+					index++;
+				} else if (i == 16) {
+					deltaValues[index] = 2;
+					index++;
+				}
+				deltaValues[index] = (int8)value;
+				index++;
+			}
+		}
+		/* If argc == 8, then only 1 core's info was given,
+		 * so, setbuf() is called once.
+		 * If argc == 16 then core 0 and 1's info was given.
+		 * So, setbuf() is called twice.
+		 * If argc == 24 then core 0, 1 and 2's info was given.
+		 * So, setbuf() is called thrice.
+		 */
+		if ((err = wlu_var_setbuf(wl, cmd->name,
+		     deltaValues, 9*sizeof(int8))) < 0)
+			return err;
+		if (argc >= 16) {
+			if ((err = wlu_var_setbuf(wl, cmd->name,
+			      deltaValues + 9, 9*sizeof(int8))) < 0)
+				return err;
+		}
+		if (argc == 24) {
+			if ((err = wlu_var_setbuf(wl, cmd->name,
+			     deltaValues + 18, 9*sizeof(int8))) < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_rssi_gain_delta_2g(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	int8 deltaValues[18];
+	int32 value;
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint8 N = 0;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+		if (phytype == WLC_PHY_TYPE_AC)
+			N = 15; /* ACPHY: 3 cores max x 5 entries */
+		for (i = 0; i < N; i++) {
+			if ((phytype == WLC_PHY_TYPE_AC) && (i%5 == 0)) {
+				if (i > 0) printf("\n");
+				if (deltaValues[i] == -1) break;
+			}
+			printf("%d ", deltaValues[i]);
+		}
+		if (i == N)
+			printf("\n");
+	} else {
+		int argc = 0;
+		int index = 0;
+		while (argv[argc])
+			argc++;
+		if (phytype == WLC_PHY_TYPE_AC) {
+			/* N = 5;  ACPHY : 5 entries for a core */
+			N = argc;
+		}
+
+		for (i = 0; i < N; i++) {
+			value = strtol(*argv++, &endptr, 0);
+			if ((value > 63 || value < -64)) {
+				return BCME_BADARG;
+			}
+			if (argc == 5) {
+				/* If number of arguments is 5, then core number has been provided.
+				 * And 8 elements related to 2 (BWs - 20 n 40) and 2 gain settings
+				 * (elna_on, elna_off) are provided. So, 2 * 2 = 4 + 1 core_num = 5
+				 */
+				deltaValues[i] = (int8)value;
+			} else {
+				/* If the number of elements is not eq to 5,
+				 * then, core number was not provided.
+				 * So, if only 4 elements are provided, only
+				 * core 0's info is given. So, for i = 0,
+				 * deltaValues element is 0 (core_num). If 8
+				 * elements are provided, then core 0 and 1's info is
+				 * provided. So, i =0 element has core_num = 0,
+				 * then, next 4 elements are core 0's
+				 * deltas. For i = 4, core 1's core_num = 1
+				 * is inserted into deltaValues array.
+				 * Similarly for third core data.
+				 */
+				if (i == 0) {
+					deltaValues[index] = 0;
+					index++;
+				} else if (i == 4) {
+					deltaValues[index] = 1;
+					index++;
+				} else if (i == 8) {
+					deltaValues[index] = 2;
+					index++;
+				}
+				deltaValues[index] = (int8)value;
+				index++;
+			}
+
+		}
+		/* If argc == 4, then only 1 core's info was given,
+		 * so, setbuf() is called once.
+		 * If argc == 8 then core 0 and 1's info was given.
+		 * So, setbuf() is called twice.
+		 * If argc == 12 then core 0, 1 and 2's info was given.
+		 * So, setbuf() is called thrice.
+		 */
+		if ((err = wlu_var_setbuf(wl, cmd->name,
+		     deltaValues, 5*sizeof(int8))) < 0)
+			return err;
+		if (argc >= 8) {
+			if ((err = wlu_var_setbuf(wl, cmd->name,
+			     deltaValues + 5, 5*sizeof(int8))) < 0)
+				return err;
+		}
+		if (argc == 12) {
+			if ((err = wlu_var_setbuf(wl, cmd->name,
+			     deltaValues + 10, 5*sizeof(int8))) < 0)
+				return err;
+		}
+
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_rssi_gain_delta_5g(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	int8 deltaValues[40];
+	int32 value = 0;
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint8 N = 0, n_per_core, n_per_core_p1;
+
+	char *varname = "rssi_cal_rev";
+
+	err = wlu_iovar_getint(wl, varname, &value);
+	if ((err < 0) || ((err == 0) && (value == 0))) {
+		/* This means, 'rssi_cal_rev' is not supported or Variable is 0 */
+		/* Calls old function */
+		n_per_core = 6;
+	} else {
+		n_per_core = 12;
+	}
+
+	n_per_core_p1 = n_per_core  + 1;
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+		if (phytype == WLC_PHY_TYPE_AC)
+			N = n_per_core_p1 * 3; /* ACPHY: 3 cores max x 7 entries */
+		for (i = 0; i < N; i++) {
+			if ((phytype == WLC_PHY_TYPE_AC) && (i%n_per_core_p1 == 0)) {
+				if (i > 0) printf("\n");
+				if (deltaValues[i] == -1) break;
+			}
+			printf("%d ", deltaValues[i]);
+		}
+		if (i == N)
+			printf("\n");
+	} else {
+		int argc = 0;
+		int index = 0;
+		while (argv[argc])
+			argc++;
+
+		if (phytype == WLC_PHY_TYPE_AC) {
+		        /* N = 7; ACPHY : 7 entries for a core if n_per_core == 6 */
+		        /* N = 13; ACPHY : 12 entries for a core if n_per_core == 12 */
+			N = argc;
+		}
+
+		if ((n_per_core == 12) && !(N == 13 || N == 12 || N == 24 || N == 36)) {
+		  printf("Incorrect number of arguments\n");
+		  return 0;
+		}
+
+		for (i = 0; i < N; i++) {
+			value = strtol(*argv++, &endptr, 0);
+			if ((value > 63 || value < -64)) {
+				return BCME_BADARG;
+			}
+			if (argc == n_per_core_p1) {
+				/* For Old implementation, ie, no Routs, n_per_core_p1 == 5
+				 * for New implementation, ie, no Routs, n_per_core_p1 == 9
+				 * If number of arguments is "n_per_core_p1",
+				 * then core number has been provided.
+				 */
+				deltaValues[i] = (int8)value;
+			} else  {
+				/* If the number of elements is not eq to
+				 *"n_per_core", then, core number was not provided.
+				 * So, if only "n_per_core" elements are provided,
+				 * only core 0's info is given. So, for i = 0,
+				 * deltaValues element is 0 (core_num). If "n_per_core * 2"
+				 * elements are provided, then core 0 and 1's info is
+				 * provided. So, i =0 element has core_num = 0, then,
+				 * next "n_per_core" elements are core 0's
+				 * deltas. For i = "n_per_core", core 1's
+				 * core_num = 1 is inserted into deltaValues array.
+				 * Similarly for third core data.
+				 */
+
+				if (i == (n_per_core * 0)) {
+					deltaValues[index] = 0;
+					index++;
+				}
+				if (i == (n_per_core * 1)) {
+					deltaValues[index] = 1;
+					index++;
+				}
+				if (i == (n_per_core * 2)) {
+					deltaValues[index] = 2;
+					index++;
+				}
+
+				deltaValues[index] = (int8)value;
+				index++;
+			}
+
+		}
+		/* If argc == "n_per_core", then only 1 core's infoxs
+		 * was given, so, setbuf() is called once.
+		 * If argc == "n_per_core * 2" then core 0 and 1's info
+		 * was given. So, setbuf() is called twice.
+		 * If argc == "n_per_core * 3" then core 0, 1 and 2's
+		 * info was given. So, setbuf() is called thrice.
+		 */
+		if ((err = wlu_var_setbuf(wl, cmd->name, deltaValues,
+		      n_per_core_p1*sizeof(int8))) < 0)
+			return err;
+		if (argc >= (n_per_core * 2)) {
+			if ((err = wlu_var_setbuf(wl, cmd->name, deltaValues +
+			     (n_per_core_p1 * 1), n_per_core_p1*sizeof(int8))) < 0)
+				return err;
+		}
+		if (argc == (n_per_core * 3)) {
+			if ((err = wlu_var_setbuf(wl, cmd->name, deltaValues +
+			     (n_per_core_p1 * 2), n_per_core_p1*sizeof(int8))) < 0)
+				return err;
+		}
+
+	}
+	return 0;
+}
+
+static int
+wl_phy_rxgainerr_2g(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	int8 deltaValues[18];
+	int32 value;
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint8 N = 0;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+		if (phytype == WLC_PHY_TYPE_AC) {
+			if (BCM4365_CHIP(dtoh32(revinfo.chipnum)))
+				N = 4;
+			else
+				N = 2;
+		}
+		for (i = 0; i < N; i++) {
+			printf("%d ", deltaValues[i]);
+		}
+		if (i == N)
+			printf("\n");
+	} else {
+		int argc = 0;
+		while (argv[argc])
+			argc++;
+
+		if (BCM4365_CHIP(dtoh32(revinfo.chipnum))) {
+			if (argc != 4) {
+				printf("IOVAR works only for 4 cores scenario. \n");
+				return err;
+			}
+		} else {
+			if (argc != 2) {
+				printf("IOVAR works only for 2 cores scenario. \n");
+				return err;
+			}
+		}
+
+		if (phytype == WLC_PHY_TYPE_AC) {
+			if (BCM4365_CHIP(dtoh32(revinfo.chipnum)))
+				N = 4;
+			else
+				N = 2;
+		}
+		for (i = 0; i < N; i++) {
+			value = strtol(*argv++, &endptr, 0);
+			if ((value > 63 || value < -64)) {
+				return BCME_BADARG;
+			}
+			deltaValues[i] = (int8)value;
+		}
+		if ((err = wlu_var_setbuf(wl, cmd->name, deltaValues, N*sizeof(int8))) < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_rxgainerr_5g(void *wl, cmd_t *cmd, char **argv)
+{
+	int i;
+	int err = -1;
+	int8 deltaValues[28];
+	int32 value;
+	char *endptr;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+	uint8 N = 0;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+		if (phytype == WLC_PHY_TYPE_AC) {
+			if (BCM4365_CHIP(dtoh32(revinfo.chipnum)))
+				N = 4;
+			else
+				N = 2;
+		}
+
+		for (i = 0; i < N; i++) {
+			printf("%d ", deltaValues[i]);
+		}
+		if (i == N)
+			printf("\n");
+	} else {
+		int argc = 0;
+		while (argv[argc])
+			argc++;
+		if (BCM4365_CHIP(dtoh32(revinfo.chipnum))) {
+			if (argc != 4) {
+				printf("IOVAR works only for 4 cores scenario. \n");
+				return err;
+			}
+		} else {
+			if (argc != 2) {
+				printf("IOVAR works only for 2 cores scenario. \n");
+				return err;
+			}
+		}
+		if (phytype == WLC_PHY_TYPE_AC) {
+			if (BCM4365_CHIP(dtoh32(revinfo.chipnum)))
+				N = 4;
+			else
+				N = 2;
+		}
+
+		for (i = 0; i < N; i++) {
+			value = strtol(*argv++, &endptr, 0);
+			if ((value > 63 || value < -64)) {
+				return BCME_BADARG;
+			}
+			deltaValues[i] = (int8)value;
+		}
+		if ((err = wlu_var_setbuf(wl, cmd->name, deltaValues, sizeof(deltaValues))) < 0)
+			return err;
+	}
+	return 0;
+}
+
+static int
+wl_phytable(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint32 tableInfo[5];
+	char *endptr;
+	void *ptr = NULL;
+	int32 tableId, tableOffset, tableWidth;
+	uint64 tableElement;
+
+	if (*++argv != NULL)
+		tableId = strtol(*argv, &endptr, 0);
+	else
+		return BCME_USAGE_ERROR;
+
+	if (*++argv != NULL)
+		tableOffset = strtol(*argv, &endptr, 0);
+	else
+		return BCME_USAGE_ERROR;
+
+	if (*++argv != NULL)
+		tableWidth = strtol(*argv, &endptr, 0);
+	else
+		return BCME_USAGE_ERROR;
+
+	if ((tableId < 0) || (tableOffset < 0))
+		return BCME_BADARG;
+
+	if ((tableWidth != 8) && (tableWidth != 16) && (tableWidth != 32) &&
+		(tableWidth != 48) && (tableWidth != 64))
+		return BCME_BADARG;
+
+	if (!*++argv) { /* wl utility reads a PHY table element */
+		tableInfo[0] = tableId;
+		tableInfo[1] = tableOffset;
+		tableInfo[2] = tableWidth;
+
+		if ((err = wlu_var_getbuf(wl, cmd->name, tableInfo, 4*sizeof(int32), &ptr)) < 0)
+			return err;
+
+		tableElement = ((uint64*)ptr)[0]; /* ptr is guaranteed to be 64 bits aligned */
+
+		/* Mask out the correct data */
+		if (tableWidth == 8)
+			tableElement &= 0xFF;
+		else if (tableWidth == 16)
+			tableElement &= 0xFFFF;
+		else if (tableWidth == 32)
+			tableElement &= 0xFFFFFFFF;
+		else if (tableWidth == 48)
+			tableElement &= 0xFFFFFFFFFFFFULL;
+
+		printf("0x%llx(%lld)\n", tableElement, tableElement);
+	} else { /* wl utility writes a PHY table element */
+		tableElement = bcm_strtoull(*argv++, &endptr, 0);
+
+		tableInfo[0] = tableId;
+		tableInfo[1] = tableOffset;
+		tableInfo[2] = tableWidth;
+		htol64_ua_store(tableElement, &tableInfo[3]);
+
+		if ((err = wlu_var_setbuf(wl, cmd->name, tableInfo, 5 * sizeof(int32))) < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_force_crsmin(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	int8 th[4] = { 0 };
+	int32 value;
+	uint argc = 0;
+	char *endptr;
+	uint8 i = 0;
+	int ret = -1;
+	wlc_rev_info_t revinfo;
+	uint32 phytype;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
+	if (ret) {
+		return ret;
+	}
+	phytype = dtoh32(revinfo.phytype);
+
+	if (phytype != WLC_PHY_TYPE_AC) {
+		return err;
+	}
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argc == 0) {
+		/* No get for now */
+		return err;
+	} else {
+		if (argc > 3) {
+			printf("IOVAR works only for up to 3 cores. \n");
+			return err;
+		}
+		for (i = 0; i < argc; i++) {
+			value = strtol(argv[i + 1], &endptr, 0);
+			if ((i == 0) && (value < -1)) {
+				/* Offset values (2nd/3rd arguments) can be negative */
+				return BCME_BADARG;
+			}
+			th[i] = (int8) value;
+		}
+		if ((err = wlu_var_setbuf(wl, cmd->name, th, 4*sizeof(int8))) < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int
+wl_phy_txpwrindex(void *wl, cmd_t *cmd, char **argv)
+{
+	uint i;
+	int ret;
+	uint32 txpwridx[4] = { 0 };
+	int8 idx[4] = { 0 };
+	uint argc;
+	char *endptr;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	for (i = 0; i < 4; i++) {
+		if (argc > i) {
+			txpwridx[i] = strtol(argv[1 + i], &endptr, 0);
+			if (*endptr != '\0') {
+				printf("error\n");
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	if (argc == 0) {
+		if ((ret = wlu_iovar_getint(wl, cmd->name, (int*)&txpwridx[0])) < 0) {
+			return (ret);
+		}
+		txpwridx[0] = dtoh32(txpwridx[0]);
+		idx[0] = (int8)(txpwridx[0] & 0xff);
+		idx[1] = (int8)((txpwridx[0] >> 8) & 0xff);
+		idx[2] = (int8)((txpwridx[0] >> 16) & 0xff);
+		idx[3] = (int8)((txpwridx[0] >> 24) & 0xff);
+		printf("txpwrindex for core{0...3}: %d %d %d %d\n", idx[0], idx[1],
+		       idx[2], idx[3]);
+	} else {
+		wlc_rev_info_t revinfo;
+		uint32 phytype;
+
+		memset(&revinfo, 0, sizeof(revinfo));
+		if ((ret = wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo))) < 0)
+			return ret;
+
+		phytype = dtoh32(revinfo.phytype);
+
+		if (phytype == WLC_PHY_TYPE_HT) {
+			if (argc != 3) {
+				printf("HTPHY must specify 3 core txpwrindex\n");
+				return BCME_USAGE_ERROR;
+			}
+		} else if (phytype == WLC_PHY_TYPE_N) {
+			if (argc != 2) {
+				printf("NPHY must specify 2 core txpwrindex\n");
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		ret = wlu_iovar_setbuf(wl, cmd->name, txpwridx, 4*sizeof(uint32),
+			buf, WLC_IOCTL_MAXLEN);
+	}
+
+	return ret;
+}
+
+static int
+wl_phy_force_vsdb_chans(void *wl, cmd_t *cmd, char **argv)
+{
+	uint16 *chans = NULL;
+	int ret = 0;
+	void	*ptr;
+
+	UNUSED_PARAMETER(wl); UNUSED_PARAMETER(cmd);
+
+
+	if (argv[1] == NULL) {
+		if ((ret = wlu_var_getbuf(wl, "force_vsdb_chans", NULL, 0, &ptr) < 0)) {
+				printf("wl_phy_maxpower: fail to get maxpower\n");
+				return ret;
+		}
+		chans = (uint16*)ptr;
+		printf("Chans : %x %x \n", chans[0], chans[1]);
+	} else if (argv[1] && argv[2]) {
+		/* Allocate memory */
+		chans = (uint16*)malloc(2 * sizeof(uint16));
+		if (chans == NULL) {
+			printf("unable to allocate Memory \n");
+			return BCME_NOMEM;
+		}
+		chans[0]  = wf_chspec_aton(argv[1]);
+		chans[1]  = wf_chspec_aton(argv[2]);
+		if (((chans[0] & 0xff) == 0) || ((chans[1] & 0xff) == 0)) {
+			chans[0] = 0;
+			chans[1] = 0;
+		}
+		ret = wlu_iovar_setbuf(wl, cmd->name, chans, 2 * sizeof(uint16),
+			buf, WLC_IOCTL_MAXLEN);
+		if (chans)
+			free(chans);
+	} else {
+		ret = BCME_USAGE_ERROR;
+	}
+
+	return ret;
+}
+
+static int
+wl_phy_pavars(void *wl, cmd_t *cmd, char **argv)
+{
+#if	defined(DONGLEBUILD)
+		return 0;
+#else
+		const pavars_t *pav = pavars;
+		uint16	inpa[WL_PHY_PAVARS_LEN];
+		char	*cpar = NULL, *p = NULL;
+		char	*par;
+		char	delimit[2] = " \0";
+		int err = 0;
+		unsigned int val, val2[SROM_PAVAR];
+		void	*ptr = NULL;
+		int paparambwver = 0;
+		int sromrev = 0;
+
+		const char *iovar = "nvram_dump";
+		void *p1 = NULL;
+
+		if ((err = wlu_var_getbuf(wl, iovar, NULL, 0, &p1)) < 0) {
+			if ((err = wlu_get(wl, WLC_NVRAM_DUMP, &buf[0], WLC_IOCTL_MAXLEN)) < 0)
+				return err;
+			p1 = (void *)buf;
+		}
+		if ((p1 = strstr(p1, "paparambwver"))) {
+			char *q = NULL;
+			p1 = (void*)((char*)p1 + 13);
+			paparambwver = strtoul(p1, &q, 10);
+		}
+
+		err = wlu_iovar_getint(wl, "sromrev", &sromrev);
+		if (paparambwver == 1)
+			pav = pavars_bwver_1;
+		else if (paparambwver == 2)
+			pav = pavars_bwver_2;
+		else if (paparambwver == 3)
+			pav = pavars_bwver_3;
+		else {
+		  if (sromrev > 12)
+			pav = pavars_SROM13;
+		  if (sromrev == 12)
+			pav = pavars_SROM12;
+		  if (sromrev < 12)
+			pav = pavars;
+		}
+		if (*++argv) {	/* set */
+			while (pav->phy_type != PHY_TYPE_NULL) {
+				bool found = FALSE;
+				int i = 0;
+				inpa[i++] = pav->phy_type;
+				inpa[i++] = pav->bandrange;
+				inpa[i++] = pav->chain;
+
+				par = malloc(strlen(pav->vars)+1);
+				if (!par)
+					return BCME_NOMEM;
+
+				strcpy(par, pav->vars);
+
+				cpar = strtok (par, delimit);	/* current param */
+
+				if ((pav->phy_type == PHY_TYPE_AC) ||
+						(pav->phy_type == PHY_TYPE_LCN20)) {
+				  int pnum = 0, n;
+				  if (sromrev >= 12) {
+					if ((pav->bandrange == WL_CHAN_FREQ_RANGE_2G) ||
+					   (pav->bandrange == WL_CHAN_FREQ_RANGE_2G_40))
+					  pnum = 4;
+					else if ((pav->bandrange ==
+						WL_CHAN_FREQ_RANGE_5G_5BAND) ||
+						(pav->bandrange ==
+						WL_CHAN_FREQ_RANGE_5G_5BAND_40) ||
+						(pav->bandrange ==
+						WL_CHAN_FREQ_RANGE_5G_5BAND_80))
+							pnum = 20;
+				  }
+				  if (sromrev < 12) {
+					if (pav->bandrange == WL_CHAN_FREQ_RANGE_2G)
+					  pnum = 3;
+					else if (pav->bandrange == WL_CHAN_FREQ_RANGE_5G_4BAND)
+					  pnum = 12;
+				  }
+				  if (cpar) {
+					/* Find the parameter in the input argument list */
+					if ((p = find_pattern2(argv, cpar, val2, pnum))) {
+						found = TRUE;
+						for (n = 0; n < pnum; n ++)
+							inpa[i + n] = (uint16)val2[n];
+					}
+				  }
+				} else {
+					do {
+						val = 0;
+						if (cpar == NULL) {
+							inpa[i] = val;
+							break;
+						}
+						/* Find the parameter in the input argument list */
+						if ((p = find_pattern(argv, cpar, &val))) {
+							found = TRUE;
+							inpa[i] = (uint16)val;
+						} else
+							inpa[i] = 0;
+						i++;
+					} while ((cpar = strtok (NULL, delimit)) != NULL);
+				}
+				free(par);
+
+				if (found) {
+					if ((err = wlu_var_setbuf(wl, cmd->name, inpa,
+						WL_PHY_PAVARS_LEN * sizeof(uint16))) < 0) {
+						printf("wl_phy_pavars: fail to set\n");
+						return err;
+					}
+				}
+				pav++;
+			}
+		} else {	/* get */
+			while (pav->phy_type != PHY_TYPE_NULL) {
+				int i = 0;
+				uint16	*outpa;
+
+				inpa[i++] = pav->phy_type;
+				inpa[i++] = pav->bandrange;
+				inpa[i++] = pav->chain;
+
+				par = malloc(strlen(pav->vars)+1);
+				if (!par)
+					return BCME_NOMEM;
+				strcpy(par, pav->vars);
+				if ((err = wlu_var_getbuf_sm(wl, cmd->name, inpa,
+					WL_PHY_PAVARS_LEN * sizeof(uint16), &ptr)) < 0) {
+					printf("phy %x band %x chain %d err %d\n", pav->phy_type,
+						pav->chain, pav->bandrange, err);
+					free(par);
+					break;
+				}
+
+				outpa = (uint16*)ptr;
+				if (outpa[0] == PHY_TYPE_NULL) {
+					pav++;
+					free(par);
+					continue;
+				}
+
+				cpar = strtok(par, delimit);	/* current param */
+
+				if ((pav->phy_type == PHY_TYPE_AC) ||
+						(pav->phy_type == PHY_TYPE_LCN20)) {
+				  int pnum = 0, n;
+				  if (sromrev >= 12) {
+					if ((pav->bandrange == WL_CHAN_FREQ_RANGE_2G) ||
+						(pav->bandrange == WL_CHAN_FREQ_RANGE_2G_40))
+						pnum = 4;
+					else if ((pav->bandrange ==
+						WL_CHAN_FREQ_RANGE_5G_5BAND) ||
+						(pav->bandrange ==
+						WL_CHAN_FREQ_RANGE_5G_5BAND_40) ||
+						(pav->bandrange == WL_CHAN_FREQ_RANGE_5G_5BAND_80))
+							pnum = 20;
+				  }
+				  if (sromrev < 12) {
+					if (pav->bandrange == WL_CHAN_FREQ_RANGE_2G)
+					  pnum = 3;
+					else if (pav->bandrange == WL_CHAN_FREQ_RANGE_5G_4BAND)
+					  pnum = 12;
+				  }
+				  printf("%s=", cpar);
+				  for (n = 0; n < pnum; n ++) {
+					if (n != 0)
+					  printf(",");
+					printf("0x%x", outpa[i + n]);
+				  }
+				  printf("\n");
+				} else {
+					do {
+						printf("%s=0x%x\n", cpar, outpa[i++]);
+					} while ((cpar = strtok (NULL, delimit)) != NULL);
+				}
+				pav++;
+				free(par);
+			}
+		}
+		return err;
+#endif 
+
+}
+
+static int
+wl_phy_povars(void *wl, cmd_t *cmd, char **argv)
+{
+#if	defined(DONGLEBUILD)
+	return 0;
+#else
+	const povars_t *pov = povars;
+	wl_po_t	inpo;
+	char	*cpar = NULL, *p = NULL;
+	char	*par;	/* holds longest povars->vars */
+	char	delimit[2] = " \0";
+	int	err = 0;
+	uint val;
+	void	*ptr = NULL;
+
+	if (*++argv) {	/* set */
+		while (pov->phy_type != PHY_TYPE_NULL) {
+			bool found = FALSE;
+			int i = 0;
+
+			inpo.phy_type = pov->phy_type;
+			inpo.band = pov->bandrange;
+
+			par = malloc(strlen(pov->vars)+1);
+			if (!par)
+				return BCME_NOMEM;
+
+			strcpy(par, pov->vars);
+
+			/* Take care of cck and ofdm before walking through povars->vars */
+			if (pov->bandrange == WL_CHAN_FREQ_RANGE_2G) {
+				p = find_pattern(argv, "cck2gpo", &val);
+				if (p)	found = TRUE;
+				inpo.cckpo = p ? (uint16)val : 0;
+
+				p = find_pattern(argv, "ofdm2gpo", &val);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GL) {
+				p = find_pattern(argv, "ofdm5glpo", &val);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GM) {
+				p = find_pattern(argv, "ofdm5gpo", &val);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GH) {
+				p = find_pattern(argv, "ofdm5ghpo", &val);
+			}
+			inpo.ofdmpo = p ? (uint32)val : 0;
+			if (p)	found = TRUE;
+
+			cpar = strtok (par, delimit);	/* current param */
+			do {
+				val = 0;
+				if (cpar == NULL) {
+					inpo.mcspo[i] = val;
+					break;
+				}
+
+				/* Find the parameter in the input argument list */
+				p = find_pattern(argv, cpar, &val);
+				if (p)	found = TRUE;
+				inpo.mcspo[i] = p ? (uint16)val : 0;
+				i++;
+			} while ((cpar = strtok (NULL, delimit)) != NULL);
+
+			if (found) {
+				if ((err = wlu_var_setbuf(wl, cmd->name, &inpo,
+					sizeof(wl_po_t))) < 0) {
+					printf("wl_phy_povars: fail to set\n");
+					free(par);
+					return err;
+				}
+			}
+			pov++;
+			free(par);
+		}
+	} else {	/* get */
+		while (pov->phy_type != PHY_TYPE_NULL) {
+			int i = 0;
+			wl_po_t	*outpo;
+
+			inpo.phy_type = pov->phy_type;
+			inpo.band = pov->bandrange;
+
+			par = malloc(strlen(pov->vars)+1);
+			if (!par)
+				return BCME_NOMEM;
+
+			strcpy(par, pov->vars);
+
+			if ((err = wlu_var_getbuf(wl, cmd->name, &inpo, sizeof(povars_t),
+				&ptr)) < 0) {
+				printf("phy %x band %x err %d\n", pov->phy_type,
+					pov->bandrange, err);
+				free(par);
+				break;
+			}
+
+			outpo = (wl_po_t*)ptr;
+			if (outpo->phy_type == PHY_TYPE_NULL) {
+				pov++;
+				free(par);
+				continue;
+			}
+
+			/* Take care of cck and ofdm before walking through povars->vars */
+			if (outpo->band == WL_CHAN_FREQ_RANGE_2G) {
+				printf("cck2gpo=0x%x\n", outpo->cckpo);
+				printf("ofdm2gpo=0x%x\n", outpo->ofdmpo);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GL) {
+				printf("ofdm5glpo=0x%x\n", outpo->ofdmpo);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GM) {
+				printf("ofdm5gpo=0x%x\n", outpo->ofdmpo);
+			} else if (pov->bandrange == WL_CHAN_FREQ_RANGE_5GH) {
+				printf("ofdm5ghpo=0x%x\n", outpo->ofdmpo);
+			}
+
+			cpar = strtok(par, delimit);	/* current param */
+			do {
+				printf("%s=0x%x\n", cpar, outpo->mcspo[i++]);
+			} while ((cpar = strtok (NULL, delimit)));
+
+			pov++;
+			free(par);
+		}
+	}
+
+	return err;
+#endif 
+}
+
+static int
+wl_phy_rpcalvars(void *wl, cmd_t *cmd, char **argv)
+{
+#if	defined(DONGLEBUILD)
+	return 0;
+#else
+	int    err = 0, k;
+	unsigned int val;
+	wl_rpcal_t rpcal[2*WL_NUM_RPCALVARS], *rpcal_out;
+	void *ptr = NULL;
+
+	if (*++argv) {	/* set */
+		bool found = FALSE;
+
+		/* initialization */
+		memset(&(rpcal[0]), 0, sizeof(wl_rpcal_t)*2*WL_NUM_RPCALVARS);
+
+		if (find_pattern(argv, "rpcal2g", &val)) {
+			found = TRUE;
+			rpcal[WL_CHAN_FREQ_RANGE_2G].value  = (uint16) val;
+			rpcal[WL_CHAN_FREQ_RANGE_2G].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb0", &val)) {
+			found = TRUE;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND0].value  = (uint16) val;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND0].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb1", &val)) {
+			found = TRUE;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND1].value  = (uint16) val;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND1].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb2", &val)) {
+			found = TRUE;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND2].value  = (uint16) val;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND2].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb3", &val)) {
+			found = TRUE;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND3].value  = (uint16) val;
+			rpcal[WL_CHAN_FREQ_RANGE_5G_BAND3].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal2gcore3", &val)) {
+			found = TRUE;
+			rpcal[WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_2G].value =
+			(uint16) (val & 0xff);
+			rpcal[WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_2G].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb0core3", &val)) {
+			found = TRUE;
+			rpcal[WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND0].value =
+			(uint16) (val & 0xff);
+			rpcal[WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND0].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb1core3", &val)) {
+			found = TRUE;
+			rpcal[WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND1].value =
+			(uint16) (val & 0xff);
+			rpcal[WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND1].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb2core3", &val)) {
+			found = TRUE;
+			rpcal[WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND2].value =
+			(uint16) (val & 0xff);
+			rpcal[WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND2].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal5gb3core3", &val)) {
+			found = TRUE;
+			rpcal[WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND3].value =
+			(uint16) (val & 0xff);
+			rpcal[WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND3].update = 1;
+		}
+
+		if (found) {
+			err = wlu_var_setbuf(wl, cmd->name, &(rpcal[0]),
+			                     sizeof(wl_rpcal_t)*2*WL_NUM_RPCALVARS);
+			if (err < 0) {
+				printf("wl_phy_rpcalvars: fail to set\n");
+				return err;
+			}
+		} else {
+			printf("wl_phy_rpcalvars: fail to found matching rpcalvar name\n");
+			return err;
+		}
+
+	} else {	/* get */
+
+		err = wlu_var_getbuf(wl, cmd->name, &(rpcal[0]),
+		                     sizeof(wl_rpcal_t)*2*WL_NUM_RPCALVARS, &ptr);
+
+		if (err < 0) {
+			printf("wl_phy_rpcalvars: fail to get\n");
+			return err;
+		} else {
+			rpcal_out = (wl_rpcal_t*) ptr;
+		}
+
+		for (k = 0; k < 2*WL_NUM_RPCALVARS; k++) {
+
+			switch (k) {
+			case WL_CHAN_FREQ_RANGE_2G:
+				printf("rpcal2g=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND0:
+				printf("rpcal5gb0=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND1:
+				printf("rpcal5gb1=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND2:
+				printf("rpcal5gb2=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND3:
+				printf("rpcal5gb3=0x%x\n", rpcal_out[k].value);
+				break;
+			case WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_2G:
+				printf("rpcal2gcore3=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND0:
+				printf("rpcal5gb0core3=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND1:
+				printf("rpcal5gb1core3=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND2:
+				printf("rpcal5gb2core3=0x%x ", rpcal_out[k].value);
+				break;
+			case WL_NUM_RPCALVARS+WL_CHAN_FREQ_RANGE_5G_BAND3:
+				printf("rpcal5gb3core3=0x%x\n", rpcal_out[k].value);
+				break;
+			}
+		}
+	}
+
+	return 0;
+#endif 
+}
+
+static int
+wl_phy_rpcalphasevars(void *wl, cmd_t *cmd, char **argv)
+{
+#if	defined(DONGLEBUILD)
+	return 0;
+#else
+	int    err = 0, k;
+	unsigned int val;
+	wl_rpcal_phase_t rpcal_phase[WL_NUM_RPCALPHASEVARS], *rpcal_phase_out;
+	void *ptr = NULL;
+
+	if (*++argv) {	/* set */
+		bool found = FALSE;
+
+		/* initialization */
+		memset(&(rpcal_phase[0]), 0, sizeof(wl_rpcal_phase_t)*WL_NUM_RPCALPHASEVARS);
+
+		if (find_pattern(argv, "rpcal_phase2g", &val)) {
+			found = TRUE;
+			rpcal_phase[WL_CHAN_FREQ_RANGE_2G].value  = (uint16) val;
+			rpcal_phase[WL_CHAN_FREQ_RANGE_2G].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal_phase5gb0", &val)) {
+			found = TRUE;
+			rpcal_phase[WL_CHAN_FREQ_RANGE_5G_BAND0].value  = (uint16) val;
+			rpcal_phase[WL_CHAN_FREQ_RANGE_5G_BAND0].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal_phase5gb1", &val)) {
+			found = TRUE;
+			rpcal_phase[WL_CHAN_FREQ_RANGE_5G_BAND1].value  = (uint16) val;
+			rpcal_phase[WL_CHAN_FREQ_RANGE_5G_BAND1].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal_phase5gb2", &val)) {
+			found = TRUE;
+			rpcal_phase[WL_CHAN_FREQ_RANGE_5G_BAND2].value  = (uint16) val;
+			rpcal_phase[WL_CHAN_FREQ_RANGE_5G_BAND2].update = 1;
+		}
+
+		if (find_pattern(argv, "rpcal_phase5gb3", &val)) {
+			found = TRUE;
+			rpcal_phase[WL_CHAN_FREQ_RANGE_5G_BAND3].value  = (uint16) val;
+			rpcal_phase[WL_CHAN_FREQ_RANGE_5G_BAND3].update = 1;
+		}
+
+		if (found) {
+			err = wlu_var_setbuf(wl, cmd->name, &(rpcal_phase[0]),
+			                     sizeof(wl_rpcal_phase_t)*WL_NUM_RPCALPHASEVARS);
+			if (err < 0) {
+				printf("wl_phy_rpcalphasevars: fail to set\n");
+				return err;
+			}
+		} else {
+			printf("wl_phy_rpcalphasevars: fail to found matching rpcalphase name\n");
+			return err;
+		}
+
+	} else {	/* get */
+
+		err = wlu_var_getbuf(wl, cmd->name, &(rpcal_phase[0]),
+		                     sizeof(wl_rpcal_phase_t)*WL_NUM_RPCALPHASEVARS, &ptr);
+
+		if (err < 0) {
+			printf("wl_phy_rpcalphasevars: fail to get\n");
+			return err;
+		} else {
+			rpcal_phase_out = (wl_rpcal_phase_t*) ptr;
+		}
+
+		for (k = 0; k < WL_NUM_RPCALPHASEVARS; k++) {
+
+			switch (k) {
+			case WL_CHAN_FREQ_RANGE_2G:
+				printf("rpcal_phase2g=0x%x ", rpcal_phase_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND0:
+				printf("rpcal_phase5gb0=0x%x ", rpcal_phase_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND1:
+				printf("rpcal_phase5gb1=0x%x ", rpcal_phase_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND2:
+				printf("rpcal_phase5gb2=0x%x ", rpcal_phase_out[k].value);
+				break;
+			case WL_CHAN_FREQ_RANGE_5G_BAND3:
+				printf("rpcal_phase5gb3=0x%x\n", rpcal_phase_out[k].value);
+				break;
+			}
+		}
+	}
+
+	return 0;
+#endif 
+}
+
+static int
+wl_phy_fem(void *wl, cmd_t *cmd, char **argv)
+{
+#if	defined(DONGLEBUILD)
+	return 0;
+#else
+	srom_fem_t	fem;
+	srom_fem_t	*rfem;
+	void		*ptr;
+	bool	found = FALSE;
+	int	err = 0;
+	uint	val;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {	/* write fem */
+
+		/* fem2g */
+		memset(&fem, 0, sizeof(srom_fem_t));
+
+		if (find_pattern(argv, "tssipos2g", &val)) {
+			found = TRUE;
+			fem.tssipos = val;
+		}
+
+		if (find_pattern(argv, "extpagain2g", &val)) {
+			found = TRUE;
+			fem.extpagain = val;
+		}
+
+		if (find_pattern(argv, "pdetrange2g", &val)) {
+			found = TRUE;
+			fem.pdetrange = val;
+		}
+
+		if (find_pattern(argv, "triso2g", &val)) {
+			found = TRUE;
+			fem.triso = val;
+		}
+
+		if (find_pattern(argv, "antswctl2g", &val)) {
+			found = TRUE;
+			fem.antswctrllut = val;
+		}
+
+		if (found) {
+			if ((err = wlu_var_setbuf(wl, "fem2g", &fem, sizeof(srom_fem_t)) < 0))
+				printf("wl_phy_fem: fail to set fem2g\n");
+			else
+				printf("fem2g set\n");
+		}
+
+		found = FALSE;
+		/* fem5g */
+		memset(&fem, 0, sizeof(srom_fem_t));
+
+		if (find_pattern(argv, "tssipos5g", &val)) {
+			found = TRUE;
+			fem.tssipos = val;
+		}
+
+		if (find_pattern(argv, "extpagain5g", &val)) {
+			found = TRUE;
+			fem.extpagain = val;
+		}
+
+		if (find_pattern(argv, "pdetrange5g", &val)) {
+			found = TRUE;
+			fem.pdetrange = val;
+		}
+
+		if (find_pattern(argv, "triso5g", &val)) {
+			found = TRUE;
+			fem.triso = val;
+		}
+
+		if (find_pattern(argv, "antswctl5g", &val)) {
+			found = TRUE;
+			fem.antswctrllut = val;
+		}
+
+		if (found) {
+			if ((err = wlu_var_setbuf(wl, "fem5g", &fem, sizeof(srom_fem_t)) < 0))
+				printf("wl_phy_fem: fail to set fem5g\n");
+			else
+				printf("fem5g set\n");
+		}
+	} else {
+		if ((err = wlu_var_getbuf(wl, "fem2g", NULL, 0, (void**)&ptr) < 0)) {
+			printf("wl_phy_fem: fail to get fem2g\n");
+		} else {
+			rfem = (srom_fem_t*)ptr; /* skip the "fem2g" */
+			printf("tssipos2g=0x%x extpagain2g=0x%x pdetrange2g=0x%x"
+			       " triso2g=0x%x antswctl2g=0x%x\n",
+			       rfem->tssipos, rfem->extpagain, rfem->pdetrange,
+			       rfem->triso, rfem->antswctrllut);
+	       }
+
+		if ((err = wlu_var_getbuf(wl, "fem5g", NULL, 0, (void**)&ptr) < 0)) {
+			printf("wl_phy_fem: fail to get fem5g\n");
+		} else {
+			rfem = (srom_fem_t*)ptr; /* skip the "fem2g" */
+			printf("tssipos5g=0x%x extpagain5g=0x%x pdetrange5g=0x%x"
+			       " triso5g=0x%x antswctl5g=0x%x\n",
+			       rfem->tssipos, rfem->extpagain, rfem->pdetrange,
+			       rfem->triso, rfem->antswctrllut);
+		}
+	}
+
+	return err;
+#endif 
+}
+
+static int
+wl_phy_maxpower(void *wl, cmd_t *cmd, char **argv)
+{
+#if	defined(DONGLEBUILD)
+	return 0;
+#else
+	int	err = 0;
+	uint	val;
+	uint8	maxp[8];
+	void	*ptr;
+	uint8	*rmaxp;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {	/* write maxpower */
+
+		if (find_pattern(argv, "maxp2ga0", &val))
+			maxp[0] = val;
+		else
+			printf("Missing maxp2ga0\n");
+
+		if (find_pattern(argv, "maxp2ga1", &val))
+			maxp[1] = val;
+		else
+			printf("Missing maxp2ga1\n");
+
+		if (find_pattern(argv, "maxp5ga0", &val))
+			maxp[2] = val;
+		else
+			printf("Missing maxp5ga0\n");
+
+		if (find_pattern(argv, "maxp5ga1", &val))
+			maxp[3] = val;
+		else
+			printf("Missing maxp5ga1\n");
+
+		if (find_pattern(argv, "maxp5gla0", &val))
+			maxp[4] = val;
+		else
+			printf("Missing maxp5gla0\n");
+
+		if (find_pattern(argv, "maxp5gla1", &val))
+			maxp[5] = val;
+		else
+			printf("Missing maxp5gla1\n");
+
+		if (find_pattern(argv, "maxp5gha0", &val))
+			maxp[6] = val;
+		else
+			printf("Missing maxp5gha0\n");
+
+		if (find_pattern(argv, "maxp5gha1", &val))
+			maxp[7] = val;
+		else
+			printf("Missing maxp5gha1\n");
+
+		if ((err = wlu_var_setbuf(wl, "maxpower", &maxp, 8 * sizeof(uint8)) < 0)) {
+			printf("wl_phy_maxpower: fail to set\n");
+		}
+	} else {
+		if ((err = wlu_var_getbuf(wl, "maxpower", NULL, 0, &ptr) < 0)) {
+			printf("wl_phy_maxpower: fail to get maxpower\n");
+			return err;
+		}
+		rmaxp = (uint8*)ptr;
+		printf("maxp2ga0=%x\n", rmaxp[0]);
+		printf("maxp2ga1=%x\n", rmaxp[1]);
+		printf("maxp5ga0=%x\n", rmaxp[2]);
+		printf("maxp5ga1=%x\n", rmaxp[3]);
+		printf("maxp5gla0=%x\n", rmaxp[4]);
+		printf("maxp5gla1=%x\n", rmaxp[5]);
+		printf("maxp5gha0=%x\n", rmaxp[6]);
+		printf("maxp5gha1=%x\n", rmaxp[7]);
+	}
+
+	return err;
+#endif 
+}
+
+static int
+wl_pkteng(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pkteng_t pkteng;
+
+	memset(&pkteng, 0, sizeof(pkteng));
+	if (strcmp(cmd->name, "pkteng_stop") == 0) {
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+		if (strcmp(*argv, "tx") == 0)
+			pkteng.flags = WL_PKTENG_PER_TX_STOP;
+		else if (strcmp(*argv, "rx") == 0)
+			pkteng.flags = WL_PKTENG_PER_RX_STOP;
+		else
+			return BCME_USAGE_ERROR;
+	}
+	else if (strcmp(cmd->name, "pkteng_start") == 0) {
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+		if (!wl_ether_atoe(*argv, (struct ether_addr *)&pkteng.dest))
+			return BCME_USAGE_ERROR;
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+		if ((strcmp(*argv, "tx") == 0) || (strcmp(*argv, "txwithack") == 0))  {
+			if (strcmp(*argv, "tx") == 0)
+				pkteng.flags = WL_PKTENG_PER_TX_START;
+			else
+				pkteng.flags = WL_PKTENG_PER_TX_WITH_ACK_START;
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+			if (strcmp(*argv, "async") == 0)
+				pkteng.flags &= ~(WL_PKTENG_SYNCHRONOUS |
+						WL_PKTENG_SYNCHRONOUS_UNBLK);
+			else if (strcmp(*argv, "sync") == 0)
+				pkteng.flags |= WL_PKTENG_SYNCHRONOUS;
+			else if (!strncmp(*argv, "sync_unblk", strlen("sync_unblk"))) {
+				pkteng.flags |= WL_PKTENG_SYNCHRONOUS_UNBLK;
+			}
+			else {
+				/* neither optional parameter [async|sync|sync_unblk] */
+				--argv;
+			}
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+			pkteng.delay = strtoul(*argv, NULL, 0);
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+			pkteng.length = strtoul(*argv, NULL, 0);
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+			pkteng.nframes = strtoul(*argv, NULL, 0);
+			if (*++argv)
+				if (!wl_ether_atoe(*argv, (struct ether_addr *)&pkteng.src))
+					return BCME_USAGE_ERROR;
+		}
+		else if ((strcmp(*argv, "rx") == 0) || (strcmp(*argv, "rxwithack") == 0)) {
+			if ((strcmp(*argv, "rx") == 0))
+				pkteng.flags = WL_PKTENG_PER_RX_START;
+			else
+				pkteng.flags = WL_PKTENG_PER_RX_WITH_ACK_START;
+
+			if (*++argv) {
+				if (strcmp(*argv, "async") == 0)
+					pkteng.flags &= ~WL_PKTENG_SYNCHRONOUS;
+				else if (strcmp(*argv, "sync") == 0) {
+					pkteng.flags |= WL_PKTENG_SYNCHRONOUS;
+					/* sync mode requires number of frames and timeout */
+					if (!*++argv)
+						return BCME_USAGE_ERROR;
+					pkteng.nframes = strtoul(*argv, NULL, 0);
+					if (!*++argv)
+						return BCME_USAGE_ERROR;
+					pkteng.delay = strtoul(*argv, NULL, 0);
+				}
+			}
+		}
+		else
+			return BCME_USAGE_ERROR;
+	}
+	else {
+		printf("Invalid command name %s\n", cmd->name);
+		return 0;
+	}
+
+	pkteng.flags = htod32(pkteng.flags);
+	pkteng.delay = htod32(pkteng.delay);
+	pkteng.nframes = htod32(pkteng.nframes);
+	pkteng.length = htod32(pkteng.length);
+
+	return (wlu_var_setbuf(wl, "pkteng", &pkteng, sizeof(pkteng)));
+}
+
+static uint32
+wl_rxiq_prepare(char **argv, wl_iqest_params_t *params, uint8 *resolution)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_rxiqest_prepare";
+	int err = BCME_OK, argc, opt_err;
+	uint8 lpf_hpc = 1;
+	uint8 dig_lpf = 1;
+	uint8 gain_correct = 0;
+	uint8 extra_gain_3dBsteps = 0;
+	uint8 force_gain_type = 0;
+	uint8 antenna = 3;
+
+	*resolution = 0;
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	/* DEFAULT:
+	 * gain_correct = 0 (disable gain correction),
+	 * lpf_hpc = 1 (sets lpf hpc to lowest value),
+	 * dig_lpf = 1; (sets to ltrn_lpf mode)
+	 * resolution = 0 (coarse),
+	 * samples = 1024 (2^10) and antenna = 3
+	 * force_gain_type = 0 (init gain mode)
+	 */
+	params->rxiq = (extra_gain_3dBsteps << 28) | (gain_correct << 24) | (dig_lpf << 22)
+	        | (lpf_hpc << 20) | (*resolution << 16) | (10 << 8) | (force_gain_type << 4)
+	        | antenna;
+
+	params->niter = 1;
+	params->delay = PHY_RXIQEST_AVERAGING_DELAY;
+	if (argc == 0)
+		return 0;
+
+	miniopt_init(&to, fn_name, NULL, FALSE);
+	while ((opt_err = miniopt(&to, argv)) != -1) {
+		if (opt_err == 1) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv += to.consumed;
+
+		if (to.opt == 'g') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int"
+					" for gain-correction (0, 1, 2, 3, 4, 7, 8)\n",
+					fn_name, to.valstr);
+
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if ((to.val < 0) || (to.val > 8)) {
+				fprintf(stderr, "%s: invalid gain-correction select %d"
+					" (0,1,2,3,4,7,8)\n", fn_name, to.val);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			gain_correct = to.val & 0xf;
+			params->rxiq = ((gain_correct << 24) | (params->rxiq & 0xf0ffffff));
+		}
+		if (to.opt == 'f') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int"
+					" for lpf-hpc override select (0, 1)\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if ((to.val < 0) || (to.val > 1)) {
+				fprintf(stderr, "%s: invalid lpf-hpc override select %d"
+					" (0,1)\n", fn_name, to.val);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			lpf_hpc = to.val & 0x3;
+			params->rxiq = ((lpf_hpc << 20) | (params->rxiq & 0xffcfffff));
+		}
+		if (to.opt == 'w') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int"
+					" for dig-lpf override select (0, 1 or 2)\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if ((to.val < 0) || (to.val > 2)) {
+				fprintf(stderr, "%s: invalid dig-lpf override select %d"
+					" (0,1,2)\n", fn_name, to.val);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			dig_lpf = to.val & 0x3;
+			params->rxiq = ((dig_lpf << 22) | (params->rxiq & 0xff3fffff));
+		}
+		if (to.opt == 'r') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int"
+					" for resolution (0, 1)\n", fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if ((to.val < 0) || (to.val > 1)) {
+				fprintf(stderr, "%s: invalid resolution select %d"
+					" (0,1)\n", fn_name, to.val);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			*resolution = to.val & 0xf;
+			params->rxiq = ((*resolution << 16) | (params->rxiq & 0xfff0ffff));
+		}
+		if (to.opt == 's') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for"
+					" the sample count\n", fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (to.val < 0 || to.val > 16) {
+				fprintf(stderr, "%s: sample count too large %d"
+					"(10 <= x <= 16)\n", fn_name, to.val);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->rxiq = (((to.val & 0xff) << 8) | (params->rxiq & 0xffff00ff));
+		}
+		if (to.opt == 'a') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int"
+					" for antenna (0, 1, 3)\n", fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if ((to.val < 0) || (to.val > 3)) {
+				fprintf(stderr, "%s: invalid antenna select %d\n",
+					fn_name, to.val);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->rxiq = ((params->rxiq & 0xfffffff0) | (to.val & 0xf));
+		}
+		if (to.opt == 'e') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int"
+					" for extra INITgain\n", fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if ((to.val < 0) || (to.val > 24) || (to.val % 3 != 0)) {
+				fprintf(stderr,
+					"%s: Valid extra INITgain = {0, 3, .., 21, 24}\n",
+					fn_name);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->rxiq = ((((to.val/3) & 0xf) << 28) | (params->rxiq & 0x0fffffff));
+		}
+		if (to.opt == 'i') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int"
+					" for init or clipLO mode\n", fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if ((to.val != 0) && (to.val != 1) &&
+					(to.val != 2) && (to.val != 3) && (to.val != 4)) {
+				fprintf(stderr,
+					"%s: Valid options - 0(default gain), 1(fixed high gain)"
+					"or 4(fixed low gain). \n",
+						fn_name);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->rxiq = ((params->rxiq & 0xffffff0f) | ((to.val << 4) & 0xf0));
+		}
+	}
+	params->rxiq = htod32(params->rxiq);
+exit:
+	return err;
+}
+
+static void
+wl_rxiq_print_4365(uint16 *iqest_core, uint8 resolution)
+{
+	if (resolution == 1) {
+		/* fine resolution power reporting (0.25dB resolution) */
+		uint8 core;
+		int16 tmp;
+		/* Four chains: */
+		for (core = 0; core < WL_STA_ANT_MAX; core ++) {
+			tmp = iqest_core[core];
+			if (tmp < 0) {
+				tmp = -1*tmp;
+				printf("-%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+			} else if (tmp > 0) {
+				printf("%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+			}
+		}
+		printf("\n");
+	} else {
+		/* fine resolution power reporting (0.25dB resolution) */
+		uint8 core;
+		int16 tmp;
+		/* Four chains: */
+		for (core = 0; core < WL_STA_ANT_MAX; core ++) {
+			tmp = (int8)(iqest_core[core]);
+			if (tmp != 0)
+				printf("%ddBm ", tmp);
+		}
+		printf("\n");
+	}
+}
+
+static void
+wl_rxiq_print(uint32 rxiq, uint8 resolution)
+{
+	if (resolution == 1) {
+		/* fine resolution power reporting (0.25dB resolution) */
+		uint8 core;
+		int16 tmp;
+		if (rxiq >> 20) {
+			/* Three chains: */
+			for (core = 0; core < 3; core ++) {
+				tmp = (rxiq >> (10*core)) & 0x3ff;
+				tmp = ((int16)(tmp << 6)) >> 6; /* sign extension */
+				if (tmp < 0) {
+					tmp = -1*tmp;
+					printf("-%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+				} else {
+					printf("%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+				}
+			}
+			printf("\n");
+		} else if (rxiq >> 10) {
+			/* 2 chains */
+			for (core = 0; core < 2; core ++) {
+				tmp = (rxiq >> (10*core)) & 0x3ff;
+				tmp = ((int16)(tmp << 6)) >> 6; /* sign extension */
+				if (tmp < 0) {
+					tmp = -1*tmp;
+					printf("-%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+				} else {
+					printf("%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+				}
+			}
+			printf("\n");
+		} else {
+			/* 1 chain */
+			tmp = rxiq & 0x3ff;
+			tmp = ((int16)(tmp << 6)) >> 6; /* sign extension */
+			if (tmp < 0) {
+				tmp = -1*tmp;
+				printf("-%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+			} else {
+				printf("%d.%ddBm ", (tmp >> 2), (tmp & 0x3)*25);
+			}
+			printf("\n");
+		}
+
+	} else {
+		if (rxiq >> 24)
+			printf("%ddBm %ddBm %ddBm %ddBm \n", (int8)(rxiq & 0xff),
+				(int8)((rxiq >> 8) & 0xff), (int8)((rxiq >> 16) & 0xff),
+				(int8)((rxiq >> 24) & 0xff));
+		else if (rxiq >> 16)
+			printf("%ddBm %ddBm %ddBm\n", (int8)(rxiq & 0xff),
+				(int8)((rxiq >> 8) & 0xff), (int8)((rxiq >> 16) & 0xff));
+		else if (rxiq >> 8)
+			printf("%ddBm %ddBm\n", (int8)(rxiq & 0xff), (int8)((rxiq >> 8) & 0xff));
+		else
+			printf("%ddBm\n", (int8)(rxiq & 0xff));
+	}
+}
+
+#define IFERR(x) do { err = (x); if (err) return err; } while (0)
+static int
+wl_rxiq(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_iqest_params_t params = {0, 0, 0};
+	uint8 resolution;
+	int err;
+	uint16 iqest_core[WL_STA_ANT_MAX];
+	wlc_rev_info_t revinfo;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	IFERR(wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)));
+
+	IFERR(wl_rxiq_prepare(argv, &params, &resolution));
+
+	if (BCM4365_CHIP(dtoh32(revinfo.chipnum))) {
+		iqest_core[0] = params.rxiq & 0xffff;
+		iqest_core[1] = (params.rxiq >> 16) & 0xffff;
+		IFERR(wlu_var_setbuf(wl, cmd->name, iqest_core, WL_STA_ANT_MAX*sizeof(int16)));
+		IFERR(wlu_iovar_get(wl, cmd->name, iqest_core, WL_STA_ANT_MAX*sizeof(int16)));
+		wl_rxiq_print_4365(iqest_core, resolution);
+		return BCME_OK;
+	}
+
+	IFERR(wlu_iovar_set(wl, cmd->name, &params, sizeof(params)));
+	IFERR(wlu_iovar_getint(wl, cmd->name, (int*)&params.rxiq));
+	wl_rxiq_print(params.rxiq, resolution);
+
+	return BCME_OK;
+}
+
+#define SWEEP_ERROR "phy_rxiqest_sweep Error: "
+static int
+wl_rxiq_sweep(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	int err, params_size, buf_size, i, offset;
+	uint8 nchannels, resolution, all;
+	char *ptr, *channels = NULL;
+	wl_iqest_sweep_params_t *sweep_params;
+	wl_iqest_result_t *result;
+	wlc_rev_info_t revinfo;
+
+	memset(&revinfo, 0, sizeof(revinfo));
+	IFERR(wlu_get(wl, WLC_GET_REVINFO, &revinfo, sizeof(revinfo)));
+
+	if (BCM4365_CHIP(dtoh32(revinfo.chipnum)))
+		return BCME_UNSUPPORTED;
+
+	offset = strlen(cmd->name) + 1;
+	sweep_params = (wl_iqest_sweep_params_t *)(buf + offset);
+	if ((err = wl_rxiq_prepare(argv, &sweep_params->params, &resolution)))
+		return err;
+	miniopt_init(&to, "wl_rxiq_sweep", NULL, FALSE);
+	while ((err = miniopt(&to, argv)) != -1) {
+		if (err == 1)
+			return BCME_USAGE_ERROR;
+
+		argv += to.consumed;
+
+		if (to.opt == 'c') {
+			if (channels) {
+				err = BCME_BADARG;
+				fprintf(stderr, SWEEP_ERROR "Duplicate channel parameters\n");
+				goto Exit;
+			}
+			channels = strdup(to.valstr);
+			if (!channels) {
+				fprintf(stderr, SWEEP_ERROR "Unable to allocate %d bytes for "
+					"wl_rxiq_sweep\n", (int)strlen(to.valstr));
+				return BCME_NOMEM;
+			}
+		}
+	}
+
+	if (!channels) {
+		err = BCME_BADCHAN;
+		fprintf(stderr, SWEEP_ERROR "Missing channel parameters\n");
+		goto Exit;
+	}
+
+	for (nchannels = 0, all = 0, ptr = channels; ptr; ptr = strchr(ptr + 1, ','), ++nchannels) {
+		char *channel = *ptr == ',' ? ptr + 1 : ptr;
+
+		if (!strnicmp(channel, "all", 3)) {
+			if (channel == ptr && !channel[3]) {
+				nchannels = 1;
+				all = 1;
+				break;
+			}
+			fprintf(stderr, SWEEP_ERROR "Channel argument should be either all or a "
+				"comma separated list of channels\n");
+			err = BCME_BADCHAN;
+			goto Exit;
+		}
+	}
+
+	if (nchannels > WL_NUMCHANNELS) {
+		fprintf(stderr, SWEEP_ERROR "Maximum of %d channels allowed\n", WL_NUMCHANNELS);
+		err = BCME_BADCHAN;
+		goto Exit;
+	}
+
+	params_size = sizeof(*sweep_params) + (nchannels - 1) * sizeof(uint8);
+	buf_size = sizeof(*result) + ((all ? WL_NUMCHANNELS : nchannels) - 1)
+		* sizeof(wl_iqest_value_t);
+	if (buf_size < params_size + offset)
+		buf_size = params_size + offset;
+	if (buf_size > WLC_IOCTL_MEDLEN) {
+		fprintf(stderr, SWEEP_ERROR "Internal error - buffer is not big enough\n");
+		err = BCME_BUFTOOSHORT;
+		goto Exit;
+	}
+	offset += params_size;
+	if (all) {
+		sweep_params->nchannels = 1;
+		sweep_params->channel[0] = 0;
+		if (sweep_params->params.niter > WL_ITER_LIMIT_MANY_CHAN) {
+			fprintf(stderr, SWEEP_ERROR "Maximum %d averaging iterations allowed if "
+				"number of channel is greater than %d\n", WL_ITER_LIMIT_MANY_CHAN,
+				WL_NUMCHANNELS_MANY_CHAN);
+			err = BCME_BADARG;
+			goto Exit;
+		}
+	}
+	else {
+		sweep_params->nchannels = 0;
+		for (i = 0, ptr = strtok(channels, ","); ptr; ++i, ptr = strtok(NULL, ",")) {
+			int j;
+			char *endptr = NULL;
+			int channel = (int)strtoul(ptr, &endptr, 0);
+
+			if (*endptr || channel < 1 || channel > 165) {
+				fprintf(stderr, SWEEP_ERROR "wrong channel value %s\n", ptr);
+				err = BCME_BADARG;
+				goto Exit;
+			}
+			for (j = 0; j < sweep_params->nchannels; ++j) {
+				if (channel == sweep_params->channel[j]) {
+					err = BCME_BADCHAN;
+					fprintf(stderr, SWEEP_ERROR "Duplicate channel "
+						"parameters\n");
+					goto Exit;
+				}
+			}
+			sweep_params->channel[sweep_params->nchannels++] = (uint8)channel;
+		}
+	}
+
+	if (sweep_params->nchannels > WL_NUMCHANNELS_MANY_CHAN && sweep_params->params.niter
+		> WL_ITER_LIMIT_MANY_CHAN) {
+		fprintf(stderr, SWEEP_ERROR "Maximum %d averaging iterations allowed if number"
+			" of channel is greater than %d\n", WL_ITER_LIMIT_MANY_CHAN,
+			WL_NUMCHANNELS_MANY_CHAN);
+		err = BCME_BADARG;
+		goto Exit;
+	}
+
+	if ((err = wlu_iovar_getbuf(wl, cmd->name, sweep_params, params_size, buf, buf_size)) < 0)
+		goto Exit;
+
+	result = (wl_iqest_result_t *)buf;
+	for (i = 0; i < result->nvalues; ++i) {
+		printf("Channel: %u\t", result->value[i].channel);
+		wl_rxiq_print(dtoh32(result->value[i].rxiq), resolution);
+	}
+Exit:
+	free(channels);
+	return err;
+}
+
+#if defined(BCMDBG)
+static int
+wl_phy_debug_cmd(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int val;
+	char *val_name;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* command name */
+	val_name = *argv++;
+	val = (*argv == NULL) ? 0 : atoi(*argv);
+
+
+	if ((err = wlu_iovar_setint(wl, val_name, (int)val)) < 0)
+		printf("PHY DEBUG COMMAND error %d\n", err);
+
+	return err;
+
+}
+#endif 
+
+static int
+wl_rifs(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int val, rifs;
+	char *val_name;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* command name */
+	val_name = *argv++;
+
+	if (!*argv) {
+		if ((err = wlu_iovar_getint(wl, val_name, (int*)&rifs)) < 0)
+			return err;
+
+		printf("%s\n", ((rifs & 0xff) ? "On" : "Off"));
+		return 0;
+	}
+
+	val = rifs = (atoi(*argv) ? 1 : 0);
+
+	if ((err = wlu_set(wl, WLC_SET_FAKEFRAG, &val, sizeof(int))) < 0) {
+		printf("Set frameburst error %d\n", err);
+		return err;
+	}
+	if ((err = wlu_iovar_setint(wl, val_name, (int)rifs)) < 0)
+		printf("Set rifs error %d\n", err);
+
+	return err;
+}
+
+static int
+wl_rifs_advert(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	int rifs_advert;
+	char *val_name;
+
+	BCM_REFERENCE(cmd);
+
+	/* command name */
+	val_name = *argv++;
+
+	if (!*argv) {
+		if ((err = wlu_iovar_getint(wl, val_name, (int*)&rifs_advert)) < 0)
+			return err;
+
+		printf("%s\n", ((rifs_advert & 0xff) ? "On" : "Off"));
+		return 0;
+	}
+
+	if (strcmp(*argv, "-1") && strcmp(*argv, "0"))
+		return BCME_USAGE_ERROR;
+
+	rifs_advert = atoi(*argv);
+
+	if ((err = wlu_iovar_setint(wl, val_name, (int)rifs_advert)) < 0)
+		printf("Set rifs mode advertisement error %d\n", err);
+
+	return err;
+}
+
+static int
+wlu_afeoverride(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	uint32 int_val;
+	bool get = TRUE;
+	void *ptr = NULL;
+	char *endptr;
+
+	if (argv[1]) {
+		uint32 get_val;
+		get = FALSE;
+		int_val = htod32(strtoul(argv[1], &endptr, 0));
+		if (wlu_var_getbuf(wl, cmd->name, var, sizeof(var), &ptr) < 0)
+			return -1;
+		get_val = *(int *)ptr;
+		get_val &= ~1;
+		if (int_val)
+			int_val = get_val | 1;
+		else
+			int_val = get_val;
+		memcpy(var, (char *)&int_val, sizeof(int_val));
+	}
+	if (get) {
+		if (wlu_var_getbuf(wl, cmd->name, var, sizeof(var), &ptr) < 0)
+			return -1;
+		printf("0x%x\n", dtoh32(*(int *)ptr));
+	}
+	else
+		wlu_var_setbuf(wl, cmd->name, &var, sizeof(var));
+	return 0;
+}
+
+/*
+ *  RADAR detection parameter control
+ */
+static int
+wl_radar_args(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	wl_radar_args_t ra;
+
+	/* Skip the command name */
+	argv++;
+
+	if (*argv == NULL) {
+		/* Get */
+
+		if ((ret = wlu_iovar_get(wl, cmd->name, &ra, sizeof(ra))) < 0)
+			return ret;
+
+		if (ra.version != WL_RADAR_ARGS_VERSION) {
+			printf("\tIncorrect version of RADAR_ARGS struct: expected %d; got %d\n",
+			       WL_RADAR_ARGS_VERSION, ra.version);
+			return -1;
+		}
+		printf("version %d npulses %d ncontig %d min_pw %d max_pw %d thresh0 0x%x "
+		       "thresh1 0x%x\n",
+		       ra.version, ra.npulses, ra.ncontig, ra.min_pw,
+		       ra.max_pw, ra.thresh0, ra.thresh1);
+		printf("blank 0x%x fmdemodcfg 0x%x npulses_lp %d min_pw_lp %d "
+		       "max_pw_lp %d\n",
+		       ra.blank, ra.fmdemodcfg, ra.npulses_lp, ra.min_pw_lp,
+		       ra.max_pw_lp);
+		printf("min_fm_lp %d max_span_lp %d min_deltat %d max_deltat %d\n",
+		       ra.min_fm_lp, ra.max_span_lp, ra.min_deltat, ra.max_deltat);
+
+		printf("autocorr 0x%x st_level_time 0x%x  t2_min %d fra_pulse_err %d\n",
+		       ra.autocorr, ra.st_level_time, ra.t2_min, ra.fra_pulse_err);
+		printf("npulses_fra %d npulses_stg2 %d npulses_stg3 %d percal_mask 0x%x quant %d\n",
+			ra.npulses_fra, ra.npulses_stg2, ra.npulses_stg3, ra.percal_mask,
+			ra.quant);
+		printf("min_burst_intv_lp %d max_burst_intv_lp %d nskip_rst_lp %d max_pw_tol %d "
+				"feature_mask 0x%x\n",
+				ra.min_burst_intv_lp, ra.max_burst_intv_lp, ra.nskip_rst_lp,
+				ra.max_pw_tol, ra.feature_mask);
+		printf("thresh0_sc 0x%x thresh1_sc 0x%x\n",
+				ra.thresh0_sc, ra.thresh1_sc);
+
+		/* this part prints only param values */
+		printf("%d %d %d %d %d 0x%x "
+		       "0x%x",
+		       ra.version, ra.npulses, ra.ncontig, ra.min_pw,
+		       ra.max_pw, ra.thresh0, ra.thresh1);
+		printf(" 0x%x 0x%x %d %d "
+		       "%d",
+		       ra.blank, ra.fmdemodcfg, ra.npulses_lp, ra.min_pw_lp,
+		       ra.max_pw_lp);
+		printf(" %d %d %d %d",
+		       ra.min_fm_lp, ra.max_span_lp, ra.min_deltat, ra.max_deltat);
+
+		printf(" 0x%x 0x%x %d %d",
+		       ra.autocorr, ra.st_level_time, ra.t2_min, ra.fra_pulse_err);
+		printf(" %d %d %d 0x%x %d",
+			ra.npulses_fra, ra.npulses_stg2, ra.npulses_stg3, ra.percal_mask,
+			ra.quant);
+		printf(" %d %d %d %d "
+				"0x%x  0x%x 0x%x\n",
+				ra.min_burst_intv_lp, ra.max_burst_intv_lp, ra.nskip_rst_lp,
+				ra.max_pw_tol, ra.feature_mask, ra.thresh0_sc, ra.thresh1_sc);
+
+
+	} else {
+		/* Set */
+		char *endptr = NULL;
+		int val_count = 32;
+		long vals[32];
+		long *pval;
+		int i;
+
+		for (i = 0; i < val_count; i++, argv++) {
+			/* verify that there is another arg */
+			if (*argv == NULL)
+				return BCME_USAGE_ERROR;
+
+			vals[i] = strtol(*argv, &endptr, 0);
+
+			/* make sure all the value string was parsed by strtol */
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+
+		pval = vals;
+
+		ra.version       = *pval++;
+		ra.npulses       = *pval++;
+		ra.ncontig       = *pval++;
+		ra.min_pw        = *pval++;
+		ra.max_pw        = *pval++;
+		ra.thresh0       = (uint16)*pval++;
+		ra.thresh1       = (uint16)*pval++;
+		ra.blank         = (uint16)*pval++;
+		ra.fmdemodcfg    = (uint16)*pval++;
+		ra.npulses_lp    = *pval++;
+		ra.min_pw_lp     = *pval++;
+		ra.max_pw_lp     = *pval++;
+		ra.min_fm_lp     = *pval++;
+		ra.max_span_lp   = *pval++;
+		ra.min_deltat    = *pval++;
+		ra.max_deltat    = *pval++;
+		ra.autocorr      = (uint16)*pval++;
+		ra.st_level_time = (uint16)*pval++;
+		ra.t2_min        = (uint16)*pval++;
+		ra.fra_pulse_err = (uint32)*pval++;
+		ra.npulses_fra   = (int)*pval++;
+		ra.npulses_stg2  = (int)*pval++;
+		ra.npulses_stg3  = (int)*pval++;
+		ra.percal_mask   = (int)*pval++;
+		ra.quant         = (int)*pval++;
+		ra.min_burst_intv_lp = (uint32)*pval++;
+		ra.max_burst_intv_lp = (uint32)*pval++;
+		ra.nskip_rst_lp  = (int)*pval++;
+		ra.max_pw_tol    = (int)*pval++;
+		ra.feature_mask  = (uint16)*pval++;
+		ra.thresh0_sc    = (uint16)*pval++;
+		ra.thresh1_sc    = (uint16)*pval++;
+
+		return wlu_var_setbuf(wl, cmd->name, &ra, sizeof(wl_radar_args_t));
+	}
+	return ret;
+}
+
+static int
+wl_radar_thrs(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	wl_radar_thr_t radar_thrs;
+
+	if (*++argv) {
+		/* Set */
+		char *endptr;
+		#ifdef WL11AC160
+			int val_count = 16;
+			uint16 vals[16];
+		#else
+			int val_count = 12;
+			uint16 vals[12];
+		#endif /* WL11AC160 */
+
+		uint16 *pval;
+		int i;
+
+		for (i = 0; i < val_count; i++, argv++) {
+			/* verify that there is another arg */
+			if (i < 12) {
+				/* for BW20,40,80 */
+				if (*argv == NULL)
+					return BCME_USAGE_ERROR;
+				vals[i] = (uint16)strtol(*argv, &endptr, 0);
+				/* make sure all the value string was parsed by strtol */
+				if (*endptr != '\0')
+					return BCME_USAGE_ERROR;
+			}
+			#ifdef WL11AC160
+			else {
+				/* for BW160 */
+				if (*argv == NULL) {
+					if (i == 12) {
+						/* To be compatable with older commands */
+						vals[i] = 0;
+						vals[i+1] = 0;
+						vals[i+2] = 0;
+						vals[i+3] = 0;
+						break;
+					} else {
+						return BCME_USAGE_ERROR;
+					}
+				} else {
+					vals[i] = (uint16)strtol(*argv, &endptr, 0);
+					/* make sure all the value string was parsed by strtol */
+					if (*endptr != '\0')
+						return BCME_USAGE_ERROR;
+				}
+
+			}
+			#endif /* WL11AC160 */
+		}
+
+		radar_thrs.version = WL_RADAR_THR_VERSION;
+
+		/* Order thresh0_20_lo, thresh1_20_lo, thresh0_40_lo, thresh1_40_lo
+		 * thresh0_20_hi, thresh1_20_hi, thresh0_40_hi, thresh1_40_hi
+		 */
+		pval = vals;
+		radar_thrs.thresh0_20_lo = (uint16)*pval++;
+		radar_thrs.thresh1_20_lo = (uint16)*pval++;
+		radar_thrs.thresh0_40_lo = (uint16)*pval++;
+		radar_thrs.thresh1_40_lo = (uint16)*pval++;
+		radar_thrs.thresh0_80_lo = (uint16)*pval++;
+		radar_thrs.thresh1_80_lo = (uint16)*pval++;
+		radar_thrs.thresh0_20_hi = (uint16)*pval++;
+		radar_thrs.thresh1_20_hi = (uint16)*pval++;
+		radar_thrs.thresh0_40_hi = (uint16)*pval++;
+		radar_thrs.thresh1_40_hi = (uint16)*pval++;
+		radar_thrs.thresh0_80_hi = (uint16)*pval++;
+		radar_thrs.thresh1_80_hi = (uint16)*pval++;
+		#ifdef WL11AC160
+		radar_thrs.thresh0_160_lo = (uint16)*pval++;
+		radar_thrs.thresh1_160_lo = (uint16)*pval++;
+		radar_thrs.thresh0_160_hi = (uint16)*pval++;
+		radar_thrs.thresh1_160_hi = (uint16)*pval++;
+		#endif /* WL11AC160 */
+
+
+		return wlu_var_setbuf(wl, cmd->name, &radar_thrs, sizeof(wl_radar_thr_t));
+	}
+	return ret;
+}
+
+
+static int
+wl_radar_thrs2(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	wl_radar_thr2_t radar_thrs2;
+	argv++;
+
+	if (*argv == NULL) {
+		if ((ret = wlu_iovar_get(wl, cmd->name, &radar_thrs2, sizeof(radar_thrs2))) < 0)
+					return ret;
+
+				if (radar_thrs2.version != WL_RADAR_ARGS_VERSION) {
+					printf("\tIncorrect version"
+					"\tof RADAR_ARGS struct:expected %d; got %d\n",
+					WL_RADAR_ARGS_VERSION, radar_thrs2.version);
+					return -1;
+				}
+				printf("version %d\n"
+				"thresh0_sc_20_lo 0x%x thresh1_sc_20_lo 0x%x"
+				"thresh0_sc_40_lo 0x%x thresh1_sc_40_lo 0x%x"
+				"thresh0_sc_80_lo 0x%x thresh1_sc_80_lo 0x%x\n"
+				"thresh0_sc_20_hi 0x%x thresh1_sc_20_hi 0x%x"
+				"thresh0_sc_40_hi 0x%x thresh1_sc_40_hi 0x%x"
+				"thresh0_sc_80_hi 0x%x thresh1_sc_80_hi 0x%x\n"
+				"fc_varth_sb 0x%x fc_varth_bin5_sb 0x%x notradar_enb 0x%x\n"
+				"max_notradar_lp 0x%x max_notradar 0x%x max_notradar_lp_sc 0x%x "
+				"max_notradar_sc 0x%x highpow_war_enb 0x%x highpow_sp_ratio 0x%x\n",
+				radar_thrs2.version, radar_thrs2.thresh0_sc_20_lo,
+				radar_thrs2.thresh1_sc_20_lo,
+				radar_thrs2.thresh0_sc_40_lo, radar_thrs2.thresh1_sc_40_lo,
+				radar_thrs2.thresh0_sc_80_lo, radar_thrs2.thresh1_sc_80_lo,
+				radar_thrs2.thresh0_sc_20_hi, radar_thrs2.thresh1_sc_20_hi,
+				radar_thrs2.thresh0_sc_40_hi, radar_thrs2.thresh1_sc_40_hi,
+				radar_thrs2.thresh0_sc_80_hi, radar_thrs2.thresh1_sc_80_hi,
+				radar_thrs2.fc_varth_sb, radar_thrs2.fc_varth_bin5_sb,
+				radar_thrs2.notradar_enb, radar_thrs2.max_notradar_lp,
+				radar_thrs2.max_notradar,
+				radar_thrs2.max_notradar_lp_sc, radar_thrs2.max_notradar_sc,
+				radar_thrs2.highpow_war_enb, radar_thrs2.highpow_sp_ratio);
+
+				/* this part prints only param values */
+				printf("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
+				"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+				radar_thrs2.thresh0_sc_20_lo, radar_thrs2.thresh1_sc_20_lo,
+				radar_thrs2.thresh0_sc_40_lo, radar_thrs2.thresh1_sc_40_lo,
+				radar_thrs2.thresh0_sc_80_lo, radar_thrs2.thresh1_sc_80_lo,
+				radar_thrs2.thresh0_sc_20_hi, radar_thrs2.thresh1_sc_20_hi,
+				radar_thrs2.thresh0_sc_40_hi, radar_thrs2.thresh1_sc_40_hi,
+				radar_thrs2.thresh0_sc_80_hi, radar_thrs2.thresh1_sc_80_hi,
+				radar_thrs2.fc_varth_sb, radar_thrs2.fc_varth_bin5_sb,
+				radar_thrs2.notradar_enb,
+				radar_thrs2.max_notradar_lp, radar_thrs2.max_notradar,
+				radar_thrs2.max_notradar_lp_sc, radar_thrs2.max_notradar_sc,
+				radar_thrs2.highpow_war_enb, radar_thrs2.highpow_sp_ratio);
+
+	} else {
+		/* Set */
+		char *endptr = NULL;
+		int val_count = 21;
+		long vals[21];
+		long *pval;
+		int i;
+
+		for (i = 0; i < val_count; i++, argv++) {
+			/* verify that there is another arg */
+			if (*argv == NULL)
+				return BCME_USAGE_ERROR;
+
+			vals[i] = strtol(*argv, &endptr, 0);
+
+			/* make sure all the value string was parsed by strtol */
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+
+		radar_thrs2.version = WL_RADAR_THR_VERSION;
+
+		pval = vals;
+		radar_thrs2.thresh0_sc_20_lo = (uint16)*pval++;
+		radar_thrs2.thresh1_sc_20_lo = (uint16)*pval++;
+		radar_thrs2.thresh0_sc_40_lo = (uint16)*pval++;
+		radar_thrs2.thresh1_sc_40_lo = (uint16)*pval++;
+		radar_thrs2.thresh0_sc_80_lo = (uint16)*pval++;
+		radar_thrs2.thresh1_sc_80_lo = (uint16)*pval++;
+		radar_thrs2.thresh0_sc_20_hi = (uint16)*pval++;
+		radar_thrs2.thresh1_sc_20_hi = (uint16)*pval++;
+		radar_thrs2.thresh0_sc_40_hi = (uint16)*pval++;
+		radar_thrs2.thresh1_sc_40_hi = (uint16)*pval++;
+		radar_thrs2.thresh0_sc_80_hi = (uint16)*pval++;
+		radar_thrs2.thresh1_sc_80_hi = (uint16)*pval++;
+		radar_thrs2.fc_varth_sb = (uint16)*pval++;
+		radar_thrs2.fc_varth_bin5_sb = (uint16)*pval++;
+		radar_thrs2.notradar_enb = (uint16)*pval++;
+		radar_thrs2.max_notradar_lp = (uint16)*pval++;
+		radar_thrs2.max_notradar = (uint16)*pval++;
+		radar_thrs2.max_notradar_lp_sc = (uint16)*pval++;
+		radar_thrs2.max_notradar_sc = (uint16)*pval++;
+		radar_thrs2.highpow_war_enb = (uint16)*pval++;
+		radar_thrs2.highpow_sp_ratio = (uint16)*pval++;
+		return wlu_var_setbuf(wl, cmd->name, &radar_thrs2, sizeof(wl_radar_thr2_t));
+	}
+	return ret;
+
+}
+
+static int
+wl_phy_dyn_switch_th(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = -1;
+	wl_dyn_switch_th_t dyn_switch_th;
+	argv++;
+
+	if (*argv == NULL) {
+		if ((ret = wlu_iovar_get(wl, cmd->name, &dyn_switch_th, sizeof(dyn_switch_th))) < 0)
+					return ret;
+
+				if (dyn_switch_th.ver != WL_PHY_DYN_SWITCH_TH_VERSION) {
+					printf("\tIncorrect version"
+					"\tof phy_dyn_switch_th:expected %d; got %d\n",
+					WL_PHY_DYN_SWITCH_TH_VERSION, dyn_switch_th.ver);
+					return -1;
+				}
+				printf("version %d\n"
+				"rssi_gain_80_3 %d rssi_gain_80_2 %d "
+				"rssi_gain_80_1 %d rssi_gain_80_0 %d \n"
+				"rssi_gain_160_3 %d rssi_gain_160_2 %d "
+				"rssi_gain_160_1 %d rssi_gain_160_0 %d \n"
+				"rssi_th_2 %d rssi_th_1 %d "
+				"rssi_th_0 %d\n",
+				dyn_switch_th.ver, dyn_switch_th.rssi_gain_80[3],
+				dyn_switch_th.rssi_gain_80[2],
+				dyn_switch_th.rssi_gain_80[1], dyn_switch_th.rssi_gain_80[0],
+				dyn_switch_th.rssi_gain_160[3], dyn_switch_th.rssi_gain_160[2],
+				dyn_switch_th.rssi_gain_160[1], dyn_switch_th.rssi_gain_160[0],
+				dyn_switch_th.rssi_th[2], dyn_switch_th.rssi_th[1],
+				dyn_switch_th.rssi_th[0]);
+
+				/* this part prints only param values */
+				printf("%d %d %d %d %d %d %d %d %d "
+				"%d %d\n",
+				dyn_switch_th.rssi_gain_80[3], dyn_switch_th.rssi_gain_80[2],
+				dyn_switch_th.rssi_gain_80[1], dyn_switch_th.rssi_gain_80[0],
+				dyn_switch_th.rssi_gain_160[3], dyn_switch_th.rssi_gain_160[2],
+				dyn_switch_th.rssi_gain_160[1], dyn_switch_th.rssi_gain_160[0],
+				dyn_switch_th.rssi_th[2], dyn_switch_th.rssi_th[1],
+				dyn_switch_th.rssi_th[0]);
+
+	} else {
+		/* Set */
+		char *endptr = NULL;
+		uint val_count = 11;
+		long vals[11];
+		long *pval;
+		uint i;
+
+		for (i = 0; i < val_count; i++, argv++) {
+			/* verify that there is another arg */
+			if (*argv == NULL)
+				return BCME_USAGE_ERROR;
+			vals[i] = strtol(*argv, &endptr, 0);
+
+			/* make sure all the value string was parsed by strtol */
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+
+		dyn_switch_th.ver = WL_PHY_DYN_SWITCH_TH_VERSION;
+
+		pval = vals;
+		dyn_switch_th.rssi_gain_80[3] = (uint16)*pval++;
+		dyn_switch_th.rssi_gain_80[2] = (uint16)*pval++;
+		dyn_switch_th.rssi_gain_80[1] = (uint16)*pval++;
+		dyn_switch_th.rssi_gain_80[0] = (uint16)*pval++;
+		dyn_switch_th.rssi_gain_160[3] = (uint16)*pval++;
+		dyn_switch_th.rssi_gain_160[2] = (uint16)*pval++;
+		dyn_switch_th.rssi_gain_160[1] = (uint16)*pval++;
+		dyn_switch_th.rssi_gain_160[0] = (uint16)*pval++;
+		dyn_switch_th.rssi_th[2] = (int16)*pval++;
+		dyn_switch_th.rssi_th[1] = (int16)*pval++;
+		dyn_switch_th.rssi_th[0] = (int16)*pval++;
+		return wlu_var_setbuf(wl, cmd->name, &dyn_switch_th, sizeof(wl_dyn_switch_th_t));
+	}
+	return ret;
+
+}
+
+static int
+wl_phy_tpc_av(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	uint argc;
+	char *endptr;
+	uint8 Av_buff[3];
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argc < 2 || argc > 3)
+		return BCME_USAGE_ERROR;
+	Av_buff[0] = (uint8)strtol(argv[1], &endptr, 0);
+	Av_buff[1] = (uint8)strtol(argv[2], &endptr, 0);
+
+	if (argc == 2) {
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, Av_buff, 2*sizeof(uint8),
+				buf, WLC_IOCTL_MAXLEN)) < 0) {
+			return (ret);
+		}
+		printf("Av = %d for core%d and sub-band %d\n", *(uint*)buf, Av_buff[0], Av_buff[1]);
+	} else if (argc == 3) {
+		Av_buff[2] = (uint8)strtol(argv[3], &endptr, 0);
+		ret = wlu_iovar_setbuf(wl, cmd->name, Av_buff, 3*sizeof(uint8),
+			buf, WLC_IOCTL_MAXLEN);
+	}
+	return ret;
+}
+
+static int
+wl_phy_tpc_vmid(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	uint argc;
+	char *endptr;
+	uint8 Vmid_buff[3];
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argc < 2 || argc > 3)
+		return BCME_USAGE_ERROR;
+	Vmid_buff[0] = (uint8)strtol(argv[1], &endptr, 0);
+	Vmid_buff[1] = (uint8)strtol(argv[2], &endptr, 0);
+
+	if (argc == 2) {
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, Vmid_buff, 2*sizeof(uint8),
+				buf, WLC_IOCTL_MAXLEN)) < 0) {
+			return (ret);
+		}
+		printf("Vmid = %d for core%d and sub-band %d\n", *(uint*)buf, Vmid_buff[0],
+				Vmid_buff[1]);
+	} else if (argc == 3) {
+		Vmid_buff[2] = (uint8)strtol(argv[3], &endptr, 0);
+		ret = wlu_iovar_setbuf(wl, cmd->name, Vmid_buff, 3*sizeof(uint8),
+			buf, WLC_IOCTL_MAXLEN);
+	}
+	return ret;
+}
+
+
+
+
+/* TXCAL IOVARS */
+static int
+wl_txcal_gainsweep_meas(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_txcal_meas_ncore_t * txcal_meas, * txcal_meas_old;
+	wl_txcal_meas_percore_t * per_core;
+	wl_txcal_meas_old_t * txcal_meas_legacy;
+	int16 pwr[WLC_TXCORE_MAX][MAX_NUM_TXCAL_MEAS];
+
+	void *ptr = NULL;
+	int err = BCME_OK;
+	int version_err = BCME_OK;
+	void* buf = NULL;
+	uint8 core;
+	uint16 i;
+	uint16 buf_size = OFFSETOF(wl_txcal_meas_ncore_t, txcal_percore) +
+			WLC_TXCORE_MAX* sizeof(wl_txcal_meas_percore_t);
+
+	/* Allocate buffer for set iovar */
+	buf = malloc(buf_size);
+	if (buf == NULL) {
+		err = BCME_NOMEM;
+		goto fail;
+	}
+	memset(buf, 0, buf_size);
+	txcal_meas = (wl_txcal_meas_ncore_t *)buf;
+
+	if (*++argv) {
+		i = 0;
+		core = strtoul(*argv, NULL, 0);
+
+		if (core > (WLC_TXCORE_MAX- 1)) {
+			err = BCME_USAGE_ERROR;
+			goto fail;
+		}
+
+		if (!*++argv) {
+			err = BCME_USAGE_ERROR;
+			goto fail;
+		}
+
+		/* Check for version */
+		version_err = wlu_var_getbuf_sm(wl, "txcal_ver", NULL, 0, &ptr);
+		if ((version_err != BCME_OK) || (*(int*)ptr == 0)) {
+		/* using wl with backward compatibility for old firmware */
+			memset(pwr, 0, WLC_TXCORE_MAX_OLD*MAX_NUM_TXCAL_MEAS*sizeof(pwr[0][0]));
+			i = 0;
+			if ((err = wlu_var_getbuf_med(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			   goto fail;
+			txcal_meas_legacy = (wl_txcal_meas_old_t *)ptr;
+			memcpy(&pwr[0][0], &txcal_meas_legacy->pwr[0][0],
+			        WLC_TXCORE_MAX_OLD*MAX_NUM_TXCAL_MEAS*sizeof(pwr[0][0]));
+			do {
+				if (i >= MAX_NUM_TXCAL_MEAS) {
+					printf("Entries exceeded max allowed\n");
+					err = BCME_USAGE_ERROR;
+					goto fail;
+				}
+				pwr[core][i] = strtoul(*argv, NULL, 0);
+				i++;
+			} while (*++argv);
+			if (i != txcal_meas_legacy->valid_cnt)	{
+				printf("Incorrect Number of Entries. Expected %d, Entered %d\n",
+					txcal_meas_legacy->valid_cnt, i);
+				err = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			err = wlu_var_setbuf(wl, cmd->name, pwr, WLC_TXCORE_MAX_OLD*
+					MAX_NUM_TXCAL_MEAS*sizeof(pwr[0][0]));
+		} else {
+			txcal_meas->version = TXCAL_IOVAR_VERSION;
+			if ((err = wlu_var_getbuf(wl, cmd->name, txcal_meas, buf_size, &ptr)) < 0)
+				goto fail;
+			txcal_meas_old = (wl_txcal_meas_ncore_t *)ptr;
+
+			if (txcal_meas_old->version != TXCAL_IOVAR_VERSION) {
+				printf("Version mismatch %d \n", txcal_meas_old->version);
+				err = BCME_UNSUPPORTED;
+				goto fail;
+			}
+			/* 	wl support for new txcal structures
+			 *  check for max core support from dongle
+			 */
+			if (core > txcal_meas_old->num_core - 1) {
+				printf("Dongle supports only %d  cores \n"
+					"Allowed range 0 - %d \n", txcal_meas_old->num_core,
+					txcal_meas_old->num_core - 1);
+				err = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			/* Initialize set structure with fw copy to start with */
+			memcpy(txcal_meas, txcal_meas_old, buf_size);
+
+			/* Get to per core info */
+			per_core = txcal_meas->txcal_percore;
+			per_core += core;
+			do {
+				if (i >= MAX_NUM_TXCAL_MEAS) {
+					printf("Entries exceeded max allowed\n");
+					err = BCME_USAGE_ERROR;
+					goto fail;
+				}
+				per_core->pwr[i] = strtoul(*argv, NULL, 0);
+				i++;
+			} while (*++argv);
+			if (i != txcal_meas_old->valid_cnt)	{
+				printf("Incorrect Number of Entries. Expected %d, Entered %d\n",
+					txcal_meas_old->valid_cnt, i);
+				err = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			/* Add magic seq number */
+			txcal_meas->version = TXCAL_IOVAR_VERSION;
+			err = wlu_var_setbuf(wl, cmd->name, txcal_meas, buf_size);
+		}
+	} else {
+
+		/* Check for version */
+		version_err = wlu_var_getbuf_sm(wl, "txcal_ver", NULL, 0, &ptr);
+		if ((version_err != BCME_OK) || (*(int*)ptr == 0)) {
+			/* support for old firmware with old txcal structures */
+			if ((err = wlu_var_getbuf_med(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			goto fail;
+			txcal_meas_legacy = (wl_txcal_meas_old_t *)ptr;
+			for (core = 0; core < WLC_TXCORE_MAX_OLD; core++) {
+				printf("CORE%d\tTSSI\t\tPWR\n", core);
+				for (i = 0; i < txcal_meas_legacy->valid_cnt; i++)
+					printf("\t%d\t\t%d\n", txcal_meas_legacy->tssi[core][i],
+					        txcal_meas_legacy->pwr[core][i]);
+			}
+		} else {
+			txcal_meas->version = TXCAL_IOVAR_VERSION;
+			if ((err = wlu_var_getbuf(wl, cmd->name, txcal_meas, buf_size, &ptr)) < 0)
+				goto fail;
+			if (txcal_meas->version != TXCAL_IOVAR_VERSION) {
+				printf("version %d unsupported \n", txcal_meas->version);
+				err = BCME_UNSUPPORTED;
+				goto fail;
+			}
+		   /* support for new firmware with new txcal structures */
+			txcal_meas = (wl_txcal_meas_ncore_t *)ptr;
+			per_core = txcal_meas->txcal_percore;
+			/* Dump the info */
+			for (core = 0; core < txcal_meas->num_core; core++) {
+				printf("CORE%d\tTSSI\t\tPWR\n", core);
+				for (i = 0; i < txcal_meas->valid_cnt; i++) {
+					printf("\t%d\t\t%d\n", per_core->tssi[i],
+					        per_core->pwr[i]);
+				}
+				per_core++;
+			}
+		}
+	}
+
+fail:
+	if (buf) {
+		free(buf);
+	}
+
+	return err;
+}
+
+static int
+wl_txcal_gainsweep(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_txcal_params_t txcal_params;
+	uint8 gidx_start, gidx_stop;
+	int8 gidx_step;
+	char *endptr = NULL;
+	char *gidx_str;
+	int ret;
+
+	memset(&txcal_params, 0, sizeof(txcal_params));
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	if (!wl_ether_atoe(*argv, (struct ether_addr *)&txcal_params.pkteng.dest))
+		return BCME_USAGE_ERROR;
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	txcal_params.pkteng.delay = strtoul(*argv, NULL, 0);
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	txcal_params.pkteng.length = strtoul(*argv, NULL, 0);
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	txcal_params.pkteng.nframes = strtoul(*argv, NULL, 0);
+	if (txcal_params.pkteng.nframes == 0)
+		txcal_params.pkteng.nframes = 4;
+
+	txcal_params.pkteng.flags = WL_PKTENG_PER_TX_START;
+	txcal_params.pkteng.flags |= WL_PKTENG_SYNCHRONOUS;
+
+	txcal_params.pkteng.flags = htod32(txcal_params.pkteng.flags);
+	txcal_params.pkteng.delay = htod32(txcal_params.pkteng.delay);
+	txcal_params.pkteng.nframes = htod32(txcal_params.pkteng.nframes);
+	txcal_params.pkteng.length = htod32(txcal_params.pkteng.length);
+
+	/* read gidx start */
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+	gidx_str = *argv;
+	gidx_start = strtoul(gidx_str, &endptr, 10);
+	if (*endptr == ':') {
+		endptr++;
+		gidx_str = endptr;
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+
+	/* read gidx step */
+	gidx_step = strtoul(gidx_str, &endptr, 10);
+	if (*endptr == ':') {
+		endptr++;
+		gidx_str = endptr;
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+	if (gidx_step == 0)
+		return BCME_USAGE_ERROR;
+
+	/* read gidx stop */
+	gidx_stop = strtoul(gidx_str, &endptr, 10);
+	if ((*endptr != '\0') && (*endptr != '\n') && (*endptr != ' '))
+		return BCME_USAGE_ERROR;
+
+	txcal_params.gidx_start = gidx_start;
+	txcal_params.gidx_step = gidx_step;
+	txcal_params.gidx_stop = gidx_stop;
+
+	ret = (wlu_var_setbuf(wl, cmd->name, &txcal_params, sizeof(txcal_params)));
+
+	return ret;
+}
+/* wl txcal_pwr_tssi_tbl */
+static int
+wl_txcal_pwr_tssi_tbl(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_txcal_power_tssi_ncore_t * txcal_tssi;
+	wl_txcal_power_tssi_ncore_t * txcal_tssi_old;
+	wl_txcal_power_tssi_percore_t * per_core;
+	wl_txcal_power_tssi_old_t txcal_pwr_tssi;
+	wl_txcal_power_tssi_old_t *txcal_pwr_tssi_ptr;
+
+	/* Total buffer size to be allocated */
+	uint16 buf_size = OFFSETOF(wl_txcal_power_tssi_ncore_t, tssi_percore) +
+		WLC_TXCORE_MAX* sizeof(wl_txcal_power_tssi_percore_t);
+
+	void *ptr = NULL;
+	int err  = BCME_OK;
+	int version_err = BCME_OK;
+	uint8 i, core = 0;
+	uint8 channel = 0;
+	void * buf = NULL;
+	int16 pwr_start = 0;
+	uint8 num_entries = 0;
+
+	/* Allocate buffer for set iovar */
+	buf = malloc(buf_size);
+	if (buf == NULL) {
+		err = BCME_NOMEM;
+		goto fail;
+	}
+	memset(buf, 0, buf_size);
+
+	/* copy older values */
+	txcal_tssi = (wl_txcal_power_tssi_ncore_t *)buf;
+
+	/* core info */
+	if (!(*++argv)) {
+		err = BCME_USAGE_ERROR;
+		goto fail;
+	}
+	core = strtoul(*argv, NULL, 0);
+
+	if (core > (WLC_TXCORE_MAX- 1)) {
+		err = BCME_USAGE_ERROR;
+		goto fail;
+	}
+
+	/* channle info */
+	if (!(*++argv)) {
+		err = BCME_USAGE_ERROR;
+		goto fail;
+	}
+	channel = strtoul(*argv, NULL, 0);
+
+	if (!(*++argv)) {		/* Get */
+
+		version_err = wlu_var_getbuf_sm(wl, "txcal_ver", NULL, 0, &ptr);
+		if ((version_err != BCME_OK) || (*(int*)ptr == 0)) {
+			/* support for firmware with old txcal structures */
+			if ((err = wlu_var_getbuf_med(wl, cmd->name, &channel,
+				sizeof(uint8), &ptr)) < 0)
+		   goto fail;
+			txcal_pwr_tssi_ptr = (wl_txcal_power_tssi_old_t *)ptr;
+			printf("CORE %d\n", core);
+			printf("\tChannel = %d\n", txcal_pwr_tssi_ptr->channel);
+			printf("\tStarting Power = %d\n", txcal_pwr_tssi_ptr->pwr_start[core]);
+			printf("\tNum of Entries = %d\n", txcal_pwr_tssi_ptr->num_entries[core]);
+			printf("\tTSSI values:\n");
+			for (i = 0; i < txcal_pwr_tssi_ptr->num_entries[core]; i++)
+				printf("\t%d\n", txcal_pwr_tssi_ptr->tssi[core][i]);
+
+			goto fail;
+		} else {
+			txcal_tssi->version = TXCAL_IOVAR_VERSION;
+			txcal_tssi->channel = channel;
+			if ((err = wlu_var_getbuf(wl, cmd->name, txcal_tssi, buf_size, &ptr)) < 0)
+				goto fail;
+			txcal_tssi = (wl_txcal_power_tssi_ncore_t *)ptr;
+
+			/* checking txcal version */
+			if (txcal_tssi->version != TXCAL_IOVAR_VERSION) {
+				printf("version %d unsupported \n", txcal_tssi->version);
+				err = BCME_UNSUPPORTED;
+				goto fail;
+			}
+
+			/* support for firmware with new txcal structures
+			 * check for max core support from dongle
+			 */
+			if (core > txcal_tssi->num_core - 1) {
+				printf("Dongle supports only %d cores \n"
+					"Allowed range 0 - %d \n", txcal_tssi->num_core,
+					txcal_tssi->num_core - 1);
+				err = BCME_USAGE_ERROR;
+				goto fail;
+			}
+			/* per core pointer */
+			per_core = txcal_tssi->tssi_percore;
+
+			/* Move to requested core */
+			per_core += core;
+			printf("CORE %d\n", core);
+			printf("\tChannel = %d\n", txcal_tssi->channel);
+			printf("\tStarting Power = %d\n", per_core->pwr_start);
+			printf("\tNum of Entries = %d\n", per_core->num_entries);
+			printf("\tTSSI values:\n");
+			for (i = 0; i < per_core->num_entries; i++)
+				printf("\t%d\n", per_core->tssi[i]);
+
+			goto fail;
+		}
+	} else {
+		argv = argv - 2;
+	}
+	if (*++argv) {
+		pwr_start = strtol(*argv, NULL, 0);
+	} else {
+		err = BCME_USAGE_ERROR;
+		goto fail;
+	}
+
+	if (*++argv) {
+		num_entries = strtoul(*argv, NULL, 0);
+	} else {
+		err = BCME_USAGE_ERROR;
+		goto fail;
+	}
+	if (num_entries >= MAX_NUM_PWR_STEP) {
+		printf("Entries exceeded max allowed\n");
+		err = -1;
+		goto fail;
+	}
+
+	if (*++argv) {
+		channel = strtoul(*argv, NULL, 0);
+	} else {
+		err = BCME_USAGE_ERROR;
+		goto fail;
+	}
+
+	version_err = wlu_var_getbuf_sm(wl, "txcal_ver", NULL, 0, &ptr);
+	if ((version_err != BCME_OK) || (*(int*)ptr == 0)) {
+		/* support for firmware with old txcal structures */
+		if ((err = wlu_var_getbuf_med(wl, cmd->name, &channel, sizeof(uint8), &ptr)) < 0)
+		goto fail;
+	    txcal_pwr_tssi_ptr = ptr;
+		txcal_pwr_tssi = *txcal_pwr_tssi_ptr;
+		txcal_pwr_tssi.channel = channel;
+		txcal_pwr_tssi.set_core = core;
+		txcal_pwr_tssi.pwr_start[core] = pwr_start;
+		txcal_pwr_tssi.num_entries[core] = num_entries;
+
+		if (*++argv) { /* Set */
+			memset(txcal_pwr_tssi.tssi[core], 0,
+			        MAX_NUM_PWR_STEP*sizeof(txcal_pwr_tssi.tssi[0][0]));
+			i = 0;
+			do {
+				if (i >= MAX_NUM_PWR_STEP) {
+					printf("Entries exceeded max allowed\n");
+					err = -1;
+					goto fail;
+				}
+				txcal_pwr_tssi.tssi[core][i] = strtoul(*argv, NULL, 0);
+				i++;
+			} while (*++argv);
+			if (i != txcal_pwr_tssi.num_entries[core]) {
+				printf("Incorrect Number of Entries. Expected %d, Entered %d\n",
+					txcal_pwr_tssi.num_entries[core], i);
+				err = -1;
+				goto fail;
+			}
+			txcal_pwr_tssi.gen_tbl = 0;
+
+
+			if ((err = wlu_var_setbuf(wl, cmd->name, &txcal_pwr_tssi,
+			        sizeof(txcal_pwr_tssi))) < 0)
+				goto fail;
+		} else { /* Generate */
+			txcal_pwr_tssi.gen_tbl = 1;
+			err = wlu_var_setbuf(wl, cmd->name, &txcal_pwr_tssi,
+					sizeof(txcal_pwr_tssi));
+			if ((err = wlu_var_getbuf_med(wl, cmd->name, &channel,
+					sizeof(uint8), &ptr)) < 0)
+				goto fail;
+			txcal_pwr_tssi_ptr = ptr;
+			printf("CORE %d\n", core);
+			printf("\tChannel = %d\n", txcal_pwr_tssi_ptr->channel);
+			printf("Starting Power = %d\n", txcal_pwr_tssi_ptr->pwr_start[core]);
+			printf("Num of Entries = %d\n", txcal_pwr_tssi_ptr->num_entries[core]);
+			printf("TSSI values:\n");
+			for (i = 0; i < txcal_pwr_tssi_ptr->num_entries[core]; i++)
+				printf("%d\n", txcal_pwr_tssi_ptr->tssi[core][i]);
+		}
+
+	} else {
+
+		txcal_tssi->version = TXCAL_IOVAR_VERSION;
+		txcal_tssi->channel = channel;
+		if ((err = wlu_var_getbuf(wl, cmd->name, txcal_tssi, buf_size, &ptr)) < 0)
+			goto fail;
+
+		/* Current copy form fw */
+		txcal_tssi_old = (wl_txcal_power_tssi_ncore_t *)ptr;
+
+		if (txcal_tssi_old->version != TXCAL_IOVAR_VERSION) {
+			printf("version %d unsupported \n", txcal_tssi_old->version);
+			err = BCME_UNSUPPORTED;
+			goto fail;
+		}
+		/* support for firmware with new txcal structures */
+		/* check for max core support from dongle */
+		if (core > txcal_tssi_old->num_core - 1) {
+			printf("Dongle supports only %d  cores \n"
+				"Allowed range 0 - %d\n", txcal_tssi_old->num_core,
+				txcal_tssi_old->num_core - 1);
+			err = BCME_USAGE_ERROR;
+			goto fail;
+		}
+
+		memcpy(txcal_tssi, txcal_tssi_old, buf_size);
+
+		/* Update user input values */
+		txcal_tssi->channel = channel;
+		txcal_tssi->set_core = core;
+
+		/* Move to requested core */
+		per_core = txcal_tssi->tssi_percore;
+		per_core += core;
+
+		/* Update per core info */
+		per_core->pwr_start = pwr_start;
+		per_core->num_entries = num_entries;
+
+		if (*++argv) { /* Set */
+			memset(per_core->tssi, 0, MAX_NUM_PWR_STEP * sizeof(per_core->tssi[0]));
+			i = 0;
+			do {
+				if (i >= MAX_NUM_PWR_STEP) {
+					printf("Entries exceeded max allowed\n");
+					err = -1;
+					goto fail;
+				}
+				per_core->tssi[i] = strtoul(*argv, NULL, 0);
+				i++;
+			} while (*++argv);
+			if (i != num_entries) {
+				printf("Incorrect Number of Entries. Expected %d, Entered %d\n",
+					num_entries, i);
+				err = -1;
+				goto fail;
+			}
+			txcal_tssi->gen_tbl = 0;
+			txcal_tssi->version = TXCAL_IOVAR_VERSION;
+			if ((err = wlu_var_setbuf(wl, cmd->name, txcal_tssi,
+			        buf_size)) < 0)
+				goto fail;
+		} else { /* Generate */
+			txcal_tssi->gen_tbl = 1;
+
+			txcal_tssi->version = TXCAL_IOVAR_VERSION;
+			err = wlu_var_setbuf(wl, cmd->name, txcal_tssi, buf_size);
+
+			txcal_tssi->version = TXCAL_IOVAR_VERSION;
+			txcal_tssi->channel = channel;
+			if ((err = wlu_var_getbuf(wl, cmd->name, txcal_tssi, buf_size, &ptr)) < 0)
+				goto fail;
+
+			txcal_tssi = (wl_txcal_power_tssi_ncore_t *)ptr;
+
+
+			/* Move to requested core */
+			per_core = txcal_tssi->tssi_percore;
+			per_core += core;
+
+			printf("CORE %d\n", core);
+			printf("\tChannel = %d\n", txcal_tssi->channel);
+			printf("Starting Power = %d\n", per_core->pwr_start);
+			printf("Num of Entries = %d\n", per_core->num_entries);
+			printf("TSSI values:\n");
+			for (i = 0; i < per_core->num_entries; i++)
+				printf("%d\n", per_core->tssi[i]);
+		}
+	}
+
+fail:
+	if (buf)
+		free(buf);
+	return err;
+}
+static int
+wl_olpc_anchoridx(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_txcal_power_tssi_old_t txcal_pwr_tssi;
+	wl_txcal_power_tssi_old_t *txcal_pwr_tssi_ptr;
+	wl_olpc_pwr_t *olpc_pwr_ptr, olpc_pwr;
+	void *ptr = NULL;
+	int err = 0;
+	int version_err = BCME_OK;
+	uint8 core = 0;
+	uint8 channel = 0;
+	int16 tempsense = 0;
+	uint8 olpc_idx = 0;
+	uint16 buf_size = sizeof(wl_olpc_pwr_t);
+	if (!(*++argv)) {
+		return BCME_USAGE_ERROR;
+	}
+	core = strtoul(*argv, NULL, 0);
+	if (!(*++argv)) {
+		return BCME_USAGE_ERROR;
+	}
+	channel = strtoul(*argv, NULL, 0);
+	olpc_pwr_ptr = &olpc_pwr;
+	olpc_pwr_ptr->core = core;
+	olpc_pwr_ptr->channel = channel;
+	olpc_pwr_ptr->version = TXCAL_IOVAR_VERSION;
+
+	if (!(*++argv)) {		/* Get */
+		version_err = wlu_var_getbuf_sm(wl, "txcal_ver", NULL, 0, &ptr);
+		if ((version_err != BCME_OK) || (*(int*)ptr == 0)) {
+			/* support for firmware with old txcal structures */
+			if ((err = wlu_var_getbuf_med(wl, cmd->name, &channel,
+				sizeof(uint8), &ptr)) < 0)
+				 return err;
+			txcal_pwr_tssi_ptr = ptr;
+			printf("CORE %d\n", core);
+			printf("\tChannel = %d\n", txcal_pwr_tssi_ptr->channel);
+			printf("\tTemperature = %d\n", txcal_pwr_tssi_ptr->tempsense[core]);
+			printf("\tTx pwr idx at anchor power is %d\n",
+				txcal_pwr_tssi_ptr->pwr_start_idx[core]);
+			return err;
+		} else {
+			if ((err = wlu_var_getbuf_sm(wl, cmd->name, olpc_pwr_ptr,
+				buf_size, &ptr)) < 0)
+				return err;
+			olpc_pwr_ptr = (wl_olpc_pwr_t *)ptr;
+			/* Checking for txcal version */
+			if (olpc_pwr_ptr->version != TXCAL_IOVAR_VERSION) {
+				printf("version %d unsupported \n", olpc_pwr_ptr->version);
+				err = BCME_UNSUPPORTED;
+				return err;
+			}
+			/* support for firmware with new txcal structures */
+			printf("CORE %d\n", core);
+			printf("\tChannel = %d\n", olpc_pwr_ptr->channel);
+			printf("\tTemperature = %d\n", olpc_pwr_ptr->tempsense);
+			printf("\tTx pwr idx at anchor power is %d\n",
+				olpc_pwr_ptr->olpc_idx);
+			return err;
+		}
+	} else {
+		olpc_idx = strtoul(*argv, NULL, 0);
+	}
+	if (!(*++argv))
+		return BCME_USAGE_ERROR;
+
+	tempsense = strtoul(*argv, NULL, 0);
+
+	if (*++argv)
+		return BCME_USAGE_ERROR;
+
+	version_err = wlu_var_getbuf_sm(wl, "txcal_ver", NULL, 0, &ptr);
+	if ((version_err != BCME_OK) || (*(int*)ptr == 0)) {
+		/* support for firmware with old txcal structures */
+		if ((err = wlu_var_getbuf_med(wl, cmd->name, &channel, sizeof(uint8), &ptr)) < 0)
+			return err;
+		txcal_pwr_tssi_ptr = ptr;
+		txcal_pwr_tssi = *txcal_pwr_tssi_ptr;
+		txcal_pwr_tssi.channel = channel;
+		txcal_pwr_tssi.tempsense[core] = tempsense;
+		txcal_pwr_tssi.set_core = core;
+		txcal_pwr_tssi.pwr_start_idx[core] = olpc_idx;
+		if ((err = wlu_var_setbuf(wl, cmd->name, &txcal_pwr_tssi,
+			sizeof(txcal_pwr_tssi))) < 0)
+			return err;
+	} else {
+		/* Checking for txcal version */
+		if ((err = wlu_var_getbuf_sm(wl, cmd->name, olpc_pwr_ptr, buf_size, &ptr)) < 0)
+			return err;
+		txcal_pwr_tssi_ptr = ptr;
+		if (olpc_pwr_ptr->version != TXCAL_IOVAR_VERSION) {
+			printf("version %d unsupported \n", olpc_pwr_ptr->version);
+			err = BCME_UNSUPPORTED;
+			return err;
+		}
+	    /* support for firmware with new txcal structures */
+		olpc_pwr_ptr = &olpc_pwr;
+		olpc_pwr_ptr->channel = channel;
+		olpc_pwr_ptr->tempsense = tempsense;
+		olpc_pwr_ptr->core = core;
+		olpc_pwr_ptr->olpc_idx = olpc_idx;
+		olpc_pwr_ptr->version = TXCAL_IOVAR_VERSION;
+
+		if ((err = wlu_var_setbuf_sm(wl, cmd->name, olpc_pwr_ptr, buf_size)) < 0)
+			return err;
+	}
+	return err;
+}
+
+static int
+wl_read_estpwrlut(void *wl, cmd_t *cmd, char **argv)
+{
+	uint16 *estpwrlut;
+	void *ptr = NULL;
+	int err;
+	uint8 i;
+	int val;
+	char* endptr = NULL;
+
+	argv++;
+
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	val = htod32(strtol(*argv, &endptr, 0));
+	if (*endptr != '\0') {
+		/* not all the value string was parsed by strtol */
+		printf("set: error parsing value \"%s\" as an integer\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	if ((err = wlu_var_getbuf_med(wl, cmd->name, &val, sizeof(val), &ptr)) < 0)
+		return err;
+	estpwrlut = ptr;
+	printf("ESTPWR LUT FOR CORE %d\n", val);
+	for (i = 0; i < 128; i++)
+		printf("%d\n", estpwrlut[i] > 0x7F ? (int16) (estpwrlut[i] - 0x100) : estpwrlut[i]);
+
+	return err;
+}
+
+static int
+wl_olpc_offset(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr = NULL;
+	int err = 0;
+	int8 olpc_offset[5];
+	int8 *olpc_offset_ptr;
+	uint8 i = 0;
+
+	if (!(*++argv)) {
+		if ((err = wlu_var_getbuf_med(wl, cmd->name, NULL, 0, &ptr)) < 0) {
+			return err;
+		}
+		olpc_offset_ptr = ptr;
+		printf("OLPC offset for 2G: %d\n", olpc_offset_ptr[0]);
+		printf("OLPC offset for 5G low/mid/high/x1: %d %d %d %d\n", olpc_offset_ptr[1],
+		       olpc_offset_ptr[2], olpc_offset_ptr[3], olpc_offset_ptr[4]);
+	} else {
+		do {
+			if (i > 4) {
+				return BCME_USAGE_ERROR;
+			}
+
+			olpc_offset[i] = strtol(*argv, NULL, 0);
+			i++;
+		} while (*++argv);
+
+		/* Expect 5 entries */
+		if (i != 5) {
+			return BCME_USAGE_ERROR;
+		}
+
+		if ((err = wlu_var_setbuf(wl, cmd->name, olpc_offset, 5*sizeof(int8))) < 0) {
+			printf("Unable to set olpc_offsets.\n");
+			return BCME_ERROR;
+		}
+	}
+	return err;
+}
+
+static int
+wl_btcoex_desense_rxgain(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_desense_restage_gain_t desense_restage_gain;
+	wl_desense_restage_gain_t *desense_restage_gain_ptr;
+	uint8 num_cores = 0, i;
+	uint32 num_params = 0;
+	int err = 0;
+	void *ptr = NULL;
+
+	memset(&desense_restage_gain, 0, sizeof(desense_restage_gain));
+	desense_restage_gain.version =  0;
+	desense_restage_gain.length = sizeof(desense_restage_gain);
+
+	if (!(*++argv)) {		/* Get */
+		if ((err = wlu_var_getbuf_med(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return err;
+
+		desense_restage_gain_ptr = ptr;
+
+		if (desense_restage_gain_ptr->band == WLC_BAND_2G)
+				printf("Band: 2G\n");
+
+		if (desense_restage_gain_ptr->band == WLC_BAND_5G)
+				printf("Band: 5G\n");
+
+		printf("# of cores: %d\n", desense_restage_gain_ptr->num_cores);
+
+		for (i = 0; i < desense_restage_gain_ptr->num_cores; i++)
+				printf("Desense for core[%d] = %d \n",
+					i, desense_restage_gain_ptr->desense_array[i]);
+
+		return BCME_OK;
+	}
+
+	/* Set */
+	if (strcmp(*argv, "b") == 0) {
+		desense_restage_gain.band = WLC_BAND_2G;
+	} else if (strcmp(*argv, "a") == 0) {
+		desense_restage_gain.band = WLC_BAND_5G;
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+
+	++argv;
+	if (*argv == NULL) {
+		return BCME_USAGE_ERROR;
+	}
+	num_cores = strtoul(*argv, NULL, 0);
+
+	if (num_cores > WL_TX_CHAINS_MAX) {
+		printf("Number of cores %d greater than max value %d\n",
+				num_cores, WL_TX_CHAINS_MAX);
+		return BCME_USAGE_ERROR;
+	}
+
+	desense_restage_gain.num_cores = num_cores;
+
+	++argv;
+	while ((argv[num_params] != NULL) &&
+		(num_params < num_cores)) {
+		desense_restage_gain.desense_array[num_params] =
+			strtoul(argv[num_params], NULL, 0);
+		num_params++;
+	}
+
+	if (num_params != num_cores || (argv[num_params] != NULL)) {
+		printf("Number of parameters(%d) not matching number of cores(%d)\n",
+			num_params, num_cores);
+		return BCME_USAGE_ERROR;
+	}
+
+	return (wlu_var_setbuf(wl, cmd->name, &desense_restage_gain, sizeof(desense_restage_gain)));
+}
diff --git a/wl/src/wl/exe/wluc_pkt_filter.c b/wl/src/wl/exe/wluc_pkt_filter.c
new file mode 100644
index 0000000..6085c49
--- /dev/null
+++ b/wl/src/wl/exe/wluc_pkt_filter.c
@@ -0,0 +1,843 @@
+/*
+ * wl pkt_filter command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_pkt_filter.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_pkt_filter_add;
+static cmd_func_t wl_pkt_filter_enable;
+static cmd_func_t wl_pkt_filter_list;
+static cmd_func_t wl_pkt_filter_stats;
+static cmd_func_t wl_pkt_filter_ports;
+
+static cmd_t wl_pkt_filter_cmds[] = {
+	{ "pkt_filter_add", wl_pkt_filter_add, -1, -1,
+	"Install a packet filter.\n"
+	"\tUsage: wl pkt_filter_add <id> <polarity> <type> <offset> <bitmask> <pattern>\n"
+	"\tid:       Integer. User specified id.\n"
+	"\ttype:     0 (Pattern matching filter)\n"
+	"\t          1 (Magic pattern match (variable offset)\n"
+	"\t          2 (Extended pattern list)\n"
+	"\t          4 (Android Packet Filter)\n"
+	"\t          5 (Pattern matching filter with timeout event)\n"
+	"\t          6 (Immediate Packet filter)\n"
+	"\toffset:   (type 0): Integer offset in received packet to start matching.\n"
+	"\t          (type 1): Integer offset, match here are anywhere later.\n"
+	"\t          (type 2): [<base>:]<offset>. Symbolic packet loc plus relative\n"
+	"\t                    offset, use wl_pkt_filter_add -l for a <base> list.\n"
+	"\t          (type 5): Integer offset in received packet to start matching.\n"
+	"\t          (type 6): [<base>:]<offset>. Symbolic packet loc plus relative\n"
+	"\t                    offset, use wl_pkt_filter_add -l for a <base> list.\n"
+	"\tpolarity: Set to 1 to negate match result. 0 is default.\n"
+	"\tbitmask:  Hex bitmask that indicates which bits of 'pattern' to match.\n"
+	"\t          Must be same size as 'pattern'. Bit 0 of bitmask corresponds\n"
+	"\t          to bit 0 of pattern, etc.  If bit N of bitmask is 0, then do\n"
+	"\t          *not* match bit N of the pattern with the received payload. If\n"
+	"\t          bit N of bitmask is 1, then perform match.\n"
+	"\tpattern:  Hex pattern to match.  Must be same size as <bitmask>.\n"
+	"\t          Syntax: same as bitmask, but for type 2 (pattern list), a '!'\n"
+	"\t          may be used to negate that pattern match (e.g. !0xff03).\n"
+	"\tFor type 2 & 6: [<base>:]<offset> <bitmask> [!]<pattern> triple may be\n"
+	"\trepeated; all sub-patterns must match for the filter to match.\n"
+	"\tFor type 4: <id> <polarity> <type> <apf program> \n"
+	"\ttimeout:  (type 5): Number of seconds to wait before sending a timeout event when\n"
+	"\t                    a matching pattern packet is not received.\n"},
+	{ "pkt_filter_clear_stats", wl_varint, -1, WLC_SET_VAR,
+	"Clear packet filter statistic counter values.\n"
+	"\tUsage: wl pkt_filter_clear_stats <id>" },
+	{ "pkt_filter_enable", wl_pkt_filter_enable, -1, -1,
+	"Enable/disable a packet filter.\n"
+	"\tUsage: wl pkt_filter_enable <id> <0|1>"},
+	{ "pkt_filter_list", wl_pkt_filter_list, -1, -1,
+	"List installed packet filters.\n"
+	"\tUsage: wl pkt_filter_list [val]\n"
+	"\tval: 0 (disabled filters) 1 (enabled filters)"},
+	{ "pkt_filter_mode", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set packet filter match action.\n"
+	"\tUsage: wl pkt_filter_mode <value>\n"
+	"\tvalue: 1 - Forward packet on match, discard on non-match (default).\n"
+	"\t       0 - Discard packet on match, forward on non-match." },
+	{ "pkt_filter_delete", wl_varint, -1, WLC_SET_VAR,
+	"Uninstall a packet filter.\n"
+	"\tUsage: wl pkt_filter_delete <id>"},
+	{ "pkt_filter_stats", wl_pkt_filter_stats, -1, -1,
+	"Retrieve packet filter statistic counter values.\n"
+	"\tUsage: wl pkt_filter_stats <id>"},
+	{ "pkt_filter_ports", wl_pkt_filter_ports, WLC_GET_VAR, WLC_SET_VAR,
+	"Set up additional port filters for TCP and UDP packets.\n"
+	"\tUsage: wl pkt_filter_ports [<port-number>] ...\n"
+	"\t       wl pkt_filter_ports none (to clear/disable)"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_pkt_filter_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register pkt_filter commands */
+	wl_module_cmds_register(wl_pkt_filter_cmds);
+}
+
+/* Packet filter section: extended filters have named offsets, add table here */
+typedef struct {
+	char *name;
+	uint16 base;
+} wl_pfbase_t;
+
+static wl_pfbase_t basenames[] = { WL_PKT_FILTER_BASE_NAMES };
+
+static void
+wl_pkt_filter_base_list(void)
+{
+	uint i;
+
+	printf("Names accepted for base offsets:\n");
+	for (i = 0; i < ARRAYSIZE(basenames); i++)
+	{
+		printf("\t%s\n", basenames[i].name);
+	}
+}
+
+static int
+wl_pkt_filter_base_parse(char *name)
+{
+	uint i;
+	char *bname, *uname;
+
+	for (i = 0; i < ARRAYSIZE(basenames); i++) {
+		bname = basenames[i].name;
+		for (uname = name; *uname; bname++, uname++) {
+			if (*bname != toupper(*uname))
+				break;
+		}
+		if (!*uname && !*bname)
+			break;
+	}
+
+	if (i < ARRAYSIZE(basenames)) {
+		return basenames[i].base;
+	} else {
+		return -1;
+	}
+}
+
+static char *
+wl_pkt_filter_base_show(uint16 base)
+{
+	uint i;
+	static char numeric[6];
+
+	for (i = 0; i < ARRAYSIZE(basenames); i++) {
+		if (basenames[i].base == base)
+			return basenames[i].name;
+	}
+
+	sprintf(numeric, "%d", base);
+	return numeric;
+}
+
+/* Enable/disable installed packet filter. */
+static int
+wl_pkt_filter_enable(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pkt_filter_enable_t	enable_parm;
+	int							rc;
+
+	if (*++argv == NULL) {
+		printf("No args provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Parse packet filter id. */
+	enable_parm.id = htod32(strtoul(*argv, NULL, 0));
+
+	if (*++argv == NULL) {
+		printf("Enable/disable value not provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Parse enable/disable value. */
+	enable_parm.enable = htod32(strtoul(*argv, NULL, 0));
+
+
+	/* Enable/disable the specified filter. */
+	rc = wlu_var_setbuf(wl,
+	                   cmd->name,
+	                   &enable_parm,
+	                   sizeof(wl_pkt_filter_enable_t));
+
+	return (rc);
+}
+
+
+/* Install a new packet filter. */
+static int
+wl_pkt_filter_add(void *wl, cmd_t *cmd, char **argv)
+{
+	const char          *str;
+	wl_pkt_filter_t     pkt_filter;
+	wl_pkt_filter_t     *pkt_filterp;
+	int                 buf_len;
+	int                 str_len;
+	int                 rc;
+	uint32              mask_size;
+	uint32              pattern_size;
+	uint                ftype;
+	char                *endptr;
+
+	UNUSED_PARAMETER(cmd);
+
+	str = "pkt_filter_add";
+	str_len = strlen(str);
+	strncpy(buf, str, str_len);
+	buf[ str_len ] = '\0';
+	buf_len = str_len + 1;
+
+	pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
+
+	if (argv[1] && strcmp(argv[1], "-l") == 0) {
+		wl_pkt_filter_base_list();
+		return BCME_OK;
+	}
+
+	/* Parse packet filter id. */
+	if (*++argv == NULL) {
+		printf("No args provided\n");
+		return BCME_USAGE_ERROR;
+	}
+	pkt_filter.id = htod32(strtoul(*argv, &endptr, 0));
+	if (*endptr) {
+		printf("Invalid number for id: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Parse filter polarity. */
+	if (*++argv == NULL) {
+		printf("Polarity not provided\n");
+		return BCME_USAGE_ERROR;
+	}
+	pkt_filter.negate_match = htod32(strtoul(*argv, &endptr, 0));
+	if (*endptr) {
+		printf("Invalid number for polarity: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Parse filter type. */
+	if (*++argv == NULL) {
+		printf("Filter type not provided\n");
+		return BCME_USAGE_ERROR;
+	}
+	pkt_filter.type = htod32(strtoul(*argv, &endptr, 0));
+	ftype = htod32(strtoul(*argv, &endptr, 0));
+	if (*endptr) {
+		printf("Invalid number for filter type: %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+	if ((ftype != WL_PKT_FILTER_TYPE_PATTERN_MATCH) &&
+		(ftype != WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH) &&
+		(ftype != WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH) &&
+		(ftype != WL_PKT_FILTER_TYPE_APF_MATCH) &&
+		(ftype != WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT) &&
+		(ftype != WL_PKT_FILTER_TYPE_IMMEDIATE_PATTERN_MATCH)) {
+		printf("Invalid filter type %d\n", ftype);
+		return BCME_USAGE_ERROR;
+	}
+	pkt_filter.type = htod32(ftype);
+
+	/* Handle basic (or magic) pattern filter */
+	if ((ftype == WL_PKT_FILTER_TYPE_PATTERN_MATCH) ||
+		(ftype == WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH)) {
+		wl_pkt_filter_pattern_t *pfilter = &pkt_filterp->u.pattern;
+
+		/* Parse pattern filter offset. */
+		if (*++argv == NULL) {
+			printf("Offset not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		pkt_filter.u.pattern.offset = htod32(strtoul(*argv, &endptr, 0));
+		if (*endptr) {
+			printf("Invalid number for offset: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* Parse pattern filter mask. */
+		if (*++argv == NULL) {
+			printf("Bitmask not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		rc =   wl_pattern_atoh(*argv, (char *)pfilter->mask_and_pattern);
+		if (rc == -1) {
+			printf("Rejecting: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		mask_size = htod32(rc);
+
+		/* Parse pattern filter pattern. */
+		if (*++argv == NULL) {
+			printf("Pattern not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		rc = wl_pattern_atoh(*argv, (char *)&pfilter->mask_and_pattern[rc]);
+		if (rc == -1) {
+			printf("Rejecting: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		pattern_size = htod32(rc);
+
+		if (mask_size != pattern_size) {
+			printf("Mask and pattern not the same size\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		pkt_filter.u.pattern.size_bytes = mask_size;
+		buf_len += WL_PKT_FILTER_FIXED_LEN;
+		buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * rc);
+
+		/* The fields that were put in a local for alignment purposes now
+		 * get copied to the right place in the ioctl buffer.
+		 */
+		memcpy((char *)pkt_filterp, &pkt_filter,
+		       WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
+	}
+
+	/* Handle pattern list */
+	if ((ftype == WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH) ||
+		(ftype == WL_PKT_FILTER_TYPE_IMMEDIATE_PATTERN_MATCH)) {
+		int list_cnt = 0;
+		wl_pkt_filter_pattern_listel_t *pf_el = &pkt_filterp->u.patlist.patterns[0];
+
+		while (*++argv != NULL) {
+			/* Parse pattern filter base and offset. */
+			if (isdigit(**argv)) {
+				/* Numeric base */
+				rc = strtoul(*argv, &endptr, 0);
+			} else {
+				endptr = strchr(*argv, ':');
+				if (endptr) {
+					*endptr = '\0';
+					rc = wl_pkt_filter_base_parse(*argv);
+					if (rc == -1) {
+						printf("Invalid base %s\n", *argv);
+						wl_pkt_filter_base_list();
+						return BCME_USAGE_ERROR;
+					}
+					*endptr = ':';
+				} else {
+					printf("Invalid [base:]offset format: %s\n", *argv);
+					return BCME_USAGE_ERROR;
+				}
+			}
+
+			if (*endptr == ':') {
+				pkt_filter.u.patlist.patterns[0].base_offs = htod16(rc);
+				rc = strtoul(endptr + 1, &endptr, 0);
+			} else {
+				/* Must have had a numeric offset only */
+				pkt_filter.u.patlist.patterns[0].base_offs = htod16(0);
+			}
+
+		        if (*endptr) {
+				printf("Invalid [base:]offset format: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+			if (rc > 0x0000FFFF) {
+				printf("Offset too large\n");
+				return BCME_USAGE_ERROR;
+			}
+			pkt_filter.u.patlist.patterns[0].rel_offs = htod16(rc);
+
+			/* Clear match_flag (may be set in parsing which follows) */
+			pkt_filter.u.patlist.patterns[0].match_flags = htod16(0);
+
+			/* Parse pattern filter mask and pattern directly into ioctl buffer */
+			if (*++argv == NULL) {
+				printf("Bitmask not provided\n");
+				return BCME_USAGE_ERROR;
+			}
+			rc = wl_pattern_atoh(*argv, (char*)pf_el->mask_and_data);
+			if (rc == -1) {
+				printf("Rejecting: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+			mask_size = htod16(rc);
+
+			if (*++argv == NULL) {
+				printf("Pattern not provided\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			if (**argv == '!') {
+				pkt_filter.u.patlist.patterns[0].match_flags =
+				        htod16(WL_PKT_FILTER_MFLAG_NEG);
+				(*argv)++;
+			}
+			if (*argv == '\0') {
+				printf("Pattern not provided\n");
+				return BCME_USAGE_ERROR;
+			}
+			rc = wl_pattern_atoh(*argv, (char*)&pf_el->mask_and_data[rc]);
+			if (rc == -1) {
+				printf("Rejecting: %s\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+			pattern_size = htod16(rc);
+
+			if (mask_size != pattern_size) {
+				printf("Mask and pattern not the same size\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			pkt_filter.u.patlist.patterns[0].size_bytes = mask_size;
+
+
+			/* Account for the size of this pattern element */
+			buf_len += WL_PKT_FILTER_PATTERN_LISTEL_FIXED_LEN + 2 * rc;
+
+			/* And the pattern element fields that were put in a local for
+			 * alignment purposes now get copied to the ioctl buffer.
+			 */
+			memcpy((char*)pf_el, &pkt_filter.u.patlist.patterns[0],
+			       WL_PKT_FILTER_PATTERN_FIXED_LEN);
+
+			/* Move to next element location in ioctl buffer */
+			pf_el = (wl_pkt_filter_pattern_listel_t*)
+			        ((uint8*)pf_el + WL_PKT_FILTER_PATTERN_LISTEL_FIXED_LEN + 2 * rc);
+
+			/* Count list element */
+			list_cnt++;
+		}
+
+		/* Account for initial fixed size, and copy initial fixed fields */
+		buf_len += WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_LIST_FIXED_LEN;
+
+		/* Update list count and total size */
+		pkt_filter.u.patlist.list_cnt = list_cnt;
+		pkt_filter.u.patlist.PAD1[0] = 0;
+		pkt_filter.u.patlist.totsize = buf + buf_len - (char*)pkt_filterp;
+		pkt_filter.u.patlist.totsize -= WL_PKT_FILTER_FIXED_LEN;
+
+		memcpy((char *)pkt_filterp, &pkt_filter,
+		       WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_LIST_FIXED_LEN);
+	}
+	/* Android Packet Filter */
+	if (ftype == WL_PKT_FILTER_TYPE_APF_MATCH) {
+		wl_apf_program_t *apf_program = &pkt_filterp->u.apf_program;
+		char *token = *++argv;
+		int count;
+		char num[3];
+
+		if (strlen(token) % 2) {
+			printf("Invalid APF program length: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		for (count = 0; *token != '\0'; count++, token += 2) {
+			strncpy(num, token, 2);
+			num[2] = '\0';
+			apf_program->instrs[count] = (uint8)strtoul(num, NULL, 16);
+		}
+		apf_program->instr_len = htod16(count);
+		apf_program->version = htod16(WL_APF_INTERNAL_VERSION);
+
+		buf_len += WL_PKT_FILTER_FIXED_LEN;
+		buf_len += WL_APF_PROGRAM_TOTAL_LEN(apf_program);
+
+		memcpy((char *)pkt_filterp, &pkt_filter, WL_PKT_FILTER_FIXED_LEN);
+	}
+
+	/* Handle pattern filter with timeout event */
+	if (ftype == WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT) {
+		wl_pkt_filter_pattern_timeout_t *pfilter = &pkt_filterp->u.pattern_timeout;
+
+		/* Parse pattern filter offset. */
+		if (*++argv == NULL) {
+			printf("Offset not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		pkt_filter.u.pattern.offset = htod32(strtoul(*argv, &endptr, 0));
+		if (*endptr) {
+			printf("Invalid number for offset: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		/* Parse pattern filter mask. */
+		if (*++argv == NULL) {
+			printf("Bitmask not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		rc = wl_pattern_atoh(*argv, (char *)pfilter->mask_and_pattern);
+		if (rc == -1) {
+			printf("Rejecting: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		mask_size = htod32(rc);
+
+		/* Parse pattern filter pattern. */
+		if (*++argv == NULL) {
+			printf("Pattern not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		rc = wl_pattern_atoh(*argv, (char *)&pfilter->mask_and_pattern[rc]);
+		if (rc == -1) {
+			printf("Rejecting: %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+		pattern_size = htod32(rc);
+
+		if (mask_size != pattern_size) {
+			printf("Mask and pattern not the same size\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if (*++argv == NULL) {
+			printf("timeout not specified\n");
+			return BCME_USAGE_ERROR;
+		}
+		pkt_filter.u.pattern_timeout.timeout = htod32(strtoul(*argv, &endptr, 0));
+		pkt_filter.u.pattern.size_bytes = mask_size;
+		buf_len += WL_PKT_FILTER_FIXED_LEN;
+		buf_len += (WL_PKT_FILTER_PATTERN_TIMEOUT_FIXED_LEN + 2 * rc);
+
+		/* The fields that were put in a local for alignment purposes now
+		 * get copied to the right place in the ioctl buffer.
+		 */
+		memcpy((char *)pkt_filterp, &pkt_filter,
+				WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_TIMEOUT_FIXED_LEN);
+	}
+
+	rc = wlu_set(wl, WLC_SET_VAR, buf, buf_len);
+
+	return (rc);
+}
+
+/* List installed packet filters. */
+static void
+wl_pkt_filter_list_mask_pat(uint8 *bytes, uint size, char *indent)
+{
+	uint j;
+
+	printf("%sMask        :0x", indent);
+
+	for (j = 0; j < size; j++)
+		printf("%02x", bytes[j]);
+
+	printf("\n%sPattern     :0x", indent);
+
+	for (; j < 2 * size; j++)
+		printf("%02x", bytes[j]);
+
+	printf("\n\n");
+}
+
+/* List installed packet filters. */
+static int
+wl_pkt_filter_list(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pkt_filter_list_t	*list;
+	wl_pkt_filter_t		*filterp;
+	void						*ptr = NULL;
+	unsigned int			i;
+	unsigned int			j;
+	int 						rc;
+	unsigned int			filter_len;
+	uint32					enable;
+
+
+	if (*++argv == NULL) {
+		printf("No args provided\n");
+		return (BCME_USAGE_ERROR);
+	}
+
+	/* Parse filter list to retrieve (enabled/disabled). */
+	enable = htod32(strtoul(*argv, NULL, 0));
+	/*
+	** Get list of installed packet filters.
+	*/
+	if ((rc = wlu_var_getbuf(wl, cmd->name, &enable, sizeof(enable), &ptr)) < 0)
+		return rc;
+
+	list = (wl_pkt_filter_list_t *) ptr;
+
+	printf("Num filters: %d\n\n", list->num);
+
+	filterp = list->filter;
+	for (i = 0; i < list->num; i++)
+	{
+		uint type = dtoh32(filterp->type);
+
+		if (type == WL_PKT_FILTER_TYPE_PATTERN_MATCH_TIMEOUT) {
+			printf("Id          :%d\n"
+				"Negate      :%d\n"
+				"Type        :%d\n"
+				"Offset      :%d\n"
+				"Pattern len :%d\n"
+				"Timeout     :%d seconds\n",
+				dtoh32(filterp->id),
+				dtoh32(filterp->negate_match),
+				dtoh32(filterp->type),
+				dtoh32(filterp->u.pattern_timeout.offset),
+				dtoh32(filterp->u.pattern_timeout.size_bytes),
+				dtoh32(filterp->u.pattern_timeout.timeout));
+
+			wl_pkt_filter_list_mask_pat(filterp->u.pattern_timeout.mask_and_pattern,
+				dtoh32(filterp->u.pattern_timeout.size_bytes), "");
+			filter_len = WL_PKT_FILTER_PATTERN_TIMEOUT_FIXED_LEN +
+					2 * dtoh32(filterp->u.pattern_timeout.size_bytes);
+		} else if (type == WL_PKT_FILTER_TYPE_APF_MATCH) {
+			wl_apf_program_t *apf_program;
+			uint8 *pc;
+			uint16 len;
+
+			apf_program = &filterp->u.apf_program;
+			pc = apf_program->instrs;
+			len = dtoh16(apf_program->instr_len);
+
+			if (dtoh16(apf_program->version) != WL_APF_INTERNAL_VERSION) {
+				printf("%s: APF: incorrect version, version=%d, "
+					"expected version=%d\n", __FUNCTION__,
+					dtoh16(apf_program->version), WL_APF_INTERNAL_VERSION);
+				rc = BCME_BADARG;
+				break;
+			}
+			printf("Id          :%d\n"
+			       "Negate      :%d\n"
+			       "Type        :%d\n"
+			       "Program len :%d\n",
+			       dtoh32(filterp->id),
+			       dtoh32(filterp->negate_match),
+			       dtoh32(filterp->type),
+			       len);
+			printf("Program		:");
+			for (j = 0; pc && (j < len); pc++, j++) {
+				printf("%02X", *pc);
+			}
+			printf("\n\n");
+			filter_len = WL_APF_PROGRAM_TOTAL_LEN(apf_program);
+		} else if ((type == WL_PKT_FILTER_TYPE_PATTERN_LIST_MATCH) ||
+			(type == WL_PKT_FILTER_TYPE_IMMEDIATE_PATTERN_MATCH)) {
+			char *indent = "    ";
+			uint cnt = filterp->u.patlist.list_cnt;
+			wl_pkt_filter_pattern_listel_t *listel = filterp->u.patlist.patterns;
+
+			printf("Id          :%d\n"
+			       "Negate      :%d\n"
+			       "Type        :%d\n"
+			       "List count  :%d\n",
+			       dtoh32(filterp->id),
+			       dtoh32(filterp->negate_match),
+			       dtoh32(filterp->type),
+			       cnt);
+
+			for (j = 1; j <= cnt; j++) {
+				printf("%sPattern %d\n", indent, j);
+				printf("%sOffset      :%s:%d\n"
+				       "%sMatch flags :%04x\n"
+				       "%sPattern len :%d\n",
+				       indent, wl_pkt_filter_base_show(dtoh16(listel->base_offs)),
+				       dtoh16(listel->rel_offs),
+				       indent, dtoh16(listel->match_flags),
+				       indent, dtoh16(listel->size_bytes));
+				wl_pkt_filter_list_mask_pat(listel->mask_and_data,
+				                            dtoh16(listel->size_bytes), indent);
+				listel = (wl_pkt_filter_pattern_listel_t*)
+				        ((uintptr)listel +
+				         WL_PKT_FILTER_PATTERN_LISTEL_FIXED_LEN +
+				         2 * dtoh16(listel->size_bytes));
+			}
+
+			filter_len = (uint8*)listel - (uint8*)&filterp->u.patlist;
+		} else {
+			printf("Id          :%d\n"
+			       "Negate      :%d\n"
+			       "Type        :%d\n"
+			       "Offset      :%d\n"
+			       "Pattern len :%d\n",
+			       dtoh32(filterp->id),
+			       dtoh32(filterp->negate_match),
+			       dtoh32(filterp->type),
+			       dtoh32(filterp->u.pattern.offset),
+			       dtoh32(filterp->u.pattern.size_bytes));
+
+			wl_pkt_filter_list_mask_pat(filterp->u.pattern.mask_and_pattern,
+			                            dtoh32(filterp->u.pattern.size_bytes), "");
+			filter_len = WL_PKT_FILTER_PATTERN_FIXED_LEN +
+			        2 * dtoh32(filterp->u.pattern.size_bytes);
+		}
+
+		filter_len += WL_PKT_FILTER_FIXED_LEN;
+		filterp = (wl_pkt_filter_t *) ((uint8 *)filterp + filter_len);
+		filterp = ALIGN_ADDR(filterp, sizeof(uint32));
+
+	}
+
+	return (rc);
+}
+
+/* Get packet filter debug statistics. */
+static int
+wl_pkt_filter_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_pkt_filter_stats_t	*stats;
+	uint32						id;
+	int 							rc;
+	void							*ptr = NULL;
+
+	if (*++argv == NULL) {
+		printf("No args provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Parse filter id to retrieve. */
+	id = htod32(strtoul(*argv, NULL, 0));
+
+
+	/* Get debug stats. */
+	if ((rc = wlu_var_getbuf(wl, cmd->name, &id, sizeof(id), &ptr)) < 0)
+		return rc;
+
+	stats = (wl_pkt_filter_stats_t *) ptr;
+
+	printf("Packets matched for filter '%d': %d\n"
+			 "Total packets discarded        : %d\n"
+			 "Total packet forwarded         : %d\n",
+			 id,
+			 dtoh32(stats->num_pkts_matched),
+			 dtoh32(stats->num_pkts_discarded),
+			 dtoh32(stats->num_pkts_forwarded));
+
+	return (rc);
+}
+
+/* Get/set packet filter port list */
+static int
+wl_pkt_filter_ports(void *wl, cmd_t *cmd, char **argv)
+{
+	int rc, i;
+	void *ptr;
+	uint16 count;
+	uint16 *ports;
+	wl_pkt_filter_ports_t *portlist;
+
+	uint len;
+	char *endptr = NULL;
+	unsigned long portnum;
+
+	if ((strlen("pkt_filter_ports") + 1 +
+	     WL_PKT_FILTER_PORTS_FIXED_LEN +
+	     sizeof(uint16) * WL_PKT_FILTER_PORTS_MAX) > WLC_IOCTL_MEDLEN) {
+		fprintf(stderr, "Ioctl sizing error.\n");
+		return -1;
+	}
+
+	if (*++argv == NULL) {
+		/* Get iovar */
+		if ((rc = wlu_var_getbuf_med(wl, cmd->name, NULL, 0, &ptr)))
+			return rc;
+
+		portlist = (wl_pkt_filter_ports_t*)ptr;
+		count = dtoh16(portlist->count);
+		ports = &portlist->ports[0];
+
+		/* Bail if anything in the headeer is unexpected */
+		if (portlist->version != WL_PKT_FILTER_PORTS_VERSION) {
+			printf("Unsupported version %d, only support %d\n",
+			       portlist->version, WL_PKT_FILTER_PORTS_VERSION);
+			return BCME_USAGE_ERROR;
+		}
+		if (portlist->reserved != 0) {
+			printf("Format error: nonzero reserved element 0x%02x\n",
+			       portlist->reserved);
+			return BCME_USAGE_ERROR;
+		}
+		if (count > WL_PKT_FILTER_PORTS_MAX) {
+			printf("Invalid count %d\n", count);
+			return BCME_USAGE_ERROR;
+		}
+
+		printf("Port count %d:\n", count);
+		for (i = 0; i < count; i++) {
+			printf("%d\n", dtoh16(ports[i]));
+		}
+
+		return 0;
+
+	} else {
+		/* Set iovar - build the structure in the global buffer */
+		portlist = (wl_pkt_filter_ports_t*)buf;
+		portlist->version = WL_PKT_FILTER_PORTS_VERSION;
+		portlist->reserved = 0;
+
+		ports = &portlist->ports[0];
+
+		for (count = 0; *argv && (count < WL_PKT_FILTER_PORTS_MAX); count++, argv++) {
+			portnum = strtoul(*argv, &endptr, 0);
+			if ((*endptr != '\0') || (portnum > 0xffff)) {
+				if (!strcmp(*argv, "none")) {
+					argv += 1;
+					break;
+				} else {
+					printf("Bad port number %s\n", *argv);
+					return BCME_USAGE_ERROR;
+				}
+			}
+			ports[count] = htod16((uint16)portnum);
+		}
+
+		if (*argv) {
+			printf("Too many port numbers!\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		portlist->count = htod16(count);
+
+		len = WL_PKT_FILTER_PORTS_FIXED_LEN + (count * sizeof(uint16));
+		memmove((buf + strlen("pkt_filter_ports") + 1), buf, len);
+		strcpy(buf, "pkt_filter_ports");
+		len += strlen("pkt_filter_ports") + 1;
+
+		return wlu_set(wl, WLC_SET_VAR, buf, len);
+	}
+}
diff --git a/wl/src/wl/exe/wluc_prot_obss.c b/wl/src/wl/exe/wluc_prot_obss.c
new file mode 100644
index 0000000..7698551
--- /dev/null
+++ b/wl/src/wl/exe/wluc_prot_obss.c
@@ -0,0 +1,248 @@
+/*
+ * wl prot_obss command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_prot_obss.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+static cmd_func_t wl_ccastats;
+#endif
+static cmd_func_t wl_dyn_bwsw_params;
+
+static cmd_t wl_prot_obss_cmds[] = {
+	{ "obss_prot", wl_bcm_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/set OBSS protection (-1=auto, 0=disable, 1=enable)\n" },
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+	{ "dump_obss", wl_ccastats, WLC_GET_VAR, -1,
+	"Usage: \n\t wl dump_obss [-d num msecs] to begin measurement\n"
+	"\t wl dump_obss to query for the measurement results" },
+	{ "ccastats", wl_ccastats, WLC_GET_VAR, -1,
+	"Usage: \n\t wl ccastats [-d num msecs] to begin measurement\n"
+	"\t wl ccastats [-o option: 0=default, 1=detail, 2=1+CRS] to query for measurements" },
+	{ "dump_obss_dyn_bwsw", wl_ccastats, WLC_GET_VAR, -1,
+	"Usage: \n\t wl dump_obss_dyn_bwsw [-d num msecs] to begin measurement\n"
+	"\t wl dump_obss_dyn_bwsw to query for the results" },
+#endif
+	{ "dyn_bwsw_params", wl_dyn_bwsw_params, WLC_GET_VAR, WLC_SET_VAR,
+	"Configure the params for dynamic bandswitch\n"
+	"\tUsage (Get): wl dyn_bwsw_params \n"
+	"\tUsage (Set): wl dyn_bwsw_params actvcfm=0x03 noactcfm=0x06\n"
+	"			noactincr=0x05 psense=2000\n"
+	"			rxcrsthresh=0x20 secdurlim=30 \n"
+	"\t To reset to default value give val 0\n"
+	"\t Example : wl dyn_bwsw_params rxcrsthresh=0\n" },
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_prot_obss_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register prot_obss commands */
+	wl_module_cmds_register(wl_prot_obss_cmds);
+}
+
+#if defined(BCMDBG) || defined(BCMDBG_DUMP)
+static int
+wl_ccastats(void *wl, cmd_t *cmd, char **argv)
+{
+	cca_stats_n_flags *results;
+	int err = 0;
+	int msr_time;
+	uint8 option = 0;
+	cca_msrmnt_query req;
+	char *ptr;
+
+	/* skip the command name */
+	argv++;
+
+	/* only switch -d for now */
+	if (*argv != NULL && !strcmp(*argv, "-d")) {
+		argv++;
+		if (*argv == NULL || (msr_time = htod32(atoi(*argv))) <= 0) {
+			printf("enter correct duration\n");
+			return 0;
+		}
+		req.msrmnt_query = 0;
+		req.time_req = msr_time;
+
+		if ((err = wlu_iovar_getbuf(wl, cmd->name, &req, sizeof(req),
+		                            buf, WLC_IOCTL_MAXLEN)) < 0) {
+			return err;
+		}
+
+		printf("Measuring %d ms ...\n", msr_time);
+	} else {
+		if (*argv != NULL && !strcmp(*argv, "-o")) {
+			argv++;
+			if (*argv != NULL) {
+				option = (uint8)htod32(atoi(*argv));
+			}
+		}
+
+		req.msrmnt_query = 1;
+		req.time_req = 0;
+		req.report_opt = option;
+
+		// retrieving the results
+		if ((err = wlu_iovar_getbuf(wl, cmd->name, &req, sizeof(req),
+		    buf, WLC_IOCTL_MAXLEN)) < 0) {
+			return err;
+		}
+
+		results = (cca_stats_n_flags *)buf;
+		ptr = results->buf;
+
+		fputs(ptr, stdout);
+	}
+
+	return err;
+}
+#endif 
+
+/* static function for iovar dyn_bwsw_params */
+static INLINE void
+dynbwsw_config_params(uint32 mask, uint32 *cfg_flag,
+	uint32 *rst_flag, uint val)
+{
+	(!val) ? (*rst_flag = (*rst_flag | mask)) : (*cfg_flag = (*cfg_flag | mask));
+}
+
+/* Given an argument String, Set/Get the dynamic bandswitch parameters */
+static int
+wl_dyn_bwsw_params(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	uint val;
+	void *ptr;
+	obss_config_params_t *params;
+	wlc_obss_dynbwsw_config_t *config_params;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) { /* write dyn_bwsw parameters */
+		params = (obss_config_params_t *)malloc(sizeof(obss_config_params_t));
+
+		if (params == NULL) {
+			printf("memory alloc failure\n");
+			return BCME_NOMEM;
+		}
+
+		config_params = &params->config_params;
+		params->reset_mask = 0x0000;
+		params->config_mask = 0x0000;
+		params->version = WL_PROT_OBSS_CONFIG_PARAMS_VERSION;
+
+		if (find_pattern(argv, "actvcfm", &val)) {
+			dynbwsw_config_params(WL_OBSS_DYN_BWSW_FLAG_ACTIVITY_PERIOD,
+				&params->config_mask, &params->reset_mask, val);
+			config_params->obss_bwsw_activity_cfm_count_cfg =
+				val;
+		}
+
+		if (find_pattern(argv, "noactcfm", &val)) {
+			dynbwsw_config_params(WL_OBSS_DYN_BWSW_FLAG_NOACTIVITY_PERIOD,
+				&params->config_mask, &params->reset_mask, val);
+
+			config_params->obss_bwsw_no_activity_cfm_count_cfg =
+				val;
+		}
+		if (find_pattern(argv, "noactincr", &val)) {
+			dynbwsw_config_params(WL_OBSS_DYN_BWSW_FLAG_NOACTIVITY_INCR_PERIOD,
+				&params->config_mask, &params->reset_mask, val);
+			config_params->obss_bwsw_no_activity_cfm_count_incr_cfg =
+				val;
+		}
+
+		if (find_pattern(argv, "psense", &val)) {
+			dynbwsw_config_params(WL_OBSS_DYN_BWSW_FLAG_PSEUDO_SENSE_PERIOD,
+				&params->config_mask, &params->reset_mask, val);
+			config_params->obss_bwsw_pseudo_sense_count_cfg = val;
+		}
+
+		if (find_pattern(argv, "rxcrsthresh", &val)) {
+			dynbwsw_config_params(WL_OBSS_DYN_BWSW_FLAG_RX_CRS_PERIOD,
+				&params->config_mask, &params->reset_mask, val);
+			config_params->obss_bwsw_rx_crs_threshold_cfg = val;
+		}
+		if (find_pattern(argv, "secdurlim", &val)) {
+			dynbwsw_config_params(WL_OBSS_DYN_BWSW_FLAG_DUR_THRESHOLD,
+				&params->config_mask, &params->reset_mask, val);
+			config_params->obss_bwsw_dur_thres = val;
+		}
+		if (find_pattern(argv, "txopthresh", &val)) {
+			dynbwsw_config_params(WL_OBSS_DYN_BWSW_FLAG_TXOP_PERIOD,
+			&params->config_mask, &params->reset_mask, val);
+			config_params->obss_bwsw_txop_threshold_cfg = val;
+		}
+		if ((err = wlu_var_setbuf(wl, "dyn_bwsw_params", params,
+			sizeof(obss_config_params_t)) < 0)) {
+			printf("wl_dyn_bwsw_params: fail to set %d\n", err);
+		}
+		config_params = NULL;
+		free(params);
+	} else {
+		if ((err = wlu_var_getbuf(wl, "dyn_bwsw_params", NULL, 0, &ptr) < 0)) {
+			printf("wl_dyn_bwsw_params: fail to get params\n");
+			return err;
+		}
+		params = (obss_config_params_t *)ptr;
+		config_params = &params->config_params;
+
+		printf("Version=%d\n", params->version);
+		printf("actvcfm=%d\n", config_params->obss_bwsw_activity_cfm_count_cfg);
+		printf("noactcfm=%d\n",
+			config_params->obss_bwsw_no_activity_cfm_count_cfg);
+		printf("noactincr=%d\n",
+			config_params->obss_bwsw_no_activity_cfm_count_incr_cfg);
+		printf("psense=%d\n", config_params->obss_bwsw_pseudo_sense_count_cfg);
+		printf("rxcrsthresh=%d\n", config_params->obss_bwsw_rx_crs_threshold_cfg);
+		printf("secdurlim=%d\n", config_params->obss_bwsw_dur_thres);
+		printf("txopthresh=%d\n", config_params->obss_bwsw_txop_threshold_cfg);
+	}
+
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_proxd.c b/wl/src/wl/exe/wluc_proxd.c
new file mode 100644
index 0000000..ab03cb1
--- /dev/null
+++ b/wl/src/wl/exe/wluc_proxd.c
@@ -0,0 +1,6356 @@
+/*
+ * wl proxd command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_proxd.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifdef WIN32
+#define bzero(b, len)	memset((b), 0, (len))
+#endif
+
+#ifdef LINUX
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* LINUX */
+
+#include <miniopt.h>
+#include <errno.h>
+
+static cmd_func_t wl_proxd;
+static cmd_func_t wl_proxd_tune;
+static cmd_func_t wl_proxd_collect;
+static cmd_func_t wl_proxd_params;
+static cmd_func_t wl_proxd_status;
+static cmd_func_t wl_proxd_payload;
+#if defined(linux)
+static cmd_func_t wl_proxd_event_check;
+#endif   /* linux */
+static cmd_func_t wl_proxd_report;
+#if defined(WL_NAN)
+static cmd_func_t wl_nan_ranging_config;
+static cmd_func_t wl_nan_ranging_start;
+static cmd_func_t wl_nan_ranging_results_host;
+#endif /* WL_NAN */
+#define WL_PROXD_PAYLOAD_LEN	1026
+#define TOF_DEFAULT_FTMCNT_SEQ		3
+
+#define PROXD_PARAMS_USAGE	\
+"\tUsage: wl proxd_params method [-c channel] [-i interval] [-d duration] [-s rssi_thresh]"	\
+" [-p tx_power] [-r tx_rate] [-t timeout] [-m maxconvergetime] [-g <xx:xx:xx:xx:xx:xx>]"	\
+" [-y retrycnt]\n\n" \
+"\tMandatory args:\n"		\
+"\t\tmethod: == 1 (RSSI) or == 2 (TOF) methods are supported) \n\n"	\
+"\tOptional method specific args - for method 1: \n"	\
+"\t\t-c chanspec     : (all methods) channel to use for Proximity Detection\n"	\
+"\t\t                :  e.g: 161/80, if [/BW] omitted, driver will assume 20Mhz by default\n" \
+"\t\t-i interval     : (RSSI method) interval between neighbor finding attempts (in TU)\n"	\
+"\t\t                : (Once associated as STA mode, this value is ignored and\n"	\
+"\t\t                :  the interval follows DTIM)\n"	\
+"\t\t-d duration     : (RSSI method) duration of neighbor finding attempts (in ms)\n"		\
+"\t\t                : == dwelling time on home channel specificed by -c channel\n"	\
+"\t\t-s rssi_thresh  : RSSI threshold for Proximity Detection criteria (in dBm)\n"	\
+"\t\t                : (-99 to -1)\n"	\
+"\t\t-p tx_power     : (RSSI method) tx power of Proximity Detection frames (in dBm)\n"	\
+"\t\t-r tx_rate      : (all methods) tx rate of Proximity Detection frames (in Mbps)\n" \
+"\t\t                : (TOF) tx_rate format is {R|{hM|vM[xS]}[s][l][g]}[eT][bB]\n" \
+"\t\t                : R - legacy rate, hM - HT MCS index[0-23], " \
+"vMxS - VHT MCS index[0-9] and Nss[1-8]\n" \
+"\t\t                : s - Use STBC expansion, l - Use LDPC encoding, " \
+"g - SGI, Short Guard Interval\n" \
+"\t\t                : eT - Tx expansion, number of tx chains[0-3], " \
+"bB - tx bandwidth, MHz: 20, 40, 80\n" \
+"\t\t-t timeout      : (all methods) state machine receive timeout of Proximity Detection " \
+"frames (in ms)\n" \
+"\t\t-m maxconverge  : (RSSI method) device stays up for a whole interval to detect the peer\n"	\
+"\t\t                : when no peer found after max converge time (in ms)\n\n"	\
+"\t\t-g tgt_mac      : (TOF) proximity target mac address for a method  \n" \
+"\t\t-f ftm_cnt      : (TOF) number of ftm frames requested by initiator from target  \n" \
+"\t\t-y retry_cnt    : (TOF) number of retransmit attempts for FTM frames \n" \
+"\tExample: wl proxd_params 1 -c 36 -i 100 -d 10 -s -40 -p 12 -r 6 -t 20 -m 1000\n" \
+"\tExample: wl proxd_params 1 -s -55\n" \
+"\tExample: wl proxd_params 2 -c 11 -f 10 -g 00:90:4c:a5:01:32 -r v0"
+
+#define PROXD_TUNE_USAGE	\
+"\tUsage: wl proxd_tune method [operations]\n\n" \
+"\tMandatory args:\n"		\
+"\t\tmethod: == 2 (TOF) methods are supported \n\n" \
+"\tOperations:\n"		\
+"\t\t-k K factor     : hardware dependant RTD delay adjustment factor \n" \
+"\t\t-b vhtack       : 0:disable VHT ACK, 1:enable VHT ACK\n" \
+"\t\t-n minDT        : min time difference of T1 and T4 or T2 and T3 \n" \
+"\t\t-x maxDT		 : max time difference of T1 and T4 or T2 and T3 \n" \
+"\t\t-t total_frmcnt : total count limit of measurement frames transmitted \n" \
+"\t\t-N threshold_log2 : log2 number of simple threshold crossing \n" \
+"\t\t-S threshold_scale: scale number of simple threshold crossing \n" \
+"\t\t-F ftm_cnt      : number of measurement frames requested by initiator \n" \
+"\t\t-r rsv_media_value: reserve media duration value for TOF \n" \
+"\t\t-f flags        : TOF state machine control flags\n" \
+"\t\t-A timestamp_adj : enable/disable sw/hw/seq assisted timestamp adjustment, " \
+"the data format is s[0|1]h[0|1]r[0|1] \n" \
+"\t\t-W window_adjust : set search window length and offset, " \
+"the data format is bBlLoO, B is bandwidth \n" \
+"\t\t                 : with value 20, 40 or 80, L is window length, O is offset"
+
+static cmd_t wl_proxd_cmds[] = {
+	{ "proxd", wl_proxd, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/Disable Proximity Detection\n"
+	"\t0 : disable\n"
+	"\t1 [initiator|target|neutral] [u/r]: enable with the specified mode and wakeup"
+	" mechanism\n"
+	"\tftm [<session-id>] <cmd> [<param-name><param-value>...]:"
+	" enable FTM, type 'wl proxd -h ftm' for more information\n\n"
+	"\tExample: wl proxd 1 initiator"},
+	{ "proxd_collect", wl_proxd_collect, WLC_GET_VAR, WLC_SET_VAR,
+	"collect the debugging informations of Proximity Detection \n\n"
+	"Optional parameters is:\n"
+	"\tenable to enable the proxd collection.\n"
+	"\tdisable to disable the proxd collection.\n"
+	"\t-l, dump local collect data and request load remote AP collect data.\n"
+	"\t-r, dump remote collect data or request load remote AP collect data.\n"
+	"\t-f File name to dump the sample buffer (default \"proxd_collect.dat\")\n"},
+	{ "proxd_params", wl_proxd_params, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get operational parameters for a method of Proximity Detection\n\n"
+	PROXD_PARAMS_USAGE},
+	{ "proxd_tune", wl_proxd_tune, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get tune parameters for TOF method of Proximity Detection\n\n"
+	PROXD_TUNE_USAGE},
+	{ "proxd_bssid", wl_iov_mac, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get BSSID to be used in proximity detection frames\n\n"
+	"\tUsage: wl proxd_bssid <xx:xx:xx:xx:xx:xx>"},
+	{ "proxd_mcastaddr", wl_iov_mac, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get Multicast MAC address of Proximity Detection Frames\n\n"
+	"\tUsage: wl proxd_mcastaddr <xx:xx:xx:xx:xx:xx>"},
+	{ "proxd_find", wl_var_void, -1, WLC_SET_VAR,
+	"Start Proximity Detection" },
+	{ "proxd_stop", wl_var_void, -1, WLC_SET_VAR,
+	"Stop Proximity Detection" },
+	{ "proxd_status", wl_proxd_status, WLC_GET_VAR, -1,
+	"Get status of Proximity Detection" },
+	{ "proxd_monitor", wl_iov_mac, -1, WLC_SET_VAR,
+	"Monitor detected peer status in proximity\n\n"
+	"\tUsage: wl proxd_monitor <xx:xx:xx:xx:xx:xx>"},
+	{ "proxd_payload", wl_proxd_payload, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set payload content transferred between the proximity detected peers\n\n"
+	"\tUsage: wl proxd_payload [len hexstring]"},
+	{ "proxd_report", wl_proxd_report, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set report distance results list\n\n"
+	"\tUsage: wl proxd_report [mac address list]"},
+#if defined(WL_NAN)
+	{"proxd_nancfg", wl_nan_ranging_config, -1, -1,
+	"Get/Set \"proxd_nancfg\" params .\n"
+	"\tUsage: wl proxd_nancfg <chanspec> <start_timeslot> <duration> [<allow_mac> [flag]]\n"},
+	{"proxd_nanfind", wl_nan_ranging_start, -1, -1,
+	"Send specified \"proxd_nanfind \" params .\n"
+	"\tUsage: wl proxd_nanfind <num_dws> [<chanspec> <peer addr> <bitmap> "
+	"<count> <retry> <flag>]\n"
+	"\t\t for each peer, add the [<chanspec> <peer addr> <bitmap> <count> <retry> <flag>]\n"},
+	{"proxd_nanstatus", wl_nan_ranging_results_host, WLC_GET_VAR, -1,
+	"Return host initiated ranging results.\n"},
+	{"proxd_nanpeer", wl_nan_ranging_results_host, WLC_GET_VAR, -1,
+	"Return peer initiated ranging results.\n"},
+#endif /* WL_NAN */
+#if defined(linux)
+	{ "proxd_event_check", wl_proxd_event_check, -1, -1,
+	"Listen and print Location Based Service events\n"
+	"\tproxd_event_check syntax is: proxd_event_check ifname"},
+#endif /* linux */
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/*
+* for FTM
+*/
+
+static int wl_proxd_cmd_method_handler(void *wl, cmd_t *cmd, char **argv);
+static int ftm_handle_help(char **argv);
+#if defined(linux)
+static int ftm_event_check(bcm_event_t *p_bcm_event);
+#endif
+static void ftm_display_config_help();
+static void ftm_display_config_options_help();
+static void ftm_display_config_avail_help();
+static void ftm_unpack_and_display_session_flags(const uint8 *p_data, uint16 tlvid);
+static void ftm_unpack_and_display_config_flags(const uint8 *p_data, uint16 tlvid);
+static int proxd_tune_display(wl_proxd_params_tof_tune_t *tof_tune, uint16 len);
+
+/*
+*for debug: define the flag WL_FTM_DEBUG to enable debug log for FTM
+*/
+/* #define WL_FTM_DEBUG */
+#ifdef WL_FTM_DEBUG
+static void ftm_format_event_mask(wl_proxd_event_type_t event, char *p_strbuf, int bufsize);
+#endif /* WL_FTM_DEBUG */
+
+/* module initialization */
+void
+wluc_proxd_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register proxd commands */
+	wl_module_cmds_register(wl_proxd_cmds);
+}
+
+static int
+wl_proxd(void *wl, cmd_t *cmd, char **argv)
+{
+	uint16 var[2], *reply;
+	uint16 method = 0, role = 0;
+	void *ptr;
+	int ret;
+
+	/* skip the command name and check if NULL */
+	if (!*++argv) {
+		/* Get */
+		ret = wlu_var_getbuf(wl, cmd->name, &var, sizeof(var), &ptr);
+		if (ret != BCME_OK) {
+			return ret;
+		}
+
+		reply = (uint16 *)ptr;
+
+		method = dtoh16(reply[0]);
+
+		printf("%d\n", method);
+
+		if (method > 0) {
+			char c = 'u';
+			role = dtoh16(reply[1]);
+			if (role & WL_PROXD_RANDOM_WAKEUP) {
+				c = 'r';
+				role &= ~WL_PROXD_RANDOM_WAKEUP;
+			}
+			if (role == WL_PROXD_MODE_INITIATOR)
+				printf("%s %c\n", "initiator", c);
+			else if (role == WL_PROXD_MODE_TARGET)
+				printf("%s %c\n", "target", c);
+			else if (role == WL_PROXD_MODE_NEUTRAL)
+				printf("%s %c\n", "neutral", c);
+		}
+	} else {
+		/* Set */
+		if (!isdigit((int)*argv[0]))
+			return wl_proxd_cmd_method_handler(wl, cmd, argv);
+
+		/* parse method and role */
+		method = (uint16)atoi(argv[0]);
+		if (method > 0) {
+			if (!argv[1]) {
+				/* Default when it is not specified */
+				role = WL_PROXD_MODE_NEUTRAL | WL_PROXD_RANDOM_WAKEUP;
+			}
+			else {
+				if (stricmp(argv[1], "initiator") == 0)
+					role = WL_PROXD_MODE_INITIATOR;
+				else if (stricmp(argv[1], "target") == 0)
+					role = WL_PROXD_MODE_TARGET;
+				else if (stricmp(argv[1], "neutral") == 0) {
+					role = WL_PROXD_MODE_NEUTRAL;
+					role |= WL_PROXD_RANDOM_WAKEUP;
+				}
+				else
+					return BCME_USAGE_ERROR;
+
+				if (argv[2]) {
+					if (*argv[2] == 'R' || *argv[2] == 'r')
+						role |= WL_PROXD_RANDOM_WAKEUP;
+					else if (*argv[2] == 'u' || *argv[2] == 'U')
+						role &= ~WL_PROXD_RANDOM_WAKEUP;
+				}
+			}
+		}
+
+		var[0] = htod16(method);
+		var[1] = htod16(role);
+
+		ret = wlu_var_setbuf(wl, cmd->name, &var, sizeof(var));
+	}
+
+	return ret;
+}
+
+static int
+wl_proxd_get_debug_data(void *wl, cmd_t *cmd, int index)
+{
+	int ret;
+	void *buff;
+	wl_proxd_collect_query_t query;
+	wl_proxd_debug_data_t *replay;
+
+	bzero(&query, sizeof(query));
+	query.method = htol32(PROXD_TOF_METHOD);
+	query.request = PROXD_COLLECT_QUERY_DEBUG;
+	query.index = htol16(index);
+
+	ret = wlu_var_getbuf(wl, cmd->name, &query, sizeof(query), &buff);
+	if (ret != BCME_OK)
+		return ret;
+
+	replay = (wl_proxd_debug_data_t *)buff;
+
+	if (index == 0)
+		printf("\n/* Debug Informations */\n");
+
+	printf("%s[%u,%u]: type %u action(%u,%u) token(%u, %u)\n",
+		replay->received? "RX" : "TX",
+		replay->count, replay->stage,
+		replay->paket_type,
+		replay->category, replay->action,
+		replay->token, replay->follow_token);
+
+	if (replay->tof_cmd == 0 && replay->tof_rsp == 0) {
+		printf("\n");
+		return BCME_OK;
+	}
+
+	printf("Index=%d\n", ltoh16(replay->index));
+	printf("M_TOF_CMD=0x%04x\tM_TOF_RSP=0x%04x\tM_TOF_ID=0x%04x\n",
+		ltoh16(replay->tof_cmd), ltoh16(replay->tof_rsp), ltoh16(replay->tof_id));
+	printf("M_TOF_AVB_RX_L=0x%04x\tM_TOF_AVB_RX_H=0x%04x\t",
+		ltoh16(replay->tof_avb_rxl), ltoh16(replay->tof_avb_rxh));
+	printf("M_TOF_AVB_TX_L=0x%04x\tM_TOF_AVB_TX_H=0x%04x\n",
+		ltoh16(replay->tof_avb_txl), ltoh16(replay->tof_avb_txh));
+	printf("M_TOF_STATUS0=0x%04x\tM_TOF_STATUS2=0x%04x\t",
+		ltoh16(replay->tof_status0), ltoh16(replay->tof_status2));
+	printf("M_TOF_CHNSM_0=0x%04x\tM_TOF_CHNSM_1=0x%04x\n",
+		ltoh16(replay->tof_chsm0), 0);
+	printf("M_TOF_PHYCTL0=0x%04x\tM_TOF_PHYCTL1=0x%04x\tM_TOF_PHYCTL2=0x%04x\n",
+		ltoh16(replay->tof_phyctl0), ltoh16(replay->tof_phyctl1),
+		ltoh16(replay->tof_phyctl2));
+	printf("M_TOF_LSIG=0x%04x\tM_TOF_VHTA0=0x%04x\tM_TOF_VHTA1=0x%04x\n",
+		ltoh16(replay->tof_lsig), ltoh16(replay->tof_vhta0), ltoh16(replay->tof_vhta1));
+	printf("M_TOF_VHTA2=0x%04x\tM_TOF_VHTB0=0x%04x\tM_TOF_VHTB1=0x%04x\n",
+		ltoh16(replay->tof_vhta2), ltoh16(replay->tof_vhtb0), ltoh16(replay->tof_vhtb1));
+	printf("M_TOF_AMPDU_CTL=0x%04x\tM_TOF_AMPDU_DLIM=0x%04x\tM_TOF_AMPDU_LEN=0x%04x\n\n",
+		ltoh16(replay->tof_apmductl), ltoh16(replay->tof_apmdudlim),
+		ltoh16(replay->tof_apmdulen));
+
+	return BCME_OK;
+}
+
+static void
+wlc_proxd_collec_header_dump(wl_proxd_collect_header_t *pHdr)
+{
+	int i;
+
+	printf("total_frames %lu\n", (unsigned long)ltoh16(pHdr->total_frames));
+	printf("nfft %lu\n", (unsigned long)ltoh16(pHdr->nfft));
+	printf("bandwidth %lu\n", (unsigned long)ltoh16(pHdr->bandwidth));
+	printf("channel %lu\n", (unsigned long)ltoh16(pHdr->channel));
+	printf("chanspec %lu\n", (unsigned long)ltoh32(pHdr->chanspec));
+	printf("fpfactor %lu\n", (unsigned long)ltoh32(pHdr->fpfactor));
+	printf("fpfactor_shift %lu\n", (unsigned long)ltoh16(pHdr->fpfactor_shift));
+	printf("distance %li\n", (long)ltoh32(pHdr->distance));
+	printf("meanrtt %lu\n", (unsigned long)ltoh32(pHdr->meanrtt));
+	printf("modertt %lu\n", (unsigned long)ltoh32(pHdr->modertt));
+	printf("medianrtt %lu\n", (unsigned long)ltoh32(pHdr->medianrtt));
+	printf("sdrtt %lu\n", (unsigned long)ltoh32(pHdr->sdrtt));
+	printf("clkdivisor %lu\n", (unsigned long)ltoh32(pHdr->clkdivisor));
+	printf("chipnum %lu\n", (unsigned long)ltoh16(pHdr->chipnum));
+	printf("chiprev %lu\n", (unsigned long)pHdr->chiprev);
+	printf("phyver %lu\n", (unsigned long)pHdr->phyver);
+	printf("localMacAddr %s\n", wl_ether_etoa(&(pHdr->localMacAddr)));
+	printf("remoteMacAddr %s\n", wl_ether_etoa(&(pHdr->remoteMacAddr)));
+	printf("params_Ki %lu\n", (unsigned long)ltoh32(pHdr->params.Ki));
+	printf("params_Kt %lu\n", (unsigned long)ltoh32(pHdr->params.Kt));
+	printf("params_vhtack %li\n", (long)ltoh16(pHdr->params.vhtack));
+	printf("params_N_log2 %d\n", TOF_BW_NUM);
+	for (i = 0; i < TOF_BW_NUM; i++) {
+		printf("%li\n", (long)ltoh16(pHdr->params.N_log2[i]));
+	}
+	printf("params_N_scale %d\n", TOF_BW_NUM);
+	for (i = 0; i < TOF_BW_NUM; i++) {
+		printf("%li\n", (long)ltoh16(pHdr->params.N_scale[i]));
+	}
+	printf("params_sw_adj %lu\n", (unsigned long)pHdr->params.sw_adj);
+	printf("params_hw_adj %lu\n", (unsigned long)pHdr->params.hw_adj);
+	printf("params_seq_en %lu\n", (unsigned long)pHdr->params.seq_en);
+	printf("params_core %lu\n", (unsigned long)pHdr->params.core);
+	printf("params_N_log2_seq 2\n");
+	for (i = 0; i < 2; i++) {
+		printf("%li\n", (long)ltoh16(pHdr->params.N_log2[i + TOF_BW_NUM]));
+	}
+	printf("params_N_scale_seq 2\n");
+	for (i = 0; i < 2; i++) {
+		printf("%li\n", (long)ltoh16(pHdr->params.N_scale[i + TOF_BW_NUM]));
+	}
+	printf("params_w_offset %d\n", TOF_BW_NUM);
+	for (i = 0; i < TOF_BW_NUM; i++) {
+		printf("%li\n", (long)ltoh16(pHdr->params.w_offset[i]));
+	};
+	printf("params_w_len %d\n", TOF_BW_NUM);
+	for (i = 0; i < TOF_BW_NUM; i++) {
+		printf("%li\n", (long)ltoh16(pHdr->params.w_len[i]));
+	};
+	printf("params_maxDT %li\n", (long)ltoh32(pHdr->params.maxDT));
+	printf("params_minDT %li\n", (long)ltoh32(pHdr->params.minDT));
+	printf("params_totalfrmcnt %lu\n", (unsigned long)pHdr->params.totalfrmcnt);
+	printf("params_rsv_media %lu\n", (unsigned long)ltoh16(pHdr->params.rsv_media));
+}
+
+static int wlc_proxd_collect_data_check_ver_len(uint16 expected_ver,
+	uint16 ver, uint16 len)
+{
+	int ret = BCME_OK;
+
+	switch (expected_ver) {
+	case WL_PROXD_COLLECT_DATA_VERSION_1:
+		/* v1 does not haver version and length fields */
+		ret = BCME_OK;
+		break;
+	case WL_PROXD_COLLECT_DATA_VERSION_2:
+		if ((ver != expected_ver) ||
+			(len != sizeof(wl_proxd_collect_data_t_v2) -
+				OFFSETOF(wl_proxd_collect_data_t_v2, len))) {
+			ret = BCME_VERSION;
+		}
+		break;
+	default:
+		ret = BCME_UNSUPPORTED;
+	}
+
+	return ret;
+}
+static int wlc_proxd_collec_data_dump(void *replay, FILE *fp,
+	wl_proxd_rssi_bias_avg_t *rssi_bias_avg, uint16 version)
+{
+	int i, n, nbytes;
+	int ret = BCME_OK;
+	wl_proxd_collect_data_t_v1 *replay_v1 = NULL;
+	wl_proxd_collect_data_t_v2 *replay_v2 = NULL;
+	wl_proxd_collect_info_t *info = NULL;
+	uint32 *H = NULL;
+	uint32 *chan = NULL;
+	uint8 *ri_rr = NULL;
+	int nfft = 0;
+#ifdef RSSI_REFINE
+	int rssi_dec = 0;
+#else
+	/* rssi_bias_avg is unused under !RSSI_REFINE. */
+	/* Macro to prevent compiler warning under some platforms */
+	UNUSED_PARAMETER(rssi_bias_avg);
+#endif
+
+	BCM_REFERENCE(H);
+	BCM_REFERENCE(chan);
+	BCM_REFERENCE(ri_rr);
+
+	/* Depending on version add the corresponding case and pointers to point
+	 * to the correct member for use in the function
+	 */
+	switch (version) {
+	case WL_PROXD_COLLECT_DATA_VERSION_1:
+		replay_v1 = (wl_proxd_collect_data_t_v1 *)replay;
+		info = &replay_v1->info;
+		H = replay_v1->H;
+		ri_rr = replay_v1->ri_rr;
+		nbytes = sizeof(wl_proxd_collect_data_t_v1)
+			- (K_TOF_COLLECT_H_SIZE_20MHZ - nfft) * sizeof(uint32);
+		break;
+	case WL_PROXD_COLLECT_DATA_VERSION_2:
+		replay_v2 = (wl_proxd_collect_data_t_v2 *)replay;
+		ret = wlc_proxd_collect_data_check_ver_len(version, replay_v2->version,
+			replay_v2->len);
+		if (ret != BCME_OK) {
+			break;
+		}
+		info = &replay_v2->info;
+		H = replay_v2->H;
+		ri_rr = replay_v2->ri_rr;
+		chan = replay_v2->chan;
+		nbytes = sizeof(wl_proxd_collect_data_t_v2)
+			- (K_TOF_COLLECT_H_SIZE_20MHZ - nfft) * sizeof(uint32);
+		break;
+	default:
+		ret = BCME_VERSION;
+		break;
+	}
+	if (ret != BCME_OK) {
+		goto done;
+	}
+
+	if (info) {
+		nfft = (int)ltoh16(info->nfft);
+#ifdef RSSI_REFINE
+		if (nfft > 0) {
+			printf("}\nImpulse Response = {\n");
+			for (i = 0; i < nfft; i++) {
+			printf("%010d ", ltoh32(info->rssi_bias.imp_resp[i]));
+				if ((i & 7) == 7)
+					printf("\n");
+			}
+			printf("RSSI_VERSION = %d\n", ltoh32(info->rssi_bias.version));
+			printf("PEAK_OFFSET = %d\n", ltoh32(info->rssi_bias.peak_offset));
+			rssi_bias_avg->avg_peak_offset += ltoh32(info->rssi_bias.peak_offset);
+			printf("PEAK_TO_AVG = %d", ltoh32(info->rssi_bias.bias));
+			rssi_bias_avg->avg_bias += ltoh32(info->rssi_bias.bias);
+			printf("\n");
+			for (i = 0; i < 10; i++) {
+				printf("THRESHOLD_%d = %u", i,
+					ltoh32(info->rssi_bias.threshold[i]));
+				if ((i+1) % 5)
+					printf(", ");
+				else
+					printf("\n");
+				rssi_bias_avg->avg_threshold[i] +=
+					ltoh32(info->rssi_bias.threshold[i]);
+			}
+			printf("SCALAR = %d", info->rssi_bias.threshold[10]);
+		}
+
+		/* convert tof_status2 from hex to dec */
+		rssi_dec = info->tof_rssi;
+		printf("\nRSSI10 = %d", rssi_dec);
+		rssi_bias_avg->avg_rssi += rssi_dec;
+		printf("\n\n");
+#endif /* RSSI_REFINE */
+
+		/* printing the info portion */
+		printf("info_type %lu\n", (unsigned long)ltoh16(info->type));
+		printf("info_index %lu\n", (unsigned long)ltoh16(info->index));
+		printf("info_tof_cmd %lu\n", (unsigned long)ltoh16(info->tof_cmd));
+		printf("info_tof_rsp %lu\n", (unsigned long)ltoh16(info->tof_rsp));
+		printf("info_tof_avb_rxl %lu\n", (unsigned long)ltoh16(info->tof_avb_rxl));
+		printf("info_tof_avb_rxh %lu\n", (unsigned long)ltoh16(info->tof_avb_rxh));
+		printf("info_tof_avb_txl %lu\n", (unsigned long)ltoh16(info->tof_avb_txl));
+		printf("info_tof_avb_txh %lu\n", (unsigned long)ltoh16(info->tof_avb_txh));
+		printf("info_tof_id %lu\n", (unsigned long)ltoh16(info->tof_id));
+		printf("info_tof_frame_type %lu\n", (unsigned long)info->tof_frame_type);
+		printf("info_tof_frame_bw %lu\n", (unsigned long)info->tof_frame_bw);
+		printf("info_tof_rssi %li\n", (long)info->tof_rssi);
+		printf("info_tof_cfo %li\n", (long)ltoh32(info->tof_cfo));
+		printf("info_gd_adj_ns %li\n", (long)ltoh32(info->gd_adj_ns));
+		printf("info_gd_h_adj_ns %li\n", (long)ltoh32(info->gd_h_adj_ns));
+		printf("info_nfft %li\n", (long)ltoh16(info->nfft));
+
+		if (H) {
+			/* printing the H portion */
+			printf("H %d\n", nfft);
+			for (i = 0; i < nfft; i++) {
+				printf("%lu\n", (unsigned long)ltoh32(H[i]));
+			}
+		}
+
+		/* printing the chan and ri_rr */
+		if (info->index == 1) {
+			if (chan && version >= WL_PROXD_COLLECT_DATA_VERSION_2) {
+				n = (int)ltoh16((info->num_max_cores + 1)*
+					(K_TOF_COLLECT_CHAN_SIZE >> (2 - info->tof_frame_bw)));
+				printf("chan_est %d\n", n);
+				for (i = 0; i < n; i++) {
+					printf("%u\n", chan[i]);
+				}
+			}
+			if (ri_rr) {
+				printf("ri_rr %d\n", FTM_TPK_RI_RR_LEN);
+				for (i = 0; i < FTM_TPK_RI_RR_LEN; i++) {
+					printf("%u\n", ri_rr[i]);
+				}
+			}
+		}
+
+		ret = fwrite(replay, 1, nbytes, fp);
+		if (ret != nbytes) {
+			fprintf(stderr, "Error writing %d bytes to file, rc %d!\n",
+				nbytes, ret);
+			return BCME_ERROR;
+		}
+	}
+
+done:
+	return ret;
+}
+
+static int
+wl_proxd_get_collect_data(void *wl, cmd_t *cmd, FILE *fp, int index,
+	wl_proxd_rssi_bias_avg_t *rssi_bias_avg)
+{
+	int ret;
+	void *buff;
+	wl_proxd_collect_query_t query;
+	uint16 expected_collect_data_ver = 0;
+
+	/* check firmware version */
+	/* Select collect data structure version based on FW version.
+	 * Extend here for future versions
+	 */
+	if (wlc_ver_major(wl) <= 5) {
+		/* use v1 */
+		expected_collect_data_ver = WL_PROXD_COLLECT_DATA_VERSION_1;
+	} else {
+		/* use v2 */
+		expected_collect_data_ver = WL_PROXD_COLLECT_DATA_VERSION_2;
+	}
+
+	bzero(&query, sizeof(query));
+	query.method = htol32(PROXD_TOF_METHOD);
+	query.request = PROXD_COLLECT_QUERY_DATA;
+	query.index = htol16(index);
+
+	ret = wlu_var_getbuf(wl, cmd->name, &query, sizeof(query), &buff);
+	if (ret != BCME_OK)
+		return ret;
+
+	ret = wlc_proxd_collec_data_dump(buff, fp, rssi_bias_avg,
+		expected_collect_data_ver);
+	if (ret != BCME_OK) {
+		return ret;
+	}
+
+	return BCME_OK;
+}
+
+static int
+wl_proxd_collect(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	void *buff;
+	wl_proxd_collect_query_t query, *pStatus;
+	wl_proxd_collect_header_t *pHdr;
+	const char *fname = "proxd_collect.dat";
+	FILE *fp = NULL;
+	int   i, collect_method, total_frames, load_request = 0, remote_request = 0;
+	char chspec_str[CHANSPEC_STR_LEN];
+	chanspec_t chanspec;
+	float d_ref = -1;
+#ifdef RSSI_REFINE
+	wl_proxd_rssi_bias_avg_t rssi_bias_avg;
+
+	bzero(&rssi_bias_avg, sizeof(rssi_bias_avg));
+#endif
+	bzero(&query, sizeof(query));
+	query.method = htol32(PROXD_TOF_METHOD);
+
+	/* Skip the command name */
+	argv++;
+	while (*argv) {
+		if (strcmp(argv[0], "disable") == 0 || *argv[0] == '0') {
+			query.request = PROXD_COLLECT_SET_STATUS;
+			query.status = 0;
+			return wlu_var_getbuf(wl, cmd->name, &query, sizeof(query), &buff);
+		}
+		collect_method = (uint16)atoi(argv[0]);
+		if (strcmp(argv[0], "enable") == 0) {
+			query.request = PROXD_COLLECT_SET_STATUS;
+			query.status = 1;
+			return wlu_var_getbuf(wl, cmd->name, &query, sizeof(query), &buff);
+		} else if (isdigit((int)*argv[0]) &&
+				((collect_method >= WL_PROXD_COLLECT_METHOD_TYPE_DISABLE) &&
+				(collect_method <= WL_PROXD_COLLECT_METHOD_TYPE_EVENT_LOG))) {
+			query.request = PROXD_COLLECT_SET_STATUS;
+			query.status = collect_method;
+			return wlu_var_getbuf(wl, cmd->name, &query, sizeof(query), &buff);
+		}
+		if (!strcmp(argv[0], "-l")) {
+			load_request = 1;
+			argv++;
+		}
+		else if (!strcmp(argv[0], "-r")) {
+			remote_request = 1;
+			argv++;
+		}
+		else if (!strcmp(argv[0], "-f")) {
+			if (argv[1] == NULL)
+				return -1;
+			fname = argv[1];
+			argv += 2;
+		}
+		else if (!strcmp(argv[0], "-d")) {
+			if (argv[1] == NULL)
+				return -1;
+			sscanf((const char*)argv[1], "%f", &d_ref);
+			argv += 2;
+		} else
+			return -1;
+	}
+
+	query.request = PROXD_COLLECT_GET_STATUS;
+	ret = wlu_var_getbuf(wl, cmd->name, &query, sizeof(query), &buff);
+	if (ret != BCME_OK)
+		return ret;
+
+	pStatus = (wl_proxd_collect_query_t *)buff;
+	if (!pStatus->status) {
+		printf("Disable\n");
+		return BCME_OK;
+	}
+
+	if (pStatus->busy) {
+		printf("Busy\n");
+		return BCME_OK;
+	}
+
+	if ((pStatus->mode == WL_PROXD_MODE_TARGET) &&
+		(remote_request || load_request)) {
+		printf("Unsupport\n");
+		return BCME_OK;
+	}
+
+	if (remote_request && !pStatus->remote) {
+		printf("Remote data have not ready, please run this command again\n");
+		load_request = 1;
+		goto exit;
+	}
+
+	if (load_request && pStatus->remote) {
+		printf("Local data have not ready, please run command 'proxd_find' to get it\n");
+		goto exit;
+	}
+
+	query.request = PROXD_COLLECT_QUERY_HEADER;
+	ret = wlu_var_getbuf(wl, cmd->name, &query, sizeof(query), &buff);
+	if (ret != BCME_OK)
+		return ret;
+
+	pHdr = (wl_proxd_collect_header_t *)buff;
+	total_frames = (int)ltoh32(pHdr->total_frames);
+	if (!total_frames) {
+		printf("Enable\n");
+		goto exit;
+	}
+
+	chanspec = wl_chspec_from_driver(pHdr->chanspec);
+	wf_chspec_ntoa(chanspec, chspec_str);
+
+	printf("d_ref %5.1f\n", d_ref);
+	wlc_proxd_collec_header_dump(pHdr);
+
+	if ((fp = fopen(fname, "wb")) == NULL) {
+		fprintf(stderr, "Problem opening file %s\n", fname);
+		return 0;
+	}
+
+	ret = fwrite(buff, 1, sizeof(wl_proxd_collect_header_t), fp);
+	if (ret != sizeof(wl_proxd_collect_header_t)) {
+		fprintf(stderr, "Error writing to file rc %d\n", ret);
+		ret = -1;
+		goto exit;
+	}
+
+	for (i = 0; i < total_frames; i++) {
+#ifdef RSSI_REFINE
+		ret = wl_proxd_get_collect_data(wl, cmd, fp, i, &rssi_bias_avg);
+#else
+		ret = wl_proxd_get_collect_data(wl, cmd, fp, i, NULL);
+#endif
+		if (ret != BCME_OK)
+			goto exit;
+	}
+#ifdef RSSI_REFINE
+	if (total_frames > 0) {
+		printf("avg_rssi = %d avg_peak_offset = %d\n",
+			rssi_bias_avg.avg_rssi/total_frames,
+			rssi_bias_avg.avg_peak_offset/total_frames);
+		for (i = 0; i < 10; i++) {
+			printf("avg_threshold_%d = %d",
+				i, rssi_bias_avg.avg_threshold[i]/total_frames);
+			if ((i+1) % 5)
+				printf(", ");
+			else
+				printf("\n");
+		}
+		printf("avg_bias = %d\n", rssi_bias_avg.avg_bias/total_frames);
+	}
+#endif
+	for (i = 0; i < 256; i++) {
+		ret = wl_proxd_get_debug_data(wl, cmd, i);
+		if (ret != BCME_OK)
+			break;
+	}
+	if (!load_request) {
+		/* FTM remote collect done */
+		query.request = PROXD_COLLECT_DONE;
+		(void)wlu_var_getbuf(wl, cmd->name, &query, sizeof(query), &buff);
+	}
+	ret = BCME_OK;
+exit:
+	if (ret == BCME_OK && load_request) {
+		query.request = PROXD_COLLECT_REMOTE_REQUEST;
+		ret = wlu_var_getbuf(wl, cmd->name, &query, sizeof(query), &buff);
+	}
+	if (fp) fclose(fp);
+	return ret;
+}
+
+/* set measurement packet transmit rate */
+static int proxd_method_set_vht_rate(miniopt_t *mopt)
+{
+	char *startp, *endp;
+	char c;
+	bool legacy_set = FALSE, ht_set = FALSE, vht_set = FALSE;
+	int rate, mcs, Nss, tx_exp, bw, val;
+	bool stbc, ldpc, sgi;
+	uint32 rspec = 0;
+
+	/* set default values */
+	rate = 0;
+	mcs = 0;
+	Nss = 0;
+	tx_exp = 0;
+	stbc = FALSE;
+	ldpc = FALSE;
+	sgi = FALSE;
+	bw = 0;
+
+	startp = mopt->valstr;
+	endp = NULL;
+	if (*startp != 'h' && *startp != 'v') {
+		if ((rate = (int)strtol(startp, &endp, 10)) == 0)
+			return -1;
+
+		rate *= 2;
+		if (endp[0] == '.' && endp[1] == '5') {
+			rate += 1;
+			endp += 2;
+		}
+		startp = endp;
+		legacy_set = TRUE;
+	}
+
+	while (startp && ((c = *startp++) != '\0')) {
+		if (c == 'h') {
+			ht_set = TRUE;
+			mcs = (int)strtol(startp, &endp, 10);
+			if (mcs < 0 || mcs > 23) {
+				printf("HT MCS index %d out of range [0-23].\n", mcs);
+				return -1;
+			}
+			startp = endp;
+		}
+		else if (c == 'v') {
+			vht_set = TRUE;
+			mcs = (int)strtol(startp, &endp, 10);
+			if (mcs < 0 || mcs > 9) {
+				printf("HT MCS index %d out of range [0-9].\n", mcs);
+				return -1;
+			}
+			startp = endp;
+		}
+		else if (c == 'x') {
+			Nss = (int)strtol(startp, &endp, 10);
+			if (Nss < 1 || Nss > 8) {
+				printf("Nss %d out of range [1-8].\n", Nss);
+				return -1;
+			}
+			startp = endp;
+		}
+		else if (c == 'e') {
+			tx_exp = (int)strtol(startp, &endp, 10);
+			if (tx_exp < 0 || tx_exp > 3) {
+				printf("tx expansion %d out of range [0-3].\n", tx_exp);
+				return -1;
+			}
+			startp = endp;
+		}
+		else if (c == 's') {
+			stbc = TRUE;
+			continue;
+		}
+		else if (c == 'l') {
+			ldpc = TRUE;
+			continue;
+		}
+		else if (c == 'g') {
+			sgi = TRUE;
+			continue;
+		}
+		else if (c == 'b') {
+			val = (int)strtol(startp, &endp, 10);
+			if (val == 20) {
+				bw = WL_RSPEC_BW_20MHZ;
+			} else if (val == 40) {
+				bw = WL_RSPEC_BW_40MHZ;
+			} else if (val == 80) {
+				bw = WL_RSPEC_BW_80MHZ;
+			} else if (val == 160) {
+				bw = WL_RSPEC_BW_160MHZ;
+			} else {
+				printf("unexpected bandwidth specified \"%d\", "
+				        "expected 20, 40, 80, or 160\n", val);
+				return -1;
+			}
+			startp = endp;
+		}
+	}
+
+	if (!legacy_set && !ht_set && !vht_set) {
+		printf("must specify one of legacy rate, HT (11n) rate hM, "
+			"or VHT (11ac) rate vM[xS]\n");
+		return -1;
+	}
+
+	if (legacy_set && (ht_set || vht_set)) {
+		printf("cannot use legacy rate and HT rate or VHT rate at the same time\n");
+		return -1;
+	}
+
+	if (ht_set && vht_set) {
+		printf("cannot use HT rate hM and HT rate vM[xS] at the same time\n");
+		return -1;
+	}
+
+	if (!vht_set && Nss != 0) {
+		printf("cannot use xS option with non VHT rate\n");
+		return -1;
+	}
+
+	if ((stbc || ldpc || sgi) && !(ht_set || vht_set)) {
+		printf("cannot use STBC/LDPC/SGI options with non HT/VHT rates\n");
+		return -1;
+	}
+
+	if (legacy_set) {
+		rspec = WL_RSPEC_ENCODE_RATE;	/* 11abg */
+		rspec |= rate;
+	} else if (ht_set) {
+		rspec = WL_RSPEC_ENCODE_HT; /* 11n HT */
+		rspec |= mcs;
+	} else {
+		rspec = WL_RSPEC_ENCODE_VHT;	/* 11ac VHT */
+		if (Nss == 0) {
+			Nss = 1; /* default Nss = 1 if --ss option not given */
+		}
+		rspec |= (Nss << WL_RSPEC_VHT_NSS_SHIFT) | mcs;
+	}
+
+	/* set the other rspec fields */
+	rspec |= (tx_exp << WL_RSPEC_TXEXP_SHIFT);
+	rspec |= bw;
+	rspec |= (stbc ? WL_RSPEC_STBC : 0);
+	rspec |= (ldpc ? WL_RSPEC_LDPC : 0);
+	rspec |= (sgi  ? WL_RSPEC_SGI  : 0);
+
+	mopt->uval = rspec;
+
+	return 0;
+}
+
+/* proxd set params common cmdl opts */
+int proxd_method_set_common_param_from_opt(cmd_t *cmd,
+	miniopt_t *mopt, wl_proxd_params_common_t *proxd_params)
+{
+	chanspec_t chanspec;
+
+	if (mopt->opt == 'c') {
+		/* chanspec iovar uses wl_chspec32_to_driver(chanspec), why ? */
+		if ((chanspec = wf_chspec_aton(mopt->valstr)) == 0) {
+			fprintf(stderr, "%s: could not parse \"%s\" as a channel\n",
+				cmd->name, mopt->valstr);
+			return BCME_BADARG;
+		}
+
+		proxd_params->chanspec
+			= wl_chspec_to_driver(chanspec);
+
+		if (proxd_params->chanspec == INVCHANSPEC) {
+			fprintf(stderr,
+				"%s: wl_chspec_to_driver() error \"%s\" \n",
+				cmd->name, mopt->valstr);
+			return BCME_BADARG;
+		}
+	} else if (mopt->opt == 't') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as a timeout\n",
+				cmd->name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_params->timeout = htod16(mopt->val);
+	}
+	else
+		return BCME_USAGE_ERROR;
+
+	return BCME_OK;
+}
+
+/*  proxd  TOF cmdl ops  */
+int proxd_method_tof_set_param_from_opt(cmd_t *cmd,
+	miniopt_t *mopt, wl_proxd_params_tof_method_t *proxd_params)
+{
+	 if (mopt->opt == 'g') {
+		/* this param is only valid for TOF method only */
+		struct ether_addr ea;
+
+		if (!wl_ether_atoe(mopt->valstr, &ea))  {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as MAC address\n",
+			cmd->name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		memcpy(&proxd_params->tgt_mac, &ea, 6);
+	} else if (mopt->opt == 'f') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as FTM frame count\n",
+			cmd->name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_params->ftm_cnt = htod16(mopt->val);
+	} else if (mopt->opt == 'y') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as Retry Count\n",
+			cmd->name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_params->retry_cnt = htod16(mopt->val);
+	}  else if (mopt->opt == 'r') {
+		if (!mopt->good_int) {
+			/* special case check for "-r 5.5" */
+			if (!strcmp(mopt->valstr, "5.5")) {
+				mopt->uval = 11;
+			} else if (proxd_method_set_vht_rate(mopt)) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as a rate\n",
+					cmd->name, mopt->valstr);
+				return BCME_USAGE_ERROR;
+			}
+		} else
+			 mopt->uval = mopt->uval*2;
+		proxd_params->tx_rate = htod16((mopt->uval & 0xffff));
+		proxd_params->vht_rate = htod16((mopt->uval >> 16));
+	} else
+		return BCME_USAGE_ERROR;
+
+	return BCME_OK;
+}
+
+/*   RSSI method specific mdl opts   */
+int proxd_method_rssi_set_param_from_opt(cmd_t *cmd,
+	miniopt_t *mopt, wl_proxd_params_rssi_method_t *proxd_params)
+{
+
+	if (mopt->opt == 'i') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as an interval\n",
+				cmd->name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_params->interval = htod16(mopt->val);
+	} else if (mopt->opt == 'd') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as a duration\n",
+				cmd->name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_params->duration = htod16(mopt->val);
+	} else if (mopt->opt == 'p') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as a power\n",
+			cmd->name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_params->tx_power = htod16(mopt->val);
+	} else if (mopt->opt == 's') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as a RSSI\n",
+				cmd->name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_params->rssi_thresh = htod16(mopt->val);
+	} else if (mopt->opt == 'm') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as a maxconvergetime\n",
+				cmd->name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_params->maxconvergtmo = htod16(mopt->val);
+	} else if (mopt->opt == 'r') {
+		if (!mopt->good_int) {
+			/* special case check for "-r 5.5" */
+			if (!strcmp(mopt->valstr, "5.5")) {
+				mopt->val = 11;
+			} else {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as a rate\n",
+					cmd->name, mopt->valstr);
+				return BCME_USAGE_ERROR;
+			}
+		} else
+			mopt->val = mopt->val*2;
+		proxd_params->tx_rate = htod16(mopt->val);
+	}
+	else
+		return BCME_USAGE_ERROR;
+
+	return BCME_OK;
+}
+
+static int
+wl_proxd_params(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_proxd_params_iovar_t proxd_params, *reply;
+	uint16 method;
+	void *ptr = NULL;
+	int ret, opt_err;
+	miniopt_t to;
+	char chspec_str[CHANSPEC_STR_LEN];
+	char rate_str[64];
+	chanspec_t chanspec;
+	uint16 interval, duration;
+	uint32 tx_rate;
+
+	/* skip the command name and check if mandatory exists */
+	if (!*++argv) {
+		fprintf(stderr, "missing mandatory parameter \'method\'\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* parse method */
+	method = (uint16)atoi(argv[0]);
+	if (method == 0) {
+		fprintf(stderr, "invalid parameter \'method\'\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	bzero(&proxd_params, sizeof(proxd_params));
+
+	/* set method to get/set */
+	proxd_params.method = htod16(method);
+
+	ret = wlu_var_getbuf_sm(wl, cmd->name, &proxd_params, sizeof(proxd_params), &ptr);
+	if (ret != BCME_OK) {
+		return ret;
+	}
+
+	if (!*++argv) {
+		/* get */
+		/* display proxd_params got */
+		reply = (wl_proxd_params_iovar_t *)ptr;
+
+		printf("bf proxd_params.method:%d\n", proxd_params.method);
+		switch (proxd_params.method) {
+
+		case PROXD_RSSI_METHOD:
+
+			chanspec = wl_chspec_from_driver(reply->u.rssi_params.chanspec);
+			tx_rate = dtoh16(reply->u.rssi_params.tx_rate);
+			wf_chspec_ntoa(chanspec, chspec_str);
+
+			printf("channel=%s\n", chspec_str);
+			printf("interval=%d TU\n", dtoh16(reply->u.rssi_params.interval));
+			printf("duration=%d ms\n", dtoh16(reply->u.rssi_params.duration));
+			printf("rssi_thresh=%d dBm\n",
+				(int16)dtoh16(reply->u.rssi_params.rssi_thresh));
+			printf("maxconvergetime=%d ms\n\n",
+				dtoh16(reply->u.rssi_params.maxconvergtmo));
+			printf("tx_power=%d dBm\n",
+				(int16)dtoh16(reply->u.rssi_params.tx_power));
+			printf("tx_rate=%d%s Mbps\n",
+				(tx_rate / 2), (tx_rate & 1) ? ".5" : "");
+			printf("timeout=%d ms\n", dtoh16(reply->u.rssi_params.timeout));
+			break;
+
+		case PROXD_TOF_METHOD:
+
+			chanspec = wl_chspec_from_driver(reply->u.tof_params.chanspec);
+			tx_rate = dtoh16(reply->u.tof_params.tx_rate) |
+				(dtoh16(reply->u.tof_params.vht_rate) << 16);
+			wf_chspec_ntoa(chanspec, chspec_str);
+			wl_rate_print(rate_str, tx_rate);
+
+			printf("tgt_mac=%s \n",
+				wl_ether_etoa(&reply->u.tof_params.tgt_mac));
+			printf("ftm_cnt= %d\n", dtoh16(reply->u.tof_params.ftm_cnt));
+			printf("channel=%s (0x%04x)\n", chspec_str, chanspec);
+			printf("tx_rate=%s (0x%08x)\n", rate_str, tx_rate);
+			printf("timeout=%d ms\n",
+				dtoh16(reply->u.tof_params.timeout));
+			printf("retry_cnt=%d \n", dtoh16(reply->u.tof_params.retry_cnt));
+			break;
+
+		default:
+			fprintf(stderr,
+				"%s: ERROR undefined method \n", cmd->name);
+			return BCME_BADARG;
+		}
+	} else {  /* set */
+		memcpy((void *)&proxd_params, (void *)ptr, sizeof(proxd_params));
+		proxd_params.method = method;
+
+		/* set */
+		miniopt_init(&to, cmd->name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			int com_res, meth_res;
+
+			if (opt_err == 1) {
+				return BCME_USAGE_ERROR;
+			}
+			argv += to.consumed;
+
+			/*  process cmd opts common for all methods */
+			com_res = proxd_method_set_common_param_from_opt(cmd,
+				&to, &proxd_params.u.cmn_params);
+
+			/* method specific opts */
+			switch (method) {
+				case PROXD_RSSI_METHOD:
+					meth_res = proxd_method_rssi_set_param_from_opt(cmd,
+						&to, &proxd_params.u.rssi_params);
+				break;
+				case PROXD_TOF_METHOD:
+					meth_res = proxd_method_tof_set_param_from_opt(cmd,
+						&to, &proxd_params.u.tof_params);
+					if (meth_res == BCME_BADARG)
+						return meth_res;
+				break;
+				default:
+					printf("ERROR: unsupported method\n");
+					return BCME_USAGE_ERROR;
+			}
+
+			/*  if option is unknown to both common and meth specific */
+			if ((com_res != BCME_OK) && (meth_res != BCME_OK)) {
+				printf(">>>> Method:%d doesn't support cmd option:'%c'\n",
+					method, to.opt);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		/* Sanity check of parameters against each other */
+		interval = dtoh16(proxd_params.u.rssi_params.interval);
+		duration = dtoh16(proxd_params.u.rssi_params.duration);
+
+		if (interval < duration) {
+			fprintf(stderr,
+				"%s: \'interval\' cannot be shorter than \'duration\'\n",
+				cmd->name);
+			return BCME_BADARG;
+		}
+
+		ret = wlu_var_setbuf(wl, cmd->name, &proxd_params, sizeof(proxd_params));
+	}
+
+	return ret;
+}
+
+/* proxd parse mixed param: <str0><val0><str1><val1>... */
+static void
+proxd_method_tof_parse_mixed_param(char* str, const char** p_name, int* p_val, int* p_map)
+{
+	char* p;
+
+	/* parse stuff of format <str0><val0><str1><val1>... */
+	while (*p_name) {
+		p = strstr((const char*)str, (const char*)*p_name);
+		if (p) {
+			p += strlen((const char*)*p_name);
+			*p_map = 1;
+			*p_val = strtol(p, NULL, 10);
+		} else {
+			*p_map = 0;
+		}
+
+		p_name++;
+		p_map++;
+		p_val++;
+	}
+}
+
+/*  proxd  TOF tune ops  */
+static int
+proxd_tune_set_param_from_opt(const char* cmd_name,
+	miniopt_t *mopt, wl_proxd_params_tof_tune_t *proxd_tune)
+{
+	if (mopt->opt == 'k') {
+		if (!mopt->good_int) {
+			char *p = strstr(mopt->valstr, ",");
+			if (p) {
+				proxd_tune->Ki = htod32(atoi(mopt->valstr));
+				proxd_tune->Kt = htod32(atoi(p+1));
+			}
+			else {
+			fprintf(stderr,
+					"%s: could not parse \"%s\" as K\n",
+				cmd_name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+			}
+		}
+		else {
+			proxd_tune->Ki = htod32(mopt->val);
+			proxd_tune->Kt = htod32(mopt->val);
+		}
+		proxd_tune->setflags |= WL_PROXD_SETFLAG_K;
+	} else if (mopt->opt == 'b') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as vhtack\n",
+				cmd_name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->vhtack = htod16(mopt->val);
+	} else if (mopt->opt == 'c') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as core\n",
+				cmd_name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->core = htod16(mopt->val);
+	} else if (mopt->opt == 'A') {
+		const char* n[4] = {"s", "h", "r", NULL};
+		int v[3] = {0, 0, 0};
+		int m[3] = {0, 0, 0};
+
+		proxd_method_tof_parse_mixed_param(mopt->valstr, n, v, m);
+		if (m[TOF_ADJ_SOFTWARE]) {
+			/* sw adj */
+			proxd_tune->sw_adj = (int16)v[TOF_ADJ_SOFTWARE];
+		}
+		if (m[TOF_ADJ_HARDWARE]) {
+			/* hw adj */
+			proxd_tune->hw_adj = (int16)v[TOF_ADJ_HARDWARE];
+		}
+		if (m[TOF_ADJ_SEQ]) {
+			/* ranging sequence */
+			proxd_tune->seq_en = (int16)v[TOF_ADJ_SEQ];
+		}
+
+		if ((m[TOF_ADJ_SOFTWARE] | m[TOF_ADJ_HARDWARE] | m[TOF_ADJ_SEQ]) == 0) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as hw/sw adjustment enable params\n",
+				cmd_name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+	} else if (mopt->opt == 'n') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as min time difference limitation\n",
+				cmd_name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->minDT = htod32(mopt->val);
+	} else if (mopt->opt == 'x') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as max time difference limitation\n",
+				cmd_name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->maxDT = htod32(mopt->val);
+	} else if (mopt->opt == 'N') {
+		int i = 0;
+		if (!mopt->good_int) {
+			char *p = mopt->valstr;
+			while (p && i < TOF_BW_SEQ_NUM) {
+				if (htod16(atoi(p)))
+					proxd_tune->N_log2[i] = htod16(atoi(p));
+				i++;
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+			if (p) {
+				proxd_tune->N_log2_2g = htod16(atoi(p));
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+			if (p) {
+				proxd_tune->seq_5g20.N_tx_log2 = htod16(atoi(p));
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+			if (p) {
+				proxd_tune->seq_5g20.N_rx_log2 = htod16(atoi(p));
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+			if (p) {
+				proxd_tune->seq_2g20.N_tx_log2 = htod16(atoi(p));
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+			if (p) {
+				proxd_tune->seq_2g20.N_rx_log2 = htod16(atoi(p));
+			}
+
+		} else {
+			for (; i < TOF_BW_SEQ_NUM; i++) {
+				proxd_tune->N_log2[i] = htod16(mopt->val);
+			}
+			proxd_tune->N_log2_2g = htod16(mopt->val);
+			proxd_tune->seq_5g20.N_tx_log2 = htod16(mopt->val);
+			proxd_tune->seq_5g20.N_rx_log2 = htod16(mopt->val);
+			proxd_tune->seq_2g20.N_tx_log2 = htod16(mopt->val);
+			proxd_tune->seq_2g20.N_rx_log2 = htod16(mopt->val);
+		}
+		proxd_tune->setflags |= WL_PROXD_SETFLAG_N;
+	} else if (mopt->opt == 'S') {
+		int i = 0;
+		if (!mopt->good_int) {
+			char *p = mopt->valstr;
+			while (p && i < TOF_BW_SEQ_NUM) {
+				if (htod16(atoi(p)))
+					proxd_tune->N_scale[i] = htod16(atoi(p));
+				i++;
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+			if (p) {
+				proxd_tune->N_scale_2g = htod16(atoi(p));
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+			if (p) {
+				proxd_tune->seq_5g20.N_tx_scale = htod16(atoi(p));
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+			if (p) {
+				proxd_tune->seq_5g20.N_rx_scale = htod16(atoi(p));
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+			if (p) {
+				proxd_tune->seq_2g20.N_tx_scale = htod16(atoi(p));
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+			if (p) {
+				proxd_tune->seq_2g20.N_rx_scale = htod16(atoi(p));
+			}
+		} else {
+			for (; i < TOF_BW_SEQ_NUM; i++) {
+				proxd_tune->N_scale[i] = htod16(mopt->val);
+			}
+			proxd_tune->N_scale_2g = htod16(mopt->val);
+			proxd_tune->seq_5g20.N_tx_scale = htod16(mopt->val);
+			proxd_tune->seq_5g20.N_rx_scale = htod16(mopt->val);
+			proxd_tune->seq_2g20.N_rx_scale = htod16(mopt->val);
+			proxd_tune->seq_2g20.N_rx_scale = htod16(mopt->val);
+		}
+		proxd_tune->setflags |= WL_PROXD_SETFLAG_S;
+	} else if (mopt->opt == 'F') {
+		int i = 0;
+		if (!mopt->good_int) {
+			char *p = mopt->valstr;
+			while (p && i < TOF_BW_SEQ_NUM) {
+				if (htod16(atoi(p)))
+					proxd_tune->ftm_cnt[i] = htod16(atoi(p));
+				i++;
+				p = strstr(p, ",");
+				if (p)
+					p++;
+			}
+		} else {
+			for (; i < TOF_BW_SEQ_NUM; i++) {
+				proxd_tune->ftm_cnt[i] = htod16(mopt->val);
+			}
+		}
+	} else if (mopt->opt == 't') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as total frmcnt\n",
+				cmd_name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->totalfrmcnt = (mopt->val);
+	} else if (mopt->opt == 'r') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as media reserve value\n",
+				cmd_name, mopt->valstr);
+				return BCME_USAGE_ERROR;
+			}
+			proxd_tune->rsv_media = (mopt->val);
+	} else if (mopt->opt == 'f') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"%s: could not parse \"%s\" as flags\n",
+				cmd_name, mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->flags = htod16(mopt->val);
+	} else if (mopt->opt == 'W') {
+		const char* n[4] = {"b", "l", "o", NULL};
+		const char* s[4] = {"s", "l", "o", NULL};
+		const char **p;
+		int v[TOF_BW_NUM] = {0, 0, 0};
+		int m[TOF_BW_NUM] = {0, 0, 0};
+		int i;
+		if (*mopt->valstr == 's')
+			p = s;
+		else
+			p = n;
+		proxd_method_tof_parse_mixed_param(mopt->valstr, p, v, m);
+		if (m[0]) {
+			/* Got bw */
+			if (v[0] == TOF_BW_80MHZ)
+				i = TOF_BW_80MHZ_INDEX;
+			else if (v[0] == TOF_BW_40MHZ)
+				i = TOF_BW_40MHZ_INDEX;
+			else if (v[0] == TOF_BW_20MHZ)
+				i = TOF_BW_20MHZ_INDEX;
+			else {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as window params\n",
+					cmd_name, mopt->valstr);
+					return BCME_USAGE_ERROR;
+			}
+			if (p == n) {
+				/* Normal */
+				if (m[1]) {
+					/* Got length */
+					proxd_tune->w_len[i] = (int16)v[1];
+				}
+				if (m[2]) {
+					/* Got offset */
+					proxd_tune->w_offset[i] = (int16)v[2];
+				}
+			} else {
+				/* Seq */
+				if (m[1] && i == TOF_BW_20MHZ_INDEX) {
+					/* Got length */
+					proxd_tune->seq_5g20.w_len = (int16)v[1];
+					proxd_tune->seq_2g20.w_len = (int16)v[1];
+				}
+				if (m[2]&& i == TOF_BW_20MHZ_INDEX) {
+					/* Got offset */
+					proxd_tune->seq_5g20.w_offset = (int16)v[2];
+					proxd_tune->seq_2g20.w_offset = (int16)v[2];
+				}
+			}
+		}
+	} else if (mopt->opt == 'B') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"proxd ftm tune: could not parse \"%s\" as bitflip_threshold\n",
+				mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->bitflip_thresh = htod16(mopt->val);
+	} else if (mopt->opt == 'R') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"proxd ftm tune: could not parse \"%s\" as snr_threshold\n",
+				mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->snr_thresh = htod16(mopt->val);
+	} else if (mopt->opt == 'T') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"proxd ftm tune: could not parse \"%s\" as recv_2g_threshold\n",
+				mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		if (mopt->val >= 0)
+			return BCME_RANGE;
+		proxd_tune->recv_2g_thresh = mopt->val;
+	} else if (mopt->opt == 'V') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"proxd ftm tune: could not parse \"%s\" as Auto Core Select "
+				"Group Delay Variance threshold\n",
+				mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->acs_gdv_thresh = htod32(mopt->val);
+	} else if (mopt->opt == 'I') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"proxd ftm tune: could not parse \"%s\" as Auto Core Select "
+				"RSSI threshold\n",
+				mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		if (mopt->val >= 0)
+			return BCME_RANGE;
+		proxd_tune->acs_rssi_thresh = mopt->val;
+	} else if (mopt->opt == 's') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"proxd ftm tune: could not parse \"%s\" as smoothing window "
+				"enable\n",
+				mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->smooth_win_en = mopt->val;
+	} else if (mopt->opt == 'M') {
+		if (!mopt->good_int) {
+			fprintf(stderr,
+				"proxd ftm tune: could not parse \"%s\" as auto core select "
+				"group delay max - min threshold\n",
+				mopt->valstr);
+			return BCME_USAGE_ERROR;
+		}
+		proxd_tune->acs_gdmm_thresh = htod32(mopt->val);
+	} else
+		return BCME_USAGE_ERROR;
+
+	return BCME_OK;
+}
+
+static int
+wl_proxd_tune(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_proxd_params_iovar_t proxd_tune, *reply;
+	uint16 method;
+	void *ptr = NULL;
+	int ret, opt_err;
+	miniopt_t to;
+
+	/* skip the command name and check if mandatory exists */
+	if (!*++argv) {
+		fprintf(stderr, "missing mandatory parameter \'method\'\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* parse method */
+	method = (uint16)atoi(argv[0]);
+	if (method == 0) {
+		fprintf(stderr, "invalid parameter \'method\'\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	bzero(&proxd_tune, sizeof(proxd_tune));
+
+	proxd_tune.method = htod16(method);
+	ret = wlu_var_getbuf_sm(wl, cmd->name, &proxd_tune, sizeof(proxd_tune), &ptr);
+	if (ret != BCME_OK) {
+		return ret;
+	}
+
+	if (!*++argv) {
+		/* get */
+		/* display proxd_params got */
+		reply = (wl_proxd_params_iovar_t *)ptr;
+
+		printf("bf proxd_params.method:%d\n", proxd_tune.method);
+		switch (proxd_tune.method) {
+		case PROXD_RSSI_METHOD:
+			break;
+
+		case PROXD_TOF_METHOD:
+			ret = proxd_tune_display(&reply->u.tof_tune, sizeof(reply->u.tof_tune));
+			break;
+
+		default:
+			fprintf(stderr,
+				"%s: ERROR undefined method \n", cmd->name);
+			return BCME_BADARG;
+		}
+	} else {
+		/* set */
+		memcpy((void *)&proxd_tune, (void *)ptr, sizeof(proxd_tune));
+		proxd_tune.method = method;
+
+		miniopt_init(&to, cmd->name, NULL, FALSE);
+		while ((opt_err = miniopt(&to, argv)) != -1) {
+			int meth_res = BCME_USAGE_ERROR;
+
+			if (opt_err == 1) {
+				return BCME_USAGE_ERROR;
+			}
+			argv += to.consumed;
+
+			/* method specific opts */
+			switch (method) {
+				case PROXD_RSSI_METHOD:
+					break;
+
+				case PROXD_TOF_METHOD:
+					meth_res = proxd_tune_set_param_from_opt(cmd->name,
+						&to, &proxd_tune.u.tof_tune);
+					break;
+
+				default:
+					printf("ERROR: unsupported method\n");
+					return BCME_USAGE_ERROR;
+			}
+
+			/*  if option is unknown to tune specific */
+			if (meth_res != BCME_OK) {
+				printf(">>>> Method:%d doesn't support cmd option:'%c'\n",
+					method, to.opt);
+				return meth_res;
+			}
+		}
+		ret = wlu_var_setbuf(wl, cmd->name, &proxd_tune, sizeof(proxd_tune));
+	}
+
+	return ret;
+}
+
+static const char *wl_proxd_mode_str(uint8 mode)
+{
+	static const char *proxd_mode[] = {"Undetected", "Neutral", "Initiator", "Target",
+		"UNKNOWN"};
+
+	if (mode > WL_PROXD_MODE_TARGET)
+		mode = WL_PROXD_MODE_TARGET+1;
+
+	return proxd_mode[mode];
+}
+static const char *wl_proxd_state_str(uint8 state)
+{
+	static const char *proxd_state[] = {"Poll", "Pairing", "Handshake", "Detected",
+		"Pipeline", "NegMode", "Monitor", "Unknown"};
+
+	if (state == RSSI_STATE_POLL)
+		return proxd_state[0];
+	if (state == RSSI_STATE_TPAIRING || state == RSSI_STATE_IPAIRING)
+		return proxd_state[1];
+	if (state == RSSI_STATE_THANDSHAKE || state == RSSI_STATE_IHANDSHAKE)
+		return proxd_state[2];
+	if (state == RSSI_STATE_CONFIRMED)
+		return proxd_state[3];
+	if (state == RSSI_STATE_PIPELINE)
+		return proxd_state[4];
+	if (state == RSSI_STATE_NEGMODE)
+		return proxd_state[5];
+	if (state == RSSI_STATE_MONITOR)
+		return proxd_state[6];
+
+	return proxd_state[7];
+}
+
+static const char *wl_proxd_tof_state_str(uint8 state)
+{
+	static const char *tof_proxd_state[] =
+		{"Idle", "Wait", "LegacyWait", "Confirmed", "Unknown", "Report"};
+
+	if (state == TOF_STATE_IDLE)
+		return tof_proxd_state[0];
+	if (state == TOF_STATE_IWAITM || state == TOF_STATE_TWAITM ||
+		state == TOF_STATE_IWAITCL || state == TOF_STATE_TWAITCL)
+		return tof_proxd_state[1];
+	if (state == TOF_STATE_ILEGACY)
+		return tof_proxd_state[2];
+	if (state == TOF_STATE_ICONFIRM)
+		return tof_proxd_state[3];
+	if (state == TOF_STATE_IREPORT)
+		return tof_proxd_state[5];
+
+	return tof_proxd_state[4];
+}
+
+static const char *wl_proxd_tof_reason_str(uint8 reason)
+{
+	static const char *tof_proxd_reason[] = {"OK", "RxedReqEnd", "Timeout",
+		"LostACK", "InvalidAVB"};
+
+	if (reason > TOF_REASON_INVALIDAVB)
+		reason = 0;
+
+	return tof_proxd_reason[reason];
+}
+
+static const char *wl_proxd_reason_str(uint8 reason)
+{
+	static const char *proxd_reason[] = {"Unknown", "Low rssi", "State machine out of SYNC",
+		"Timeout"};
+
+	if (reason > RSSI_REASON_TIMEOUT)
+		reason = 0;
+
+	return proxd_reason[reason];
+}
+
+static int
+wl_proxd_status(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_proxd_status_iovar_t status, *statusp;
+	int ret = BCME_BADARG;
+
+	if (!*++argv) {
+		/* Get */
+		bzero(&status, sizeof(wl_proxd_status_iovar_t));
+		if ((ret = wlu_iovar_get(wl, cmd->name, (void *) &status,
+			(sizeof(wl_proxd_status_iovar_t)))) < 0)
+			return (ret);
+
+		statusp = &status;
+		switch (statusp->method)
+		{
+			case PROXD_RSSI_METHOD:
+				printf("mode=%s\n", wl_proxd_mode_str(statusp->mode));
+				printf("state=%s\n", wl_proxd_state_str(statusp->state));
+				printf("peer mode=%s\n", wl_proxd_mode_str(statusp->peermode));
+				printf("peer=%s\n", wl_ether_etoa(&statusp->peer));
+				printf("lowest rssi=%d\n", statusp->low_rssi);
+				printf("highest rssi=%d\n", statusp->hi_rssi);
+				printf("tx pkts=%d\n", statusp->txcnt);
+				printf("rx pkts=%d\n", statusp->rxcnt);
+				printf("reason=%s\n\n", wl_proxd_reason_str(statusp->reason));
+				break;
+
+			case PROXD_TOF_METHOD:
+				printf("mode=%s\n", wl_proxd_mode_str(statusp->mode));
+				printf("state=%s\n", wl_proxd_tof_state_str(statusp->state));
+				if (statusp->distance == 0xffffffff)
+					printf("distance=-1\n");
+				else
+					printf("distance=%d.%04d\n", statusp->distance >> 4,
+						((statusp->distance & 0xf)*625));
+				printf("peer=%s\n", wl_ether_etoa(&statusp->peer));
+				printf("avg rssi=%d\n", statusp->avg_rssi);
+				printf("tx pkts=%d\n", statusp->txcnt);
+				printf("rx pkts=%d\n", statusp->rxcnt);
+				printf("frame types = CCK %d OFDM %d 11N %d 11AC %d\n",
+					statusp->frame_type_cnt[FRAME_TYPE_CCK],
+					statusp->frame_type_cnt[FRAME_TYPE_OFDM],
+					statusp->frame_type_cnt[FRAME_TYPE_11N],
+					statusp->frame_type_cnt[FRAME_TYPE_11AC]);
+				printf("adj types = SW %d HW %d SEQ %d NONE %d\n",
+					statusp->adj_type_cnt[TOF_ADJ_SOFTWARE],
+					statusp->adj_type_cnt[TOF_ADJ_HARDWARE],
+					statusp->adj_type_cnt[TOF_ADJ_SEQ],
+					statusp->adj_type_cnt[TOF_ADJ_NONE]);
+				printf("report status= %d\n", statusp->dbgstatus);
+				printf("reason=%s\n", wl_proxd_tof_reason_str(statusp->reason));
+				printf("frmcnt=%d\n", statusp->low_rssi);
+				if (statusp->hi_rssi == TOF_LEGACY_AP)
+					printf("measure=OneSide\n\n");
+				else
+					printf("measure=TwoSide\n\n");
+				break;
+
+			default:
+				printf("ERROR: unsupported method\n");
+				return BCME_USAGE_ERROR;
+		}
+	}
+	else
+		printf("Cannot set proxd_status\n");
+
+	return ret;
+}
+static int
+wl_proxd_payload(void *wl, cmd_t *cmd, char **argv)
+{
+	char *buf;
+	uint16 len, *reply;
+	int ret;
+
+	buf = malloc(WL_PROXD_PAYLOAD_LEN);
+	if (buf == NULL) {
+		fprintf(stderr, "Failed to allocate buffer of %d bytes\n", WL_PROXD_PAYLOAD_LEN);
+		return -1;
+	}
+	bzero(buf, WL_PROXD_PAYLOAD_LEN);
+
+	/* skip the command name and check if NULL */
+	if (!*++argv) {
+		/* Get */
+		if ((ret = wlu_iovar_get(wl, cmd->name, (void *)buf, WL_PROXD_PAYLOAD_LEN)) < 0) {
+			free(buf);
+			return (ret);
+		}
+		reply = (uint16 *)buf;
+		len = dtoh16(reply[0]);
+
+		if (len > 0) {
+			char *ptr = buf+sizeof(uint16);
+			char *endptr = ptr+len;
+			int num = 0;
+			uint8 val;
+
+			printf("Payload Length %d\n", len);
+			while (ptr < endptr)
+			{
+				val = *(uint8 *)ptr++;
+				printf("%02X", val);
+				if (++num == 40)
+				{
+					printf("\n");
+					num = 0;
+				}
+			}
+			if (num) printf("\n");
+		}
+	} else {
+		/* Set */
+		len = (uint16)atoi(argv[0]);
+		if (len > 0) {
+			if (!argv[1]) {
+				printf("Payload content is missing\n");
+				free(buf);
+				return -1;
+			}
+			else {
+				char *ptr = argv[1];
+				char *bufp = buf;
+				char hex[] = "XX";
+
+				if ((uint16)strlen(ptr) != len*2)
+				{
+					printf("Payload length mismatch %d %d\n", len,
+						((int)strlen(ptr))/2);
+					free(buf);
+					return -1;
+				}
+				while (*ptr) {
+					strncpy(hex, ptr, 2);
+					*bufp++ = (char) strtoul(hex, NULL, 16);
+					ptr += 2;
+				}
+			}
+		}
+		ret = wlu_var_setbuf(wl, cmd->name, buf, len);
+	}
+	free(buf);
+	return ret;
+}
+
+static int wl_proxd_report(void *wl, cmd_t *cmd, char **argv)
+{
+	uint16 len;
+	int i, ret;
+	struct ether_addr addrlist[WL_PROXD_MAXREPORT];
+
+	/* skip the command name and check if NULL */
+	if (!*++argv) {
+		/* Get */
+		len = sizeof(struct ether_addr) * WL_PROXD_MAXREPORT;
+		bzero(&addrlist[0], len);
+		if ((ret = wlu_iovar_get(wl, cmd->name, (void *)addrlist, len)) < 0) {
+			return (ret);
+		}
+
+		for (i = 0; i < WL_PROXD_MAXREPORT; i++)
+		{
+			if (ETHER_ISNULLADDR(&addrlist[i]))
+				break;
+			printf("%s ", wl_ether_etoa(&addrlist[i]));
+		}
+		printf("\n");
+	} else {
+		/* Set */
+		i = 0;
+		while (argv[0]) {
+			if (i >= WL_PROXD_MAXREPORT) {
+				printf("Over the maxium report number %d\n", WL_PROXD_MAXREPORT);
+				return BCME_BUFTOOLONG;
+			}
+			if (!wl_ether_atoe(argv[0], &addrlist[i])) {
+				if (i == 0)
+					return BCME_BADADDR;
+				break;
+			}
+			i++;
+			argv++;
+		}
+		ret = wlu_var_setbuf(wl, cmd->name, addrlist, ETHER_ADDR_LEN * i);
+	}
+
+	return ret;
+}
+
+/*   print or calculate & print location info   */
+void wl_proxd_tof_host_calc(wl_proxd_event_data_t* evp)
+{
+	uint32 distance;
+	uint32 meanrtt, modertt, medianrtt, dst_sigma;	/* standard deviation */
+	int ftm_cnt;
+	int16 avg_rssi, validfrmcnt;
+	int32 var1, var2, var3;
+	char diststr[40];
+
+	distance = ntoh32(evp->distance);
+	dst_sigma = ntoh32(evp->sdrtt);
+	ftm_cnt = ntoh16(evp->ftm_cnt);
+	avg_rssi = ntoh16(evp->avg_rssi);
+	validfrmcnt = ntoh16(evp->validfrmcnt);
+	meanrtt = ntoh32(evp->meanrtt);
+	modertt = ntoh32(evp->modertt);
+	medianrtt = ntoh32(evp->medianrtt);
+	var1 = ntoh32(evp->var1);
+	var2 = ntoh32(evp->var2);
+	var3 = ntoh32(evp->var3);
+
+	bzero(diststr, sizeof(diststr));
+	if (distance == 0xffffffff)
+		sprintf(diststr, "distance=-1m\n");
+	else
+		sprintf(diststr, "distance=%d.%04dm\n", distance>>4, (distance & 0xf) * 625);
+
+	if (ntoh16(evp->mode) == WL_PROXD_MODE_TARGET) {
+		if (evp->TOF_type == TOF_TYPE_REPORT) {
+			printf("Report:(%s) and ", wl_ether_etoa(&evp->peer_mac));
+			printf("(%s); %s", wl_ether_etoa((struct ether_addr *)
+				&evp->peer_router_info), diststr);
+		}
+		else
+		printf("Target:(%s); %s; ", wl_ether_etoa(&evp->peer_mac), diststr);
+		printf("mean %d mode %d median %d\n", meanrtt, modertt, medianrtt);
+	}
+	else
+		printf("Initiator:(%s); %s; ", wl_ether_etoa(&evp->peer_mac), diststr);
+
+	printf("sigma:%d.%d;", dst_sigma/10, dst_sigma % 10);
+	printf("rssi:%d validfrmcnt %d\n", avg_rssi, validfrmcnt);
+
+	if (evp->TOF_type == TOF_TYPE_REPORT)
+		printf("var3: %d\n", var3);
+	else
+	printf("var: %d %d %d\n", var1, var2, var3);
+
+	if (ftm_cnt > 1) {
+		int i;
+		printf("event contains %d rtd samples for host side calculation:\n",
+			ftm_cnt);
+
+		for (i = 0; i < ftm_cnt; i++) {
+			printf("ftm[%d] --> value:%d rssi:%d\n", i,
+				ntoh32(evp->ftm_buff[i].value), evp->ftm_buff[i].rssi);
+		}
+
+		printf("host side calculation result: TBD\n");
+		/* TODO: process raw samples */
+		/*  e.g:
+			1)  mean Mn = (S1+S2+... Sn)/N
+			2)  variatin: Xn = (Sn - M)^2;
+			3)  sqrt((X1 + X2 + .. Xn)/N)
+		*/
+	}
+}
+#ifdef WL_NAN
+static const char *wl_proxd_nan_status_str(uint8 status)
+{
+	static const char *proxd_nan_status[] = {"Unknown", "Success", "Fail", "Timeout", "Abort"};
+
+	if (status > WL_NAN_RANGING_STATUS_ABORT)
+		status = 0;
+
+	return proxd_nan_status[status];
+}
+
+/*   print or calculate & print nan event   */
+void wl_proxd_nan_host_calc(wl_nan_ranging_event_data_t* evp)
+{
+	wl_nan_ranging_result_t *rp;
+	int i;
+	uint32 distance;
+	uint32 dst_sigma;	/* standard deviation */
+	uint8 validfrmcnt;
+	char dist[40];
+
+	rp = evp->rr;
+	for (i = 0; i < evp->count; i++, rp++) {
+		distance = rp->distance;
+		dst_sigma = rp->rtt_var;
+		validfrmcnt = rp->sounding_count;
+
+		bzero(dist, sizeof(dist));
+		if (distance == 0xffffffff)
+			sprintf(dist, "distance=-1m\n");
+		else
+			sprintf(dist, "distance=%d.%dm\n", distance>>4, (distance & 0xf)*625);
+
+		if (evp->mode == WL_PROXD_MODE_TARGET) {
+			if (!ETHER_ISNULLADDR(&rp->tgtea)) {
+				printf("Report:(%s) and ", wl_ether_etoa(&rp->ea));
+				printf("(%s); %s", wl_ether_etoa(&rp->tgtea), dist);
+			}
+			else
+				printf("Target:(%s); %s; ", wl_ether_etoa(&rp->ea), dist);
+		}
+		else
+			printf("Initiator:(%s); %s", wl_ether_etoa(&rp->ea), dist);
+
+		printf("%s sigma:%d.%d validfrmcnt %d\n", wl_proxd_nan_status_str(rp->status),
+			dst_sigma/10, dst_sigma % 10, validfrmcnt);
+	}
+}
+#endif /* WL_NAN */
+
+#if defined(linux)
+/*   print timestamp info   */
+static void wl_proxd_tof_ts_results(wl_proxd_event_ts_results_t* tsp)
+{
+	int16 ver;
+	int tscnt;
+	int i;
+
+	ver = ntoh16(tsp->ver);
+	tscnt = ntoh16(tsp->ts_cnt);
+	if (ver == 2) {
+		printf("Frame Count %d\n Timestamps:\n", tscnt);
+		if (tscnt > 0) {
+			for (i = 0; i < tscnt; i++) {
+				printf("t1[%d]=%u : t2[%d]=%u : t3[%d]=%u : t4[%d]=%u\n",
+					i, ntoh32(tsp->ts_buff[i].t1),
+					i, ntoh32(tsp->ts_buff[i].t2),
+					i, ntoh32(tsp->ts_buff[i].t3),
+					i, ntoh32(tsp->ts_buff[i].t4));
+			}
+		}
+	}
+}
+
+#define PROXD_EVENTS_BUFFER_SIZE 2048
+static int
+wl_proxd_event_check(void *wl, cmd_t *cmd, char **argv)
+{
+	bool exit_on1stresult = FALSE;
+	int fd, err, octets;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	char ifnames[IFNAMSIZ] = {"eth0"};
+	bcm_event_t *event;
+	uint32 reason;
+	uint16 mode; /* target or initiator */
+	char* data;
+	int event_type;
+	uint8 event_inds_mask[WL_EVENTING_MASK_LEN];	/* 128-bit mask */
+	wl_proxd_event_data_t* evp = NULL;
+#ifdef WL_NAN
+	wl_nan_ranging_event_data_t *nanevp = NULL;
+#endif
+	wl_proxd_event_ts_results_t* tsp = NULL;
+
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if (argv[1] == NULL) {
+		printf("<ifname> param is missing\n");
+		return -1;
+	}
+
+	if (*++argv) {
+		strncpy(ifnames, *argv, (IFNAMSIZ - 1));
+	}
+
+	bzero(&ifr, sizeof(ifr));
+	strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+
+
+	/*  read current mask state  */
+	if ((err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN))) {
+		printf("couldn't read event_msgs\n");
+		return (err);
+	}
+	event_inds_mask[WLC_E_PROXD / 8] |= 1 << (WLC_E_PROXD % 8);
+	if ((err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN)))
+		return (err);
+
+	if (*++argv) {
+		if (strcmp(*argv, "osh") == 0) {
+			/* exit after processing 1st proximity result */;
+			exit_on1stresult = TRUE;
+		}
+	}
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETHER_TYPE_BRCM));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		return -1;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get iface:%s index \n", ifr.ifr_name);
+		goto exit1;
+	}
+
+	bzero(&sll, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETHER_TYPE_BRCM);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		goto exit1;
+	}
+
+	data = (char*)malloc(PROXD_EVENTS_BUFFER_SIZE);
+
+	if (data == NULL) {
+		printf("Cannot not allocate %d bytes for events receive buffer\n",
+			PROXD_EVENTS_BUFFER_SIZE);
+		goto exit1;
+	}
+
+	printf("waiting for LBS events :%s\n", ifr.ifr_name);
+
+	while (1) {
+		fflush(stdout);
+		octets = recv(fd, data, PROXD_EVENTS_BUFFER_SIZE, 0);
+
+		if (octets <= 0)  {
+			/* sigterm */
+			err = -1;
+			break;
+		}
+
+		event = (bcm_event_t *)data;
+		event_type = ntoh32(event->event.event_type);
+		reason = ntoh32(event->event.reason);
+
+#ifdef WL_FTM_DEBUG
+		printf("%s: event_type 0x%x, ntoh32()=0x%x, ltoh32()=0x%x\n",
+			__FUNCTION__, event->event.event_type, event_type,
+			ltoh32(event->event.event_type));
+#endif /* WL_FTM_DEBUG */
+
+		if ((event_type != WLC_E_PROXD)) {
+		/* may be other BCM events we are not interested in */
+#ifdef WL_FTM_DEBUG
+			printf("WARNING: not a proxd BCM_EVENT:%d\n", event_type);
+#endif /* WL_FTM_DEBUG */
+				continue;
+		}
+
+		/* check 'version' for FTM events */
+		if (ftm_event_check((bcm_event_t *) data) == 0)
+			continue;		/* continue to rx event */
+		/* continue to handle non-FTM events */
+
+#ifdef WL_NAN
+		if (reason == WLC_E_PROXD_NAN_EVENT) {
+			nanevp = (wl_nan_ranging_event_data_t *)&data[sizeof(bcm_event_t)];
+			mode = nanevp->mode;
+		}
+		else
+#endif
+		if (reason == WLC_E_PROXD_TS_RESULTS) {
+			tsp = (wl_proxd_event_ts_results_t*)&data[sizeof(bcm_event_t)];
+			mode = ntoh16(tsp->mode);
+		} else {
+		/* move to bcm event payload, which is proxd event structure */
+		evp = (wl_proxd_event_data_t*)&data[sizeof(bcm_event_t)];
+		mode = ntoh16(evp->mode);
+		}
+
+		printf("mode:%s; event:",
+			(mode == WL_PROXD_MODE_INITIATOR)?"initiator":"target");
+
+		switch (reason) {
+		case WLC_E_PROXD_FOUND:
+			printf("WLC_E_PROXD_FOUND; ");
+			wl_proxd_tof_host_calc(evp); /* backward compatibility with RSSI method */
+			break;
+		case WLC_E_PROXD_GONE:
+			printf("WLC_E_PROXD_GONE; ");
+			break;
+		case WLC_E_PROXD_START:
+			/* event for targets / accesspoints  */
+			printf("WLC_E_PROXD_START; ");
+			break;
+		case WLC_E_PROXD_STOP:
+			printf("WLC_E_PROXD_STOP; ");
+		break;
+		case WLC_E_PROXD_COMPLETED:
+			printf("WLC_E_PROXD_COMPLETED; ");
+			/* all new method results should land here */
+			wl_proxd_tof_host_calc(evp);
+			if (exit_on1stresult)
+				goto exit0;
+			break;
+		case WLC_E_PROXD_TS_RESULTS:
+			printf("WLC_E_PROXD_TS_RESULTS; ");
+			wl_proxd_tof_ts_results(tsp);
+			if (exit_on1stresult)
+				goto exit0;
+			break;
+		case WLC_E_PROXD_ERROR:
+			printf("WLC_E_PROXD_ERROR:%d;", evp->err_code);
+			/* all new method results should land here */
+			wl_proxd_tof_host_calc(evp);
+			if (exit_on1stresult)
+				goto exit0;
+			break;
+		case WLC_E_PROXD_COLLECT_START:
+			printf("WLC_E_PROXD_COLLECT_START; ");
+			break;
+		case WLC_E_PROXD_COLLECT_STOP:
+			printf("WLC_E_PROXD_COLLECT_STOP; ");
+			break;
+		case WLC_E_PROXD_COLLECT_COMPLETED:
+			printf("WLC_E_PROXD_COLLECT_COMPLETED; ");
+			break;
+		case WLC_E_PROXD_COLLECT_ERROR:
+			printf("WLC_E_PROXD_COLLECT_ERROR; ");
+			break;
+#ifdef WL_NAN
+		case WLC_E_PROXD_NAN_EVENT:
+			printf("WLC_E_NAN_EVENT; ");
+			wl_proxd_nan_host_calc(nanevp);
+			break;
+#endif
+		default:
+			printf("ERROR: unsupported EVENT reason code:%d; ",
+				reason);
+			err = -1;
+			break;
+		}
+
+		printf("\n");
+	}
+exit0:
+	/* if we ever reach here */
+	free(data);
+exit1:
+	close(fd);
+
+	/* Read the event mask from driver and mask the event WLC_E_PROXD */
+	if (!(err = wlu_iovar_get(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN))) {
+		event_inds_mask[WLC_E_PROXD / 8] &= (~(1 << (WLC_E_PROXD % 8)));
+		err = wlu_iovar_set(wl, "event_msgs", &event_inds_mask, WL_EVENTING_MASK_LEN);
+	}
+
+	fflush(stdout);
+	return (err);
+}
+#endif /* linux */
+
+#if defined(WL_NAN)
+static int wl_nan_ranging_config(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_nan_ranging_config_t	nanconfig, *pnan_config;
+	char chspec_str[CHANSPEC_STR_LEN];
+	int 	rc;
+	void	*ptr = NULL;
+	int	count;
+	chanspec_t chanspec;
+
+	count = ARGCNT(argv);
+
+	/* GET operation */
+	if (*++argv == NULL) {
+		if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return rc;
+		pnan_config = (wl_nan_ranging_config_t *)ptr;
+		wf_chspec_ntoa(pnan_config->chanspec, chspec_str);
+		printf("chanspec:           %s(0x%04x)\n", chspec_str, pnan_config->chanspec);
+		printf("timeslot:           %d\n", pnan_config->timeslot);
+		printf("duration:           %d\n", pnan_config->duration);
+		printf("allowed mac:        %02x:%02x:%02x:%02x:%02x:%02x\n",
+			pnan_config->allow_mac.octet[0],
+			pnan_config->allow_mac.octet[1],
+			pnan_config->allow_mac.octet[2],
+			pnan_config->allow_mac.octet[3],
+			pnan_config->allow_mac.octet[4],
+			pnan_config->allow_mac.octet[5]);
+		printf("flags:              0x%04x\n", pnan_config->flags);
+		return rc;
+	}
+
+	/*
+	** Set the attributes.
+	*/
+	if (count < 4) {
+		return BCME_USAGE_ERROR;
+	}
+
+	pnan_config = &nanconfig;
+
+	if ((chanspec = wf_chspec_aton(*argv)) == 0) {
+		fprintf(stderr, "%s: could not parse \"%s\" as a channel\n",
+			cmd->name, *argv);
+		return BCME_BADARG;
+	}
+
+	pnan_config->chanspec = wl_chspec_to_driver(chanspec);
+
+	if (pnan_config->chanspec == INVCHANSPEC) {
+		fprintf(stderr, "%s: wl_chspec_to_driver() error \"%s\" \n",
+			cmd->name, *argv);
+		return BCME_BADARG;
+	}
+
+	pnan_config->timeslot = strtoul(*++argv, NULL, 0);
+	if (pnan_config->timeslot == 0 || pnan_config->timeslot >= 512) {
+		fprintf(stderr, "Invalid timeslot \"%s\" \n", *argv);
+		return BCME_BADARG;
+	}
+
+	pnan_config->duration = strtoul(*++argv, NULL, 0);
+	if (pnan_config->duration == 0 || pnan_config->duration >= 512) {
+		fprintf(stderr, "Invalid duration \"%s\" \n", *argv);
+		return BCME_BADARG;
+	}
+
+	if (*++argv) {
+		/* MAC address */
+		if (!wl_ether_atoe(*argv, &pnan_config->allow_mac)) {
+			fprintf(stderr, "nan ranging config mac addr err\n");
+			return BCME_BADARG;
+		}
+		if (*++argv) {
+			pnan_config->flags = strtoul(*argv, NULL, 0);
+		} else
+			pnan_config->flags = 0;
+	} else {
+		memcpy(&pnan_config->allow_mac, &ether_bcast, ETHER_ADDR_LEN);
+		pnan_config->flags = 0;
+	}
+
+	rc = wlu_var_setbuf(wl, cmd->name, pnan_config, sizeof(wl_nan_ranging_config_t));
+
+	return (rc);
+}
+
+static int wl_nan_ranging_start(void *wl, cmd_t *cmd, char **argv)
+{
+	const char  *str;
+	wl_nan_ranging_list_t *pnan_list;
+	int	buf_len;
+	int	str_len;
+	int 	rc, i;
+	void	*ptr = NULL;
+	int count;
+	chanspec_t chanspec;
+
+	count = ARGCNT(argv);
+
+	/* GET operation */
+	if (*++argv == NULL) {
+		if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return rc;
+		pnan_list = (wl_nan_ranging_list_t *)ptr;
+		printf("num peers:       %d \n", pnan_list->count);
+		printf("num peers done:  %d \n", pnan_list->num_peers_done);
+		printf("num dws:         %d \n", pnan_list->num_dws);
+
+		printf("----------------------------------------------------------------------\n");
+		printf("Address \t\tchanspec\tcount\tretry\tabitmap\tflags\n");
+		for (i = 0; i < pnan_list->count; i++) {
+			printf("%02x:%02x:%02x:%02x:%02x:%02x\t0x%04x\t\t%d\t%d\t0x%x\t0x%x\n",
+				pnan_list->rp[i].ea.octet[0],
+				pnan_list->rp[i].ea.octet[1],
+				pnan_list->rp[i].ea.octet[2],
+				pnan_list->rp[i].ea.octet[3],
+				pnan_list->rp[i].ea.octet[4],
+				pnan_list->rp[i].ea.octet[5],
+				pnan_list->rp[i].chanspec,
+				pnan_list->rp[i].frmcnt,
+				pnan_list->rp[i].retrycnt,
+				pnan_list->rp[i].abitmap,
+				pnan_list->rp[i].flags);
+		}
+		return rc;
+	}
+
+	/*
+	** Set the attributes.
+	*/
+	if ((count % 6) != 2) {
+		return BCME_USAGE_ERROR;
+	}
+
+	str = cmd->name;
+	str_len = strlen(str);
+	strncpy(buf, str, str_len);
+	buf[ str_len ] = '\0';
+
+	pnan_list = (wl_nan_ranging_list_t *) (buf + str_len + 1);
+	pnan_list->count = count/6;
+	pnan_list->num_peers_done = 0;
+	pnan_list->num_dws =  strtoul(*argv++, NULL, 0);
+	for (i = 0; i < pnan_list->count; i++, argv++) {
+		if ((chanspec = wf_chspec_aton(*argv)) == 0) {
+			fprintf(stderr, "%s: could not parse \"%s\" as a channel\n",
+				cmd->name, *argv);
+			return BCME_BADARG;
+		}
+
+		pnan_list->rp[i].chanspec = wl_chspec_to_driver(chanspec);
+
+		if (pnan_list->rp[i].chanspec == INVCHANSPEC) {
+			fprintf(stderr, "%s: wl_chspec_to_driver() error \"%s\" \n",
+				cmd->name, *argv);
+			return BCME_BADARG;
+		}
+
+		if (!wl_ether_atoe(*++argv, &pnan_list->rp[i].ea)) {
+			fprintf(stderr, "ranging mac addr err\n");
+			return BCME_BADADDR;
+		}
+
+		pnan_list->rp[i].abitmap = strtoul(*++argv, NULL, 0);
+		pnan_list->rp[i].frmcnt = strtoul(*++argv, NULL, 0);
+		if (pnan_list->rp[i].frmcnt >= 255) {
+			fprintf(stderr, "Invalid frame count \"%s\" \n", *argv);
+			return BCME_BADARG;
+		}
+
+		pnan_list->rp[i].retrycnt = strtoul(*++argv, NULL, 0);
+		pnan_list->rp[i].flags = strtoul(*++argv, NULL, 0);
+	}
+
+	fprintf(stderr, "count %d\n", pnan_list->count);
+	buf_len = str_len + 1 + sizeof(wl_nan_ranging_list_t) +
+		sizeof(wl_nan_ranging_peer_t) * (pnan_list->count - 1);
+
+	rc = wlu_set(wl, WLC_SET_VAR, buf, buf_len);
+
+	return (rc);
+}
+
+static int wl_nan_ranging_results_host(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_nan_ranging_event_data_t *pnan_event;
+	int rc, i;
+	void *ptr = NULL;
+
+	UNUSED_PARAMETER(argv);
+	if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return rc;
+	pnan_event = (wl_nan_ranging_event_data_t *) ptr;
+	printf("num results:       %d \n", pnan_event->count);
+	printf("num good results:  %d \n", pnan_event->success_count);
+	printf("------------------------------------------------------------------------------\n");
+	printf("Address\t\t\tchanspec\tvalidcnt\tts\t\tdist\tstatus\n");
+	for (i = 0; i < pnan_event->count; i++) {
+		printf("%02x:%02x:%02x:%02x:%02x:%02x\t",
+			pnan_event->rr[i].ea.octet[0],
+			pnan_event->rr[i].ea.octet[1],
+			pnan_event->rr[i].ea.octet[2],
+			pnan_event->rr[i].ea.octet[3],
+			pnan_event->rr[i].ea.octet[4],
+			pnan_event->rr[i].ea.octet[5]);
+		printf("%04x\t\t%d\t\t%u\t",
+			pnan_event->rr[i].chanspec,
+			pnan_event->rr[i].sounding_count,
+			pnan_event->rr[i].timestamp);
+		if (pnan_event->rr[i].distance == 0xffffffff)
+			printf("-1\t");
+		else
+			printf("%d.%04d\t", pnan_event->rr[i].distance >> 4,
+				(pnan_event->rr[i].distance & 0x0f) * 625);
+		printf("%s\n", wl_proxd_nan_status_str(pnan_event->rr[i].status));
+	}
+
+	return (rc);
+}
+#endif /* WL_NAN */
+
+/*
+*  proxd ftm sub-commands info and handlers
+*/
+typedef struct ftm_subcmd_info ftm_subcmd_info_t;
+typedef int (ftm_cmd_handler_t)(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv);
+
+/* bitmask indicating which command groups; */
+typedef enum {
+	FTM_SUBCMD_FLAG_METHOD	= 0x01,	/* FTM method command */
+	FTM_SUBCMD_FLAG_SESSION = 0x02,	/* FTM session command */
+	FTM_SUBCMD_FLAG_ALL = FTM_SUBCMD_FLAG_METHOD | FTM_SUBCMD_FLAG_SESSION
+} ftm_subcmd_flag_t;
+
+struct ftm_subcmd_info {
+	char				*name;		/* cmd-name string as cmdline input */
+	wl_proxd_cmd_t		cmdid;		/* cmd-id */
+	ftm_cmd_handler_t	*handler;	/* cmd-handler */
+	ftm_subcmd_flag_t	cmdflag;
+	char				*helpmsg;	/* messages for 'wl proxd -h ftm' */
+};
+
+#define FTM_IOC_BUFSZ  2048	/* ioc buffsize for our module (> BCM_XTLV_HDR_SIZE) */
+
+/* declare proxd ftm-method command handlers ftm_subcmd_xxxx() */
+/* e.g. static ftm_cmd_handler_t ftm_subcmd_get_version; */
+#define FTM_SUBCMD_FUNC(suffix) ftm_subcmd_ ##suffix
+#define DECL_CMDHANDLER(X) static ftm_cmd_handler_t ftm_subcmd_##X
+
+/* get */
+DECL_CMDHANDLER(get_version);		/* method-only */
+DECL_CMDHANDLER(get_result);		/* session-only */
+DECL_CMDHANDLER(get_info);			/* method + session */
+DECL_CMDHANDLER(get_status);		/* method + session */
+DECL_CMDHANDLER(get_sessions);		/* method-only */
+DECL_CMDHANDLER(get_counters);		/* method + session */
+DECL_CMDHANDLER(dump);				/* method + session */
+DECL_CMDHANDLER(get_ranging_info);		/* method-only */
+
+/* set */
+DECL_CMDHANDLER(enable);			/* method-only */
+DECL_CMDHANDLER(disable);			/* method-only */
+DECL_CMDHANDLER(config);			/* method + session */
+DECL_CMDHANDLER(start_session);		/* session-only */
+DECL_CMDHANDLER(burst_request);		/* session-only */
+DECL_CMDHANDLER(stop_session);		/* session-only */
+DECL_CMDHANDLER(delete_session);	/* session-only */
+DECL_CMDHANDLER(clear_counters);	/* method + session */
+DECL_CMDHANDLER(start_ranging);		/* method-only */
+DECL_CMDHANDLER(stop_ranging);		/* method-only */
+
+DECL_CMDHANDLER(tune);			/* method-only both set/get */
+
+static const ftm_subcmd_info_t ftm_cmdlist[] = {
+	/* (get) wl proxd ftm ver */
+	{"ver", WL_PROXD_CMD_GET_VERSION, FTM_SUBCMD_FUNC(get_version),
+	FTM_SUBCMD_FLAG_METHOD, "Get the proxd FTM method API version information" },
+	/* (get) wl proxd ftm <session-id> result */
+	{"result", WL_PROXD_CMD_GET_RESULT, FTM_SUBCMD_FUNC(get_result),
+	FTM_SUBCMD_FLAG_SESSION, "Get a session result" },
+	/* (get) wl proxd ftm [<session-id>] info */
+	{"info", WL_PROXD_CMD_GET_INFO, FTM_SUBCMD_FUNC(get_info),
+	FTM_SUBCMD_FLAG_METHOD | FTM_SUBCMD_FLAG_SESSION,
+	"Get the detail information for the FTM method or a specific session" },
+	/* (get) wl proxd ftm [<session-id>] status */
+	{"status", WL_PROXD_CMD_GET_STATUS, FTM_SUBCMD_FUNC(get_status),
+	FTM_SUBCMD_FLAG_METHOD | FTM_SUBCMD_FLAG_SESSION,
+	"Get the status for the FTM method or a specific session" },
+	/* (get) wl proxd ftm sessions */
+	{"sessions", WL_PROXD_CMD_GET_SESSIONS, FTM_SUBCMD_FUNC(get_sessions),
+	FTM_SUBCMD_FLAG_METHOD, "List all sessions" },
+	/* (get) wl proxd ftm [<session-id>] counters */
+	{"counters", WL_PROXD_CMD_GET_COUNTERS, FTM_SUBCMD_FUNC(get_counters),
+	FTM_SUBCMD_FLAG_METHOD | FTM_SUBCMD_FLAG_SESSION,
+	"Get the counters for the FTM method or a specific session" },
+	/* (get) wl proxd ftm ranging-info */
+	{ "ranging-info", WL_PROXD_CMD_GET_RANGING_INFO, FTM_SUBCMD_FUNC(get_ranging_info),
+	FTM_SUBCMD_FLAG_METHOD,
+	"Get the ranging information for the FTM method" },
+	/* (get) wl proxd ftm [<session-id>] dump */
+	{"dump", WL_PROXD_CMD_DUMP, FTM_SUBCMD_FUNC(dump),
+	FTM_SUBCMD_FLAG_METHOD | FTM_SUBCMD_FLAG_SESSION,
+	"Dump all information for the FTM method or a specific session" },
+	/* (set) wl proxd ftm enable */
+	{"enable", WL_PROXD_CMD_ENABLE, FTM_SUBCMD_FUNC(enable),
+	FTM_SUBCMD_FLAG_METHOD, "Enable proximity detection using FTM method" },
+	/* (set) wl proxd ftm disable */
+	{"disable", WL_PROXD_CMD_DISABLE, FTM_SUBCMD_FUNC(disable),
+	FTM_SUBCMD_FLAG_METHOD, "Disable proximity detection using FTM method" },
+	/* wl proxd ftm [<session-id>] config .... */
+	{"config", WL_PROXD_CMD_CONFIG, FTM_SUBCMD_FUNC(config),
+	FTM_SUBCMD_FLAG_METHOD | FTM_SUBCMD_FLAG_SESSION,
+	"Set the configuration for the FTM method or a specific session" },
+	/* (set) wl proxd ftm <session-id> start */
+	{"start", WL_PROXD_CMD_START_SESSION, FTM_SUBCMD_FUNC(start_session),
+	FTM_SUBCMD_FLAG_SESSION, "Start scheduling the burst(s) for a session" },
+	/* (set) wl proxd ftm <session-id> burst-request */
+	{"burst-request", WL_PROXD_CMD_BURST_REQUEST, FTM_SUBCMD_FUNC(burst_request),
+	FTM_SUBCMD_FLAG_SESSION,
+	"On initiator, send burst requests and process FTM frames. On target, send FTM frames" },
+	/* (set) wl proxd ftm <session-id> stop */
+	{"stop", WL_PROXD_CMD_STOP_SESSION, FTM_SUBCMD_FUNC(stop_session),
+	FTM_SUBCMD_FLAG_SESSION, "Stop a session" },
+	/* (set) wl proxd ftm <session-id> delete */
+	{"delete", WL_PROXD_CMD_DELETE_SESSION, FTM_SUBCMD_FUNC(delete_session),
+	FTM_SUBCMD_FLAG_SESSION, "Delete a session" },
+	/* (set) wl proxd ftm [<session-id>] clear_counters */
+	{"clear-counters", WL_PROXD_CMD_CLEAR_COUNTERS, FTM_SUBCMD_FUNC(clear_counters),
+	FTM_SUBCMD_FLAG_METHOD | FTM_SUBCMD_FLAG_SESSION,
+	"Clear the counters for the FTM method or a specific session" },
+	{"start-ranging", WL_PROXD_CMD_START_RANGING, FTM_SUBCMD_FUNC(start_ranging),
+	FTM_SUBCMD_FLAG_METHOD, "Start ranging for sessions" },
+	{ "stop-ranging", WL_PROXD_CMD_STOP_RANGING, FTM_SUBCMD_FUNC(stop_ranging),
+	FTM_SUBCMD_FLAG_METHOD, "Stop ranging" },
+	{ "tune", WL_PROXD_CMD_TUNE, FTM_SUBCMD_FUNC(tune),
+	FTM_SUBCMD_FLAG_METHOD, "proxd_tune" },
+};
+
+/*
+* get subcmd info for a specific FTM 'cmdname'
+* return NULL if specified <cmdname> is not supported.
+*/
+const ftm_subcmd_info_t *
+ftm_get_subcmd_info(char *cmdname)
+{
+	int i;
+	const ftm_subcmd_info_t *p_subcmd_info;
+
+	/* search for the specified cmdname from the pre-defined supported cmd list */
+	p_subcmd_info = &ftm_cmdlist[0];
+	for (i = 0; i < (int) ARRAYSIZE(ftm_cmdlist); i++) {
+		if (stricmp(p_subcmd_info->name, cmdname) == 0)
+			return p_subcmd_info;
+		p_subcmd_info++;
+	}
+
+	return NULL; /* cmd not supported */
+}
+
+/*
+* 'wl proxd ascii-method' handler
+*     handle 'wl proxd ftm [<session-id>] <cmdname> [<param-name><param-value>]*'
+*/
+static int
+wl_proxd_cmd_method_handler(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_proxd_method_t method;
+	wl_proxd_session_id_t	session_id;
+	const ftm_subcmd_info_t *p_subcmd_info;
+
+	/* ignore the command name 'proxd' */
+	UNUSED_PARAMETER(cmd);
+
+	/* check for "wl proxd -h ftm" or "wl proxd help ftm" --> display the usage */
+	if (!stricmp(*argv, "-h") || !stricmp(*argv, "help"))  {
+		return ftm_handle_help(++argv); /* return BCME_USAGE_ERROR; */
+	}
+
+	/* parse proxd-method, currently only support 'ftm' */
+	if (stricmp(*argv, "ftm") != 0) {			/* un-supported proxd-method */
+		printf("error: proxd-method '%s' is not supported\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+	method = WL_PROXD_METHOD_FTM;
+
+	/* skip 'ftm-method' and parse session-id if specified */
+	session_id = WL_PROXD_SESSION_ID_GLOBAL;
+	if (*++argv) {
+		if (isdigit((int)*argv[0])) {
+			session_id = (wl_proxd_session_id_t) atoi(argv[0]);
+			argv++;			/* skip to 'cmdname' */
+		}
+	}
+
+	/* parse 'cmd' in "wl proxd ftm [<session-id>] <cmd> [<param-name><param-value>]*" */
+	if (!*argv) {
+		printf("error: proxd ftm-method cmdname is not specified\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* search for the specified <cmdname> from the pre-defined supported cmd list */
+	p_subcmd_info = ftm_get_subcmd_info(*argv);
+	if (p_subcmd_info == NULL) {
+		/* cannot find the cmd in the ftm_cmdlist */
+		printf("error: invalid proxd ftm command '%s'\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* dispacth cmd to appropriate handler */
+	if (p_subcmd_info->handler) {
+		/* For 'method-only' commands, 'session-id' can be omitted */
+		if (((p_subcmd_info->cmdflag & FTM_SUBCMD_FLAG_METHOD) != 0) &&
+			((p_subcmd_info->cmdflag & FTM_SUBCMD_FLAG_SESSION) == 0)) {
+			if (session_id != WL_PROXD_SESSION_ID_GLOBAL) {
+				printf("proxd ftm %s: error, does not accept non-zero session-id\n",
+					p_subcmd_info->name);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		/* For 'session-only' commands, 'session-id' must be provided */
+		if (((p_subcmd_info->cmdflag & FTM_SUBCMD_FLAG_METHOD) == 0) &&
+			((p_subcmd_info->cmdflag & FTM_SUBCMD_FLAG_SESSION) != 0)) {
+			if (session_id == WL_PROXD_SESSION_ID_GLOBAL) {
+				printf("proxd ftm %s: error, please specify a valid session-id\n",
+					p_subcmd_info->name);
+				return BCME_USAGE_ERROR;
+			}
+		}
+
+		return p_subcmd_info->handler(wl, p_subcmd_info, method, session_id, ++argv);
+	}
+
+	return BCME_OK;
+
+}
+
+/*
+* definition for id-string mapping.
+*   This is used to map an id (can be cmd-id, tlv-id, ....) to a text-string
+*   for debug-display or cmd-log-display
+*/
+typedef struct ftm_strmap_entry {
+	int32		id;
+	char		*text;
+} ftm_strmap_entry_t;
+
+/*
+* lookup 'id' (as a key) from a table
+* if found, return the entry pointer, otherwise return NULL
+*/
+static const ftm_strmap_entry_t*
+ftm_get_strmap_info(int32 id, const ftm_strmap_entry_t *p_table, uint32 num_entries)
+{
+	int i;
+	const ftm_strmap_entry_t *p_entry;
+
+	/* scan thru the table till end */
+	p_entry = p_table;
+	for (i = 0; i < (int) num_entries; i++)
+	{
+		if (p_entry->id == id)
+			return p_entry;
+		p_entry++;		/* next entry */
+	}
+
+	return NULL;			/* not found */
+}
+
+/*
+* lookup 'str' (as a key) from a table
+* if found, return the entry pointer, otherwise return NULL
+*/
+static const ftm_strmap_entry_t*
+ftm_get_strmap_info_strkey(char *strkey, const ftm_strmap_entry_t *p_table, uint32 num_entries)
+{
+	int i;
+	const ftm_strmap_entry_t *p_entry;
+
+	/* scan thru the table till end */
+	p_entry = p_table;
+	for (i = 0; i < (int) num_entries; i++)
+	{
+		if (stricmp(p_entry->text, strkey) == 0)
+			return p_entry;
+		p_entry++;		/* next entry */
+	}
+
+	return NULL;			/* not found */
+}
+
+/*
+* map enum to a text-string for display, this function is called by the following:
+* For debug/trace:
+*     ftm_[cmdid|tlvid]_to_str()
+* For TLV-output log for 'get' commands
+*     ftm_[method|tmu|caps|status|state]_value_to_logstr()
+* Input:
+*     pTable -- point to a 'enum to string' table.
+*/
+static const char *
+ftm_map_id_to_str(int32 id, const ftm_strmap_entry_t *p_table, uint32 num_entries)
+{
+	const ftm_strmap_entry_t*p_entry = ftm_get_strmap_info(id, p_table, num_entries);
+	if (p_entry)
+		return (p_entry->text);
+
+	return "invalid";
+}
+
+/* define entry, e.g. { WL_PROXD_CMD_xxx, "WL_PROXD_CMD_xxx" } */
+#define DEF_STRMAP_ENTRY(id) { (id), #id }
+
+#ifdef WL_FTM_DEBUG
+/* ftm cmd-id mapping */
+static const ftm_strmap_entry_t ftm_cmdid_map[] = {
+	/* {wl_proxd_cmd_t(WL_PROXD_CMD_xxx), "WL_PROXD_CMD_xxx" }, */
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_NONE),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_VERSION),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_ENABLE),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_DISABLE),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_CONFIG),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_START_SESSION),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_BURST_REQUEST),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_STOP_SESSION),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_DELETE_SESSION),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_RESULT),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_INFO),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_STATUS),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_SESSIONS),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_COUNTERS),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_CLEAR_COUNTERS),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_DUMP),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_START_RANGING),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_STOP_RANGING),
+	DEF_STRMAP_ENTRY(WL_PROXD_CMD_GET_RANGING_INFO),
+};
+
+/*
+* map a ftm cmd-id to a text-string for display
+*/
+static const char *
+ftm_cmdid_to_str(uint16 cmdid)
+{
+	return ftm_map_id_to_str((int32) cmdid, &ftm_cmdid_map[0], ARRAYSIZE(ftm_cmdid_map));
+}
+#endif /* WL_FTM_DEBUG */
+
+/* ftm tlv-id mapping */
+static const ftm_strmap_entry_t ftm_tlvid_loginfo[] = {
+	/* { WL_PROXD_TLV_ID_xxx,				"text for WL_PROXD_TLV_ID_xxx" }, */
+	{ WL_PROXD_TLV_ID_NONE,					"none" },
+	{ WL_PROXD_TLV_ID_METHOD,				"method" },
+	{ WL_PROXD_TLV_ID_FLAGS,				"flags" },
+	{ WL_PROXD_TLV_ID_CHANSPEC,				"chanspec" },
+	{ WL_PROXD_TLV_ID_TX_POWER,				"tx power" },
+	{ WL_PROXD_TLV_ID_RATESPEC,				"ratespec" },
+	{ WL_PROXD_TLV_ID_BURST_DURATION,		"burst duration" },
+	{ WL_PROXD_TLV_ID_BURST_PERIOD,			"burst period" },
+	{ WL_PROXD_TLV_ID_BURST_FTM_SEP,		"burst ftm sep" },
+	{ WL_PROXD_TLV_ID_BURST_NUM_FTM,		"burst num ftm" },
+	{ WL_PROXD_TLV_ID_NUM_BURST,			"num burst" },
+	{ WL_PROXD_TLV_ID_FTM_RETRIES,			"ftm retries" },
+	{ WL_PROXD_TLV_ID_BSS_INDEX,			"BSS index" },
+	{ WL_PROXD_TLV_ID_BSSID,				"bssid" },
+	{ WL_PROXD_TLV_ID_INIT_DELAY,			"burst init delay" },
+	{ WL_PROXD_TLV_ID_BURST_TIMEOUT,		"burst timeout" },
+	{ WL_PROXD_TLV_ID_EVENT_MASK,			"event mask" },
+	{ WL_PROXD_TLV_ID_FLAGS_MASK,			"flags mask" },
+	{ WL_PROXD_TLV_ID_PEER_MAC,				"peer addr" },
+	{ WL_PROXD_TLV_ID_FTM_REQ,				"ftm req" },
+	{ WL_PROXD_TLV_ID_LCI_REQ,				"lci req" },
+	{ WL_PROXD_TLV_ID_LCI,					"lci" },
+	{ WL_PROXD_TLV_ID_CIVIC_REQ,			"civic req" },
+	{ WL_PROXD_TLV_ID_CIVIC,				"civic" },
+	{ WL_PROXD_TLV_ID_AVAIL24,				"availability" },
+	{ WL_PROXD_TLV_ID_SESSION_FLAGS,		"session flags" },
+	{ WL_PROXD_TLV_ID_SESSION_FLAGS_MASK,	"session flags mask" },
+	{ WL_PROXD_TLV_ID_RX_MAX_BURST,			"rx max bursts" },
+	{ WL_PROXD_TLV_ID_RANGING_INFO,			"ranging info" },
+	{ WL_PROXD_TLV_ID_RANGING_FLAGS,		"ranging flags" },
+	{ WL_PROXD_TLV_ID_RANGING_FLAGS_MASK,	"ranging flags mask" },
+	{ WL_PROXD_TLV_ID_NAN_MAP_ID,			"nan map id" },
+	{ WL_PROXD_TLV_ID_DEV_ADDR,				"dev addr" },
+	{ WL_PROXD_TLV_ID_AVAIL,				"availability" },
+	{ WL_PROXD_TLV_ID_FTM_REQ_RETRIES,		"ftm request retries" },
+	{ WL_PROXD_TLV_ID_TPK,					"FTM TPK" },
+
+	/* output - 512 + x */
+	{ WL_PROXD_TLV_ID_STATUS,				"status" },
+	{ WL_PROXD_TLV_ID_COUNTERS,				"counters" },
+	{ WL_PROXD_TLV_ID_INFO,					"info" },
+	{ WL_PROXD_TLV_ID_RTT_RESULT,			"rtt result" },
+	{ WL_PROXD_TLV_ID_AOA_RESULT,			"aoa result" },
+	{ WL_PROXD_TLV_ID_SESSION_INFO,			"session info" },
+	{ WL_PROXD_TLV_ID_SESSION_STATUS,		"session status" },
+	{ WL_PROXD_TLV_ID_SESSION_ID_LIST,		"session ids" },
+	/* debug tlvs can be added starting 1024 */
+	{ WL_PROXD_TLV_ID_DEBUG_MASK,			"debug mask" },
+	{ WL_PROXD_TLV_ID_COLLECT,				"collect" },
+	{ WL_PROXD_TLV_ID_STRBUF,				"result" }
+};
+
+/*
+* map a ftm TLV-id to a text-string for display as a 'heading'
+*/
+static const char *
+ftm_tlvid_to_logstr(uint16 tlvid)
+{
+	return ftm_map_id_to_str((int32) tlvid,
+		&ftm_tlvid_loginfo[0], ARRAYSIZE(ftm_tlvid_loginfo));
+}
+
+/*
+* The following string mapping tables are used for TLVs display received from 'get' commands
+*/
+/*
+* proximity detection method --> text string mapping
+*/
+static const ftm_strmap_entry_t ftm_method_value_loginfo[] = {
+	/* wl_proxd_method_t,		text-string */
+	{ WL_PROXD_METHOD_RSVD1,	"RSSI not supported" },
+	{ WL_PROXD_METHOD_TOF,		"11v+BCM proprietary" },
+	{ WL_PROXD_METHOD_RSVD2,	"11v only" },
+	{ WL_PROXD_METHOD_FTM,		"FTM" },		/* IEEE rev mc/2014 */
+	{ WL_PROXD_METHOD_NONE,		"none" }
+};
+static const char *
+ftm_method_value_to_logstr(wl_proxd_method_t method)
+{
+	return ftm_map_id_to_str((int32)method,
+		&ftm_method_value_loginfo[0], ARRAYSIZE(ftm_method_value_loginfo));
+}
+
+/*
+* time interval unit --> text string mapping
+*/
+static const ftm_strmap_entry_t ftm_tmu_value_loginfo[] = {
+	/* wl_proxd_tmu_t,			text-string */
+	{ WL_PROXD_TMU_TU,			"TU" },
+	{ WL_PROXD_TMU_SEC,			"sec" },
+	{ WL_PROXD_TMU_MILLI_SEC,	"ms" },
+	{ WL_PROXD_TMU_MICRO_SEC,	"us" },
+	{ WL_PROXD_TMU_NANO_SEC,	"ns" },
+	{ WL_PROXD_TMU_PICO_SEC,	"ps" }
+};
+
+static const char *
+ftm_tmu_value_to_logstr(wl_proxd_tmu_t tmu)
+{
+	return ftm_map_id_to_str((int32)tmu,
+		&ftm_tmu_value_loginfo[0], ARRAYSIZE(ftm_tmu_value_loginfo));
+}
+
+/*
+* proxd FTM method capabilities --> text string mapping
+*/
+static const ftm_strmap_entry_t ftm_caps_value_loginfo[] = {
+	/* wl_proxd_ftm_capts_t,	text-string */
+	{ WL_PROXD_FTM_CAP_FTM1,	"FTM" },
+	{ WL_PROXD_FTM_CAP_NONE,	"none" }
+};
+
+static const char *
+ftm_caps_value_to_logstr(wl_proxd_ftm_caps_t caps)
+{
+	return ftm_map_id_to_str((int32)caps,
+		&ftm_caps_value_loginfo[0], ARRAYSIZE(ftm_caps_value_loginfo));
+}
+
+/*
+* status --> text string mapping
+*/
+static const ftm_strmap_entry_t ftm_status_value_loginfo[] = {
+	/* wl_proxd_status_t,			text-string */
+	{ WL_PROXD_E_NOT_BCM,			"different vendor" },
+	{ WL_PROXD_E_FRAME_TYPE,		"invalid frame type" },
+	{ WL_PROXD_E_VERNOSUPPORT,		"unsupported version" },
+	{ WL_PROXD_E_SEC_NOKEY,			"no key" },
+	{ WL_PROXD_E_SEC_POLICY,		"security policy violation" },
+	{ WL_PROXD_E_SCAN_INPROCESS,		"scan in process" },
+	{ WL_PROXD_E_BAD_PARTIAL_TSF,		"bad partial TSF" },
+	{ WL_PROXD_E_SCANFAIL,			"scan failed" },
+	{ WL_PROXD_E_NOTSF,			"no TSF" },
+	{ WL_PROXD_E_POLICY,			"policy failed" },
+	{ WL_PROXD_E_INCOMPLETE,		"incomplete" },
+	{ WL_PROXD_E_OVERRIDDEN,		"overridden" },
+	{ WL_PROXD_E_ASAP_FAILED,		"ASAP failed" },
+	{ WL_PROXD_E_NOTSTARTED,		"not started" },
+	{ WL_PROXD_E_INVALIDMEAS,		"invalid measurement" },
+	{ WL_PROXD_E_INCAPABLE,		"incapable" },
+	{ WL_PROXD_E_MISMATCH,		"mismatch"},
+	{ WL_PROXD_E_DUP_SESSION,		"dup session" },
+	{ WL_PROXD_E_REMOTE_FAIL,		"remote fail" },
+	{ WL_PROXD_E_REMOTE_INCAPABLE,	"remote incapable" },
+	{ WL_PROXD_E_SCHED_FAIL,		"sched failure" },
+	{ WL_PROXD_E_PROTO,			"protocol error" },
+	{ WL_PROXD_E_EXPIRED,			"expired" },
+	{ WL_PROXD_E_TIMEOUT,			"timeout" },
+	{ WL_PROXD_E_NOACK,			"no ack" },
+	{ WL_PROXD_E_DEFERRED,		"deferred" },
+	{ WL_PROXD_E_INVALID_SID,		"invalid session id" },
+	{ WL_PROXD_E_REMOTE_CANCEL,		"remote cancel" },
+	{ WL_PROXD_E_CANCELED,		"canceled" },
+	{ WL_PROXD_E_INVALID_SESSION,	"invalid session" },
+	{ WL_PROXD_E_BAD_STATE,		"bad state" },
+	{ WL_PROXD_E_ERROR,			"error" },
+	{ WL_PROXD_E_OK,				"OK" }
+};
+
+/*
+* convert BCME_xxx error codes into related error strings
+* note, bcmerrorstr() defined in bcmutils is for BCMDRIVER only,
+*       this duplicate copy is for WL access and may need to clean up later
+*/
+static const char *ftm_bcmerrorstrtable[] = BCMERRSTRINGTABLE;
+static const char *
+ftm_status_value_to_logstr(wl_proxd_status_t status)
+{
+	static char ftm_msgbuf_status_undef[32];
+	const ftm_strmap_entry_t *p_loginfo;
+	int bcmerror;
+
+	/* check if within BCME_xxx error range */
+	bcmerror = (int) status;
+	if (VALID_BCMERROR(bcmerror))
+		return ftm_bcmerrorstrtable[-bcmerror];
+
+	/* otherwise, look for 'proxd ftm status' range */
+	p_loginfo = ftm_get_strmap_info((int32) status,
+		&ftm_status_value_loginfo[0], ARRAYSIZE(ftm_status_value_loginfo));
+	if (p_loginfo)
+		return p_loginfo->text;
+
+	/* report for 'out of range' FTM-status error code */
+	memset(ftm_msgbuf_status_undef, 0, sizeof(ftm_msgbuf_status_undef));
+	snprintf(ftm_msgbuf_status_undef, sizeof(ftm_msgbuf_status_undef),
+		"Undefined status %d", status);
+	return &ftm_msgbuf_status_undef[0];
+}
+
+/*
+* session-state --> text string mapping
+*/
+static const ftm_strmap_entry_t ftm_session_state_value_loginfo[] = {
+	/* wl_proxd_session_state_t,			text string */
+	{ WL_PROXD_SESSION_STATE_CREATED,		"created" },
+	{ WL_PROXD_SESSION_STATE_CONFIGURED,	"configured" },
+	{ WL_PROXD_SESSION_STATE_STARTED,		"started" },
+	{ WL_PROXD_SESSION_STATE_DELAY,			"delay" },
+	{ WL_PROXD_SESSION_STATE_USER_WAIT,		"user-wait" },
+	{ WL_PROXD_SESSION_STATE_SCHED_WAIT,	"sched-wait" },
+	{ WL_PROXD_SESSION_STATE_BURST,			"burst" },
+	{ WL_PROXD_SESSION_STATE_STOPPING,		"stopping" },
+	{ WL_PROXD_SESSION_STATE_ENDED,			"ended" },
+	{ WL_PROXD_SESSION_STATE_START_WAIT,	"start-wait" },
+	{ WL_PROXD_SESSION_STATE_DESTROYING,	"destroying" },
+	{ WL_PROXD_SESSION_STATE_NONE,			"none" }
+};
+
+static const char *
+ftm_session_state_value_to_logstr(wl_proxd_session_state_t state)
+{
+	return ftm_map_id_to_str((int32)state, &ftm_session_state_value_loginfo[0],
+		ARRAYSIZE(ftm_session_state_value_loginfo));
+}
+
+/*
+* ranging-state --> text string mapping
+*/
+static const ftm_strmap_entry_t ftm_ranging_state_value_loginfo [] = {
+	/* wl_proxd_ranging_state_t,			text string */
+		{ WL_PROXD_RANGING_STATE_NONE, "none" },
+		{ WL_PROXD_RANGING_STATE_NOTSTARTED, "nonstarted" },
+		{ WL_PROXD_RANGING_STATE_INPROGRESS, "inprogress" },
+		{ WL_PROXD_RANGING_STATE_DONE, "done" },
+};
+
+static const char *
+ftm_ranging_state_value_to_logstr(wl_proxd_ranging_state_t state)
+{
+	return ftm_map_id_to_str((int32) state, &ftm_ranging_state_value_loginfo[0],
+		ARRAYSIZE(ftm_ranging_state_value_loginfo));
+}
+
+/*
+* ranging-flags --> text string mapping
+*/
+static const ftm_strmap_entry_t ftm_ranging_flags_value_loginfo [] = {
+	/* wl_proxd_ranging_flags_t,			text string */
+	{ WL_PROXD_RANGING_FLAG_NONE, "none" },  /* no flags */
+	{ WL_PROXD_RANGING_FLAG_DEL_SESSIONS_ON_STOP, "del sessions on stop" },
+	{ WL_PROXD_RANGING_FLAG_ALL, "all" },
+};
+
+static const char *
+ftm_ranging_flags_value_to_logstr(wl_proxd_ranging_flags_t flags)
+{
+	return ftm_map_id_to_str((int32) flags, &ftm_ranging_flags_value_loginfo[0],
+		ARRAYSIZE(ftm_ranging_flags_value_loginfo));
+}
+
+/*
+* availability flag --> text string mapping
+*/
+static const ftm_strmap_entry_t ftm_avail_flags_value_loginfo [] = {
+	/* wl_proxd_avail_flags_t,			text string */
+	{ WL_PROXD_AVAIL_NONE, "none" },
+	{ WL_PROXD_AVAIL_NAN_PUBLISHED, "NAN published" },
+	{ WL_PROXD_AVAIL_SCHEDULED, "scheduled" }	/* scheduled by proxd */
+};
+
+static const char *
+ftm_avail_flags_value_to_logstr(wl_proxd_avail_flags_t flags)
+{
+	return ftm_map_id_to_str((int32) flags, &ftm_avail_flags_value_loginfo[0],
+			ARRAYSIZE(ftm_avail_flags_value_loginfo));
+}
+
+/*
+* availability time-ref --> text string mapping
+* (use for logging and cmd-line params parsing)
+*/
+static const ftm_strmap_entry_t ftm_avail_timeref_value_loginfo [] = {
+	/* wl_proxd_time_ref_t,			text string */
+	{ WL_PROXD_TREF_NONE, "none" },
+	{ WL_PROXD_TREF_DEV_TSF, "dev-tsf" },
+	{ WL_PROXD_TREF_NAN_DW, "nan-dw" },
+	{ WL_PROXD_TREF_TBTT, "tbtt" }
+};
+
+static const char *
+ftm_avail_timeref_value_to_logstr(wl_proxd_time_ref_t timeref)
+{
+	return ftm_map_id_to_str((int32) timeref, &ftm_avail_timeref_value_loginfo[0],
+			ARRAYSIZE(ftm_avail_timeref_value_loginfo));
+}
+
+/*
+* allocate a buffer for get/set 'proxd ftm' iovar
+*
+* Input:
+*       tlvs_bufsize: specify the max-size of all TLVs reserved for this buffer
+*       The following fields will be used for setting the proxd-method iovar header:
+*             method, session_id, cmdid
+*
+* if succeeds, this function allocates a buffer, setup proxd-method iovar header
+*              then returns the pointer to allocated buffer and the bufsize(in bytes)
+*              to caller. Note, the 'len' and a dummy-TLV will be set in the iovar header,
+*              caller may adjust the 'len' based on #of valid TLVs later.
+* if failed, return 'NULL' to indicate error (e.g. no memory).
+*/
+static wl_proxd_iov_t *
+ftm_alloc_getset_buf(wl_proxd_method_t method, wl_proxd_session_id_t session_id,
+	wl_proxd_cmd_t cmdid, uint16 tlvs_bufsize, uint16 *p_out_bufsize)
+{
+	uint16 proxd_iovsize;
+	wl_proxd_tlv_t *p_tlv;
+	wl_proxd_iov_t *p_proxd_iov = (wl_proxd_iov_t *) NULL;
+
+	*p_out_bufsize = 0;	/* init */
+
+	/* calculate the whole buffer size, including one reserve-tlv entry in the header */
+	proxd_iovsize = sizeof(wl_proxd_iov_t) + tlvs_bufsize;
+
+	p_proxd_iov = calloc(1, proxd_iovsize);
+	if (p_proxd_iov == NULL) {
+		printf("error: failed to allocate %d bytes of memory\n", proxd_iovsize);
+		return NULL;
+	}
+
+	/* setup proxd-FTM-method iovar header */
+	p_proxd_iov->version = htol16(WL_PROXD_API_VERSION);
+	p_proxd_iov->len = htol16(proxd_iovsize); /* caller may adjust it based on #of TLVs */
+	p_proxd_iov->cmd = htol16(cmdid);
+	p_proxd_iov->method = htol16(method);
+	p_proxd_iov->sid = htol16(session_id);
+
+	/* initialize the reserved/dummy-TLV in iovar header */
+	p_tlv = p_proxd_iov->tlvs;
+	p_tlv->id = htol16(WL_PROXD_TLV_ID_NONE);
+	p_tlv->len = htol16(0);
+
+	*p_out_bufsize = proxd_iovsize;	/* for caller's reference */
+
+	return p_proxd_iov;
+}
+
+/*
+* unpack and display rtt_result TLV
+*/
+
+#define PDFTM_BURST_STATE_NAMES \
+	{"INVALID", \
+	"FTM2/M1/RESPONSE", \
+	"FTM3/M2/LTFTRIGGER", \
+	"FTM4/M3/DONE", \
+	}
+
+#define FTM_FRAME_TYPES \
+	{"SETUP", "TRIGGER", "TIMESTAMP"}
+
+static void
+ftm_unpack_and_display_rtt_result(const uint8 *p_data, uint16 tlvid, uint16 len)
+{
+	int		i;
+	char	dispbuf[256];
+	char	*p_dest;
+	wl_proxd_rtt_result_t *p_data_info;
+	wl_proxd_result_flags_t flags;
+	wl_proxd_session_state_t session_state;
+	int32 avg_dist;
+	wl_proxd_rtt_sample_t	*p_sample;
+	uint16 num_rtt;
+	char* pstatestr[] = PDFTM_BURST_STATE_NAMES;
+	char *ftm_frame_types[] =  FTM_FRAME_TYPES;
+
+	UNUSED_PARAMETER(len);
+
+	p_data_info = (wl_proxd_rtt_result_t *) p_data;
+
+	/* unpack and format 'flags' for display */
+	flags = ltoh16_ua(&p_data_info->flags);
+	memset(dispbuf, 0, sizeof(dispbuf));
+	p_dest = &dispbuf[0];
+	if (flags & WL_PROXD_RESULT_FLAG_NLOS) {
+		strncpy(p_dest, "NLOS", sizeof(dispbuf) - strlen(dispbuf) - 1);
+		p_dest = &dispbuf[strlen(dispbuf)];
+	}
+	if (flags & WL_PROXD_RESULT_FLAG_LOS)
+		strncpy(p_dest, " LOS", sizeof(dispbuf) - strlen(dispbuf) - 1);
+	if (flags & WL_PROXD_RESULT_FLAG_FATAL)
+		strncpy(p_dest, " Fatal error", sizeof(dispbuf) - strlen(dispbuf) - 1);
+
+	printf("> %s:\n>\tsessionId=%d, flags=0x%04x('%s'), peer=%s\n",
+		ftm_tlvid_to_logstr(tlvid),
+		ltoh16_ua(&p_data_info->sid),
+		flags,
+		dispbuf,								/* flags */
+		wl_ether_etoa(&p_data_info->peer));
+
+	/* session state and status */
+	session_state = ltoh16_ua(&p_data_info->state);
+	printf(">\tsession state=%d(%s)",
+		session_state, ftm_session_state_value_to_logstr(session_state));
+
+	printf(">\tburst_duration: %d%s\n",
+		ltoh32_ua(&p_data_info->u.burst_duration.intvl),
+		ftm_tmu_value_to_logstr(ltoh16_ua(&p_data_info->u.burst_duration.tmu)));
+
+	/* show avg_dist (1/256m units), burst_num */
+	avg_dist = ltoh32_ua(&p_data_info->avg_dist);
+	if ((uint32)avg_dist == 0xffffffff) {	/* report 'failure' case */
+		printf(">\tavg_dist=-1m, burst_num=%d, valid_measure_cnt=%d num_ftm=%d\n",
+		ltoh16_ua(&p_data_info->burst_num),
+		p_data_info->num_valid_rtt, p_data_info->num_ftm); /* in a session */
+	}
+	else {
+		printf(">\tavg_dist=%d.%04dm, burst_num=%d, valid_measure_cnt=%d num_ftm=%d\n",
+			avg_dist >> 8, /* 1/256m units */
+			((avg_dist & 0xff) * 625) >> 4,
+			ltoh16_ua(&p_data_info->burst_num),
+			p_data_info->num_valid_rtt, p_data_info->num_ftm); /* in a session */
+	}
+
+	/* show 'avg_rtt' sample */
+	p_sample = &p_data_info->avg_rtt;
+	printf(">\tavg_rtt sample: rssi=%d snr=%d bitflips=%d rtt=%d%s "
+		"std_deviation =%d.%d ratespec=0x%08x\n",
+		(wl_proxd_rssi_t) ltoh16_ua(&p_sample->rssi),
+		(wl_proxd_snr_t) ltoh16_ua(&p_sample->snr),
+		(wl_proxd_bitflips_t) ltoh16_ua(&p_sample->bitflips),
+		ltoh32_ua(&p_sample->rtt.intvl),
+		ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample->rtt.tmu)),
+		ltoh16_ua(&p_data_info->sd_rtt)/10, ltoh16_ua(&p_data_info->sd_rtt)%10,
+		ltoh32_ua(&p_sample->ratespec));
+
+	printf(">\tnum_measurements: %d ", p_data_info->num_meas);
+	printf(" Flags:");
+	if (p_data_info->flags & WL_PROXD_REQUEST_SENT) {
+		if (p_data_info->flags & WL_PROXD_REQUEST_ACKED) {
+			if (p_data_info->num_meas)
+				printf("(%s)", pstatestr[p_data_info->num_meas]);
+			else
+				printf("(FTM1/REQSENT/ACKED)");
+		} else {
+			printf("(FTM1/REQSENT/NOACK)");
+		}
+	} else {
+		printf("(NO_REQ_SENT)");
+	}
+	printf("(LTFSEQ %sSTARTED)\n", (p_data_info->flags & WL_PROXD_LTFSEQ_STARTED)? "":"not ");
+
+	/* display detail if available */
+	num_rtt = ltoh16_ua(&p_data_info->num_rtt);
+	if (num_rtt > 0)
+	{
+		printf(">\tnum rtt: %d samples\n", num_rtt);
+		p_sample = &p_data_info->rtt[0];
+		for (i = 0; i < num_rtt; i++)
+		{
+			uint16 snr = 0, bitflips = 0;
+			int16 rssi = 0;
+			int32 dist = 0;
+			/* FTM frames 1,4,7,11 have valid snr, rssi and bitflips */
+			if ((i%TOF_DEFAULT_FTMCNT_SEQ) == 1) {
+				rssi = (wl_proxd_rssi_t) ltoh16_ua(&p_sample->rssi);
+				snr = (wl_proxd_snr_t) ltoh16_ua(&p_sample->snr);
+				bitflips = (wl_proxd_bitflips_t) ltoh16_ua(&p_sample->bitflips);
+				dist = ltoh32_ua(&p_sample->distance);
+			} else {
+				rssi = -1;
+				snr = 0;
+				bitflips = 0;
+				dist = 0;
+			}
+			printf(">\t sample[%d]: id=%d rssi=%d snr=%d bitflips=%d "
+				"dist=%d rtt=%d%s status %s Type %s coreid=%d\n",
+				i, p_sample->id, rssi, snr, bitflips, dist,
+				ltoh32_ua(&p_sample->rtt.intvl),
+				ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample->rtt.tmu)),
+				ftm_status_value_to_logstr(ltoh32_ua(&p_sample->status)),
+				ftm_frame_types[i % TOF_DEFAULT_FTMCNT_SEQ], p_sample->coreid);
+				p_sample++;
+		}
+	}
+	return;
+}
+
+/*
+* unpack and display session_info TLV (WL_PROXD_TLV_ID_SESSION_INFO)
+*/
+static void
+ftm_unpack_and_display_session_info(const uint8 *p_data, uint16 tlvid, uint16 len)
+{
+	wl_proxd_ftm_session_info_t *p_data_info;
+	wl_proxd_session_state_t session_state;
+	wl_proxd_status_t proxd_status;
+
+	UNUSED_PARAMETER(len);
+
+	p_data_info = (wl_proxd_ftm_session_info_t *) p_data;
+
+	printf("> %s: bssidx=%d, bssid=%s\n",
+		ftm_tlvid_to_logstr(tlvid),
+		p_data_info->bss_index,
+		wl_ether_etoa(&p_data_info->bssid));
+
+	session_state = ltoh16_ua(&p_data_info->state);
+	proxd_status = ltoh32_ua(&p_data_info->status);
+
+	printf("\tsessionId=%d, state=%d(%s), status=%d(%s), burst_num=%d, "
+		"meas_start %u.%u\n",
+		ltoh16_ua(&p_data_info->sid),
+		session_state,
+		ftm_session_state_value_to_logstr(session_state),
+		proxd_status,
+		ftm_status_value_to_logstr(proxd_status),
+		ltoh16_ua(&p_data_info->burst_num),
+		ltoh32_ua(&p_data_info->meas_start_hi), ltoh32_ua(&p_data_info->meas_start_lo));
+
+	return;
+}
+
+/*
+* unpack and display session status TLV (WL_PROXD_TLV_ID_SESSION_STATUS)
+*/
+static void
+ftm_unpack_and_display_session_status(const uint8 *p_data, uint16 tlvid, uint16 len)
+{
+	wl_proxd_ftm_session_status_t *p_data_info;
+	wl_proxd_session_state_t session_state;
+	wl_proxd_status_t proxd_status;
+
+	UNUSED_PARAMETER(len);
+
+	p_data_info = (wl_proxd_ftm_session_status_t *) p_data;
+	session_state = ltoh16_ua(&p_data_info->state);
+	proxd_status = ltoh32_ua(&p_data_info->status);
+	printf("> %s: sessionId=%d, state=%d(%s), status=%d(%s), burst_num=%d\n",
+		ftm_tlvid_to_logstr(tlvid),
+		ltoh16_ua(&p_data_info->sid),
+		session_state,
+		ftm_session_state_value_to_logstr(session_state),
+		proxd_status,
+		ftm_status_value_to_logstr(proxd_status),
+		ltoh16_ua(&p_data_info->burst_num));
+
+	return;
+}
+
+/*
+* unpack and display session_id lists TLV (WL_PROXD_TLV_ID_COUNTERS)
+*/
+static void
+ftm_unpack_and_display_counters(const uint8 *p_data, uint16 tlvid, uint16 len)
+{
+	wl_proxd_counters_t *p_data_info;
+
+	UNUSED_PARAMETER(len);
+
+	p_data_info = (wl_proxd_counters_t *) p_data;
+	printf("> %s:\n\ttx-frame-count=%d, rx-frame_count=%d\n",
+		ftm_tlvid_to_logstr(tlvid),
+		ltoh32_ua(&p_data_info->tx),			/* tx frame count */
+		ltoh32_ua(&p_data_info->rx));			/* rx frame count */
+
+	printf("\tnoack=%d, txfail=%d num_meas=%d\n",
+		ltoh32_ua(&p_data_info->noack), 		/* tx w/o ack */
+		ltoh32_ua(&p_data_info->txfail),		/* tx failures */
+		ltoh32_ua(&p_data_info->num_meas));		/* tx failures */
+
+	printf("\tburst=%d, sessions=%d, max_sessions=%d\n",
+		ltoh32_ua(&p_data_info->burst),			/* # of burst */
+		ltoh32_ua(&p_data_info->sessions),		/* # of sessions */
+		ltoh32_ua(&p_data_info->max_sessions));	/* max concurrency */
+
+	printf("\tsched_fail=%d, timeouts=%d, protocol errors=%d\n",
+		ltoh32_ua(&p_data_info->sched_fail), /* scheduling failures */
+		ltoh32_ua(&p_data_info->timeouts),	/* timeouts */
+		ltoh32_ua(&p_data_info->protoerr));	/* protocol err */
+
+	printf("\tLCI: tx request=%d, rx request=%d, tx report=%d, rx report=%d\n",
+		ltoh32_ua(&p_data_info->lci_req_tx), /*  tx LCI requests */
+		ltoh32_ua(&p_data_info->lci_req_rx), /*  rx LCI requests */
+		ltoh32_ua(&p_data_info->lci_rep_tx), /*  tx LCI reports */
+		ltoh32_ua(&p_data_info->lci_rep_rx)); /*  rx LCI reports */
+
+	printf("\tcivic: tx request=%d, rx request=%d, tx report=%d, "
+		"rx report=%d\n",
+		ltoh32_ua(&p_data_info->civic_req_tx), /* tx civic requests */
+		ltoh32_ua(&p_data_info->civic_req_rx), /* rx civic requests */
+		ltoh32_ua(&p_data_info->civic_rep_tx), /* tx civic reports */
+		ltoh32_ua(&p_data_info->civic_rep_rx)); /* rx civic reports */
+
+	printf("\tranging: created=%d, done=%d\n",
+		ltoh32_ua(&p_data_info->rctx), ltoh32_ua(&p_data_info->rctx_done));
+
+	printf("\tpublish errors=%d\n", ltoh32_ua(&p_data_info->publish_err));
+	printf("\tsched on_chan=%d off_chan=%d\n", ltoh32_ua(&p_data_info->on_chan),
+		ltoh32_ua(&p_data_info->off_chan));
+	printf("\ttsf %u.%u\n",
+		ltoh32_ua(&p_data_info->tsf_hi),
+		ltoh32_ua(&p_data_info->tsf_lo));
+	return;
+}
+
+/*
+* unpack and display session_id lists TLV (WL_PROXD_TLV_ID_SESSION_ID_LIST)
+*/
+static void
+ftm_unpack_and_display_session_idlist(const uint8 *p_data, uint16 tlvid, uint16 len)
+{
+	wl_proxd_session_id_list_t *p_data_info;
+	int i;
+	uint16 num_ids;
+
+	UNUSED_PARAMETER(len);
+
+	p_data_info = (wl_proxd_session_id_list_t *) p_data;
+	num_ids = ltoh16_ua(&p_data_info->num_ids);
+	printf("> %s: total %d id(s)\n", ftm_tlvid_to_logstr(tlvid), num_ids);
+
+	for (i = 0; i < num_ids; i++) {
+		printf(">\tsession[%d]: %d\n", i, ltoh16_ua(&p_data_info->ids[i]));
+	}
+
+	return;
+}
+
+/*
+* unpack and display availability TLV
+*/
+static void
+ftm_unpack_and_display_avail(const uint8 *p_data, uint16 tlvid, uint16 len)
+{
+	wl_proxd_avail_t		*avail;
+	wl_proxd_avail24_t		*avail24;
+	wl_proxd_avail_t		l_avail;
+	wl_proxd_avail_flags_t 	flags;
+	wl_proxd_time_ref_t 	time_ref;
+	uint16					num_slots;
+	wl_proxd_time_slot_t	*avail_slot;
+	chanspec_t				chanspec;
+	int						i;
+	char					dispbuf[256];
+
+	UNUSED_PARAMETER(len);
+
+	/* unpack and format the avail-header for display */
+	if (tlvid == WL_PROXD_TLV_ID_AVAIL24) {
+		avail24 = (wl_proxd_avail24_t *) p_data;
+		/* convert the old version */
+		l_avail.flags = avail24->flags;
+		l_avail.time_ref = avail24->time_ref;
+		l_avail.num_slots = avail24->num_slots;
+		l_avail.max_slots = avail24->max_slots;
+		l_avail.repeat = avail24->repeat;
+		avail = &l_avail;
+
+		avail_slot = &avail24->ts0[0];
+	}
+	else { /* WL_PROXD_TLV_ID_AVAIL */
+		avail = (wl_proxd_avail_t *) p_data;
+		avail_slot = WL_PROXD_AVAIL_TIMESLOTS(avail);
+	}
+
+	flags = ltoh16_ua(&avail->flags);
+	time_ref = ltoh16_ua(&avail->time_ref);
+	num_slots = ltoh16_ua(&avail->num_slots);
+
+	printf("> %s:\n>\tflags=0x%04x('%s'), time-ref=0x%04x('%s'), "
+		"period=%d%s, num_slots=%d, max_slots=%d\n",
+		ftm_tlvid_to_logstr(tlvid),
+		flags, ftm_avail_flags_value_to_logstr(flags),
+		time_ref, ftm_avail_timeref_value_to_logstr(time_ref),
+		ltoh32_ua(&avail->repeat.intvl),
+		ftm_tmu_value_to_logstr(ltoh16_ua(&avail->repeat.tmu)),
+		num_slots, ltoh16_ua(&avail->max_slots));
+
+	/* unpack and format the time slots for display */
+	for (i = 0; i < num_slots; i++) {
+		printf(">\tslots[%d]: start: %d%s duration: %d%s",
+			i, ltoh32_ua(&avail_slot->start.intvl),
+			ftm_tmu_value_to_logstr(ltoh16_ua(&avail_slot->start.tmu)),
+			ltoh32_ua(&avail_slot->duration.intvl),
+			ftm_tmu_value_to_logstr(ltoh16_ua(&avail_slot->duration.tmu)));
+
+		chanspec = (chanspec_t) ltoh32_ua(&avail_slot->chanspec);
+		if (wf_chspec_valid(chanspec)) {
+			memset(dispbuf, 0, sizeof(dispbuf));
+			wf_chspec_ntoa(chanspec, dispbuf);
+			printf(" chanspec: 0x%04x(%s)\n", chanspec, dispbuf);
+		}
+		else {
+			printf(" chanspec: 0x%04x(invalid)\n", chanspec);
+		}
+		avail_slot++;
+	}
+}
+
+/*
+* unpack and display session_info TLV (WL_PROXD_TLV_ID_RANGING_INFO)
+*/
+static void
+ftm_unpack_and_display_ranging_info(const uint8 *p_data, uint16 tlvid, uint16 len)
+{
+	wl_proxd_ranging_info_t *p_data_info;
+	wl_proxd_status_t proxd_status;
+	wl_proxd_ranging_state_t	state;
+	wl_proxd_ranging_flags_t	flags;
+
+	UNUSED_PARAMETER(len);
+
+	p_data_info = (wl_proxd_ranging_info_t *) p_data;
+
+	printf("> %s:\n", ftm_tlvid_to_logstr(tlvid));
+
+	proxd_status = ltoh32_ua(&p_data_info->status);
+	state = ltoh16_ua(&p_data_info->state);
+	flags = ltoh16_ua(&p_data_info->flags);
+
+	printf("\tstatus=%d(%s), state=%d(%s), flags=0x%04x(%s), num_sids=%d, num_done=%d\n",
+		proxd_status,
+		ftm_status_value_to_logstr(proxd_status),
+		state,
+		ftm_ranging_state_value_to_logstr(state),
+		flags,
+		ftm_ranging_flags_value_to_logstr(flags),
+		ltoh16_ua(&p_data_info->num_sids),
+		ltoh16_ua(&p_data_info->num_done));
+
+	return;
+}
+
+/*
+ * a callback function, displays (wl_proxd_tlv_t) bcm_xtlv variables rcvd in
+ * get ioctl's xtlv buffer.
+ *  -- This function processes GET result for all 'proxd ftm' commands, provided
+ *     that XTLV types (AKA the explicit xtlv types) packed into the ioctl buff
+ *     are unique across all 'proxd ftm' ioctl commands
+ * -- This function is also used to display rx FTM events (content in XTLVs),
+ *    see ftm_event_check().
+ */
+static int
+ftm_unpack_xtlv_cbfn(void *ctx, const uint8 *p_data, uint16 tlvid, uint16 len)
+{
+	int res = BCME_OK;
+	char dispbuf[256];
+	wl_proxd_event_type_t event_data;
+	char event_dispbuf[256];
+	chanspec_t chanspec;
+	wl_proxd_intvl_t *p_data_intvl;
+	wl_proxd_ftm_info_t *p_data_info;
+	wl_proxd_tpk_t *tpk_info;
+
+
+#ifdef WL_FTM_DEBUG
+	/* for 'get' commands :
+			wl_proxd_iov_t *p_proxd_iov = (wl_proxd_iov_t *) ctx;
+	   for event_check:
+			ctx is NULL
+	*/
+	printf("enter %s(ctx=%p, data=%p, tlvid=%d, len=%d)...\n",
+		__FUNCTION__, ctx, p_data, tlvid, len);
+#else
+	UNUSED_PARAMETER(ctx);
+#endif /* WL_FTM_DEBUG */
+
+	memset(dispbuf, 0, sizeof(dispbuf));	/* clear the buffer for display */
+
+	switch (tlvid) {
+		/* data=uint8 as a number, display in decimal */
+		case WL_PROXD_TLV_ID_BSS_INDEX:
+		case WL_PROXD_TLV_ID_FTM_RETRIES:	/* at FTM level */
+		case WL_PROXD_TLV_ID_FTM_REQ_RETRIES:
+			printf("> %s: %d\n", ftm_tlvid_to_logstr(tlvid), *p_data);
+		break;
+
+		/* data=uint16 as a number, display in decimal */
+		case WL_PROXD_TLV_ID_BURST_NUM_FTM:	/* per burst */
+		case WL_PROXD_TLV_ID_NUM_BURST:
+		case WL_PROXD_TLV_ID_RX_MAX_BURST:
+			printf("> %s: %d\n", ftm_tlvid_to_logstr(tlvid), ltoh16_ua(p_data));
+		break;
+
+		/* data=uin32 as a number, display in decimal */
+		case WL_PROXD_TLV_ID_NONE:
+		case WL_PROXD_TLV_ID_TX_POWER:
+		case WL_PROXD_TLV_ID_STATUS:			/* not used ? SJL_FIXME */
+		case WL_PROXD_TLV_ID_NAN_MAP_ID:
+			printf("> %s: %d\n", ftm_tlvid_to_logstr(tlvid), ltoh32_ua(p_data));
+		break;
+
+		/* data=uint32 as a number, display in hex */
+		case WL_PROXD_TLV_ID_RATESPEC:
+		case WL_PROXD_TLV_ID_DEBUG_MASK:
+		case WL_PROXD_TLV_ID_RANGING_FLAGS:
+		case WL_PROXD_TLV_ID_RANGING_FLAGS_MASK:
+			printf("> %s: 0x%x\n", ftm_tlvid_to_logstr(tlvid), ltoh32_ua(p_data));
+		break;
+
+		/* data=uint32 as a number, display in hex */
+		case WL_PROXD_TLV_ID_FLAGS:
+		case WL_PROXD_TLV_ID_FLAGS_MASK:
+			ftm_unpack_and_display_config_flags(p_data, tlvid);
+		break;
+
+		/* data=uint32 as a number, display in hex */
+		case WL_PROXD_TLV_ID_SESSION_FLAGS:
+		case WL_PROXD_TLV_ID_SESSION_FLAGS_MASK:
+			ftm_unpack_and_display_session_flags(p_data, tlvid);
+			break;
+
+		/* data=uint32 as a number, display in hex */
+		case WL_PROXD_TLV_ID_EVENT_MASK:
+		{
+			event_data = ltoh32_ua(p_data);
+			event_dispbuf[0] = '\0';
+#ifdef WL_FTM_DEBUG
+			/* convert to a readable text-string */
+			ftm_format_event_mask(event_data, event_dispbuf, sizeof(event_dispbuf));
+#endif /* WL_FTM_DEBUG */
+			printf("> %s: 0x%x %s\n",
+				ftm_tlvid_to_logstr(tlvid), event_data, event_dispbuf);
+		}
+		break;
+
+		/* data=uin32 as a number, convert and display a text-string */
+		case WL_PROXD_TLV_ID_METHOD:
+			printf("> %s: %s\n", ftm_tlvid_to_logstr(tlvid),
+				ftm_method_value_to_logstr((wl_proxd_method_t) ltoh32_ua(p_data)));
+		break;
+
+		/* data=uint32 as a chanspec */
+		case WL_PROXD_TLV_ID_CHANSPEC:
+		{
+			chanspec = (chanspec_t) ltoh32_ua(p_data);
+			if (wf_chspec_valid(chanspec)) {
+				wf_chspec_ntoa(chanspec, dispbuf);
+				printf("> %s: %s 0x%04x\n",
+					ftm_tlvid_to_logstr(tlvid), dispbuf, chanspec);
+			} else {
+				printf("> %s: invalid 0x%04x\n",
+					ftm_tlvid_to_logstr(tlvid), chanspec);
+			}
+		}
+		break;
+
+		/* data=intvl */
+		case WL_PROXD_TLV_ID_BURST_DURATION:
+		case WL_PROXD_TLV_ID_BURST_PERIOD:
+		case WL_PROXD_TLV_ID_BURST_FTM_SEP:
+		case WL_PROXD_TLV_ID_INIT_DELAY:
+		case WL_PROXD_TLV_ID_BURST_TIMEOUT:
+		{
+			p_data_intvl = (wl_proxd_intvl_t *) p_data;
+			printf("> %s: %d%s\n", ftm_tlvid_to_logstr(tlvid),
+				ltoh32_ua(&p_data_intvl->intvl),
+				ftm_tmu_value_to_logstr(ltoh16_ua(&p_data_intvl->tmu)));
+		}
+		break;
+
+		case WL_PROXD_TLV_ID_BSSID:
+		case WL_PROXD_TLV_ID_PEER_MAC:
+		case WL_PROXD_TLV_ID_DEV_ADDR:
+			printf("> %s: %s\n", ftm_tlvid_to_logstr(tlvid),
+				wl_ether_etoa((struct ether_addr *)p_data));
+		break;
+
+		case WL_PROXD_TLV_ID_TPK:
+		{
+			tpk_info = (wl_proxd_tpk_t *)p_data;
+			printf("> %s: mac addr%s \n", ftm_tlvid_to_logstr(tlvid),
+				wl_ether_etoa((struct ether_addr *)&tpk_info->peer));
+		}
+		break;
+
+		case WL_PROXD_TLV_ID_INFO:			/* data=wl_proxd_ftm_info_t */
+		{
+			p_data_info = (wl_proxd_ftm_info_t *) p_data;
+			printf("> %s: capabilities=%s, max sessions=%d, num sessions=%d,"
+				"rx_max_burst=%d\n",
+				ftm_tlvid_to_logstr(tlvid),
+				ftm_caps_value_to_logstr(ltoh16_ua(&p_data_info->caps)),
+				ltoh16_ua(&p_data_info->max_sessions),
+				ltoh16_ua(&p_data_info->num_sessions),
+				ltoh16_ua(&p_data_info->rx_max_burst));
+		}
+		break;
+
+		case WL_PROXD_TLV_ID_FTM_REQ:		/* data=dot11_ftm_req_t, var-len */
+			printf("> %s: data-len=%d byte(s)\n",
+				ftm_tlvid_to_logstr(tlvid), len);
+			if (len > 0)
+				prhex(NULL, (uint8 *)p_data, len);
+		break;
+
+		case WL_PROXD_TLV_ID_RTT_RESULT:	/* data=wl_proxd_rtt_result_t */
+			ftm_unpack_and_display_rtt_result(p_data, tlvid, len);
+		break;
+
+		case WL_PROXD_TLV_ID_SESSION_INFO:	/* data=wl_proxd_ftm_session_info_t */
+			ftm_unpack_and_display_session_info(p_data, tlvid, len);
+		break;
+
+		case WL_PROXD_TLV_ID_SESSION_STATUS:	/* data=wl_proxd_ftm_session_status_t */
+			ftm_unpack_and_display_session_status(p_data, tlvid, len);
+		break;
+
+		case WL_PROXD_TLV_ID_COUNTERS:			/* data=wl_proxd_counters_t */
+			ftm_unpack_and_display_counters(p_data, tlvid, len);
+		break;
+
+		case WL_PROXD_TLV_ID_SESSION_ID_LIST:	/* data=wl_proxd_session_id_list */
+			ftm_unpack_and_display_session_idlist(p_data, tlvid, len);
+		break;
+
+		case WL_PROXD_TLV_ID_RANGING_INFO:	/* data=wl_proxd_ranging_info_t */
+			ftm_unpack_and_display_ranging_info(p_data, tlvid, len);
+		break;
+
+		case WL_PROXD_TLV_ID_STRBUF:
+			if (len > 0)
+				printf("> %s:\n%s\n", ftm_tlvid_to_logstr(tlvid), p_data);
+		break;
+
+		case WL_PROXD_TLV_ID_AVAIL24:
+		case WL_PROXD_TLV_ID_AVAIL:
+			ftm_unpack_and_display_avail(p_data, tlvid, len);
+		break;
+
+		case WL_PROXD_TLV_ID_LCI:
+		case WL_PROXD_TLV_ID_CIVIC:
+			printf("> %s: data-len=%d byte(s)\n",
+				ftm_tlvid_to_logstr(tlvid), len);
+			if (len > 0)
+				prhex(NULL, (uint8*)p_data, len);
+		break;
+		case WL_PROXD_TLV_ID_TUNE:
+			res = proxd_tune_display((wl_proxd_params_tof_tune_t *)p_data, len);
+		break;
+		case WL_PROXD_TLV_ID_AOA_RESULT:	/* SJL_FIXME */
+		case WL_PROXD_TLV_ID_COLLECT:		/* SJL_FIXME */
+		case WL_PROXD_TLV_ID_LCI_REQ:		/* SJL_FIXME */
+		case WL_PROXD_TLV_ID_CIVIC_REQ:	/* SJL_FIXME */
+			/* fall thru (not used/supported now) */
+		default:
+			printf("> Unsupported %s: %d\n", ftm_tlvid_to_logstr(tlvid), tlvid);
+			res = BCME_ERROR;
+		break;
+	}
+
+	return res;
+}
+
+/* pack TLVs for checking if a specific tlv-id is supported or not
+* for WL_PROXD_CMD_IS_TLV_SUPPORTED
+*/
+static int
+ftm_pack_tlv_id_support(uint8 *buf, uint16 bufsize, void *ctx, uint16 *all_tlvsize)
+{
+	int err = BCME_OK;
+	uint16	buf_space_left;
+	uint16	tlv_id;
+	wl_proxd_tlv_t *p_tlv = (wl_proxd_tlv_t *) buf;
+
+	*all_tlvsize = 0;
+
+	if (!ctx)
+		return BCME_BADARG;
+
+	/* TLV buffer starts with a full size, will decrement for each packed TLV */
+	buf_space_left = bufsize;
+
+	tlv_id = htol16(*((uint16 *) ctx));
+	err = bcm_pack_xtlv_entry((uint8 **) &p_tlv, &buf_space_left,
+		WL_PROXD_TLV_ID_TLV_ID, sizeof(uint16), (void *) &tlv_id,
+		BCM_XTLV_OPTION_ALIGN32);
+	if (err != BCME_OK) {
+		printf("%s: failed to pack TLVs, err=%d\n",
+			__FUNCTION__, err);
+		goto done;
+	}
+
+	/* return the len to include all TLVs(including TLV header) */
+	*all_tlvsize = (bufsize - buf_space_left);
+
+done:
+	return err;
+}
+
+/*
+* check if a tlv-id is supported:
+* return BCME_OK if tlv-id is supported
+*/
+static int
+ftm_is_tlv_id_supported(void *wl, uint16 tlv_id)
+{
+	int 			err;
+	wl_proxd_iov_t	*p_proxd_iov;
+	uint16 			proxd_iovsize;
+	uint16 			all_tlvsize = 0;
+	wl_proxd_iov_t *p_iovresp = NULL;
+
+	/*  alloc mem for ioctl header + reserved bufsize for tlvs (initialize to zero) */
+	p_proxd_iov = ftm_alloc_getset_buf(WL_PROXD_METHOD_FTM,
+		WL_PROXD_SESSION_ID_GLOBAL, WL_PROXD_CMD_IS_TLV_SUPPORTED,
+		FTM_IOC_BUFSZ, &proxd_iovsize);
+	if (p_proxd_iov == NULL) {
+		err = BCME_NOMEM;
+		goto done;
+	}
+
+	/* Setup TLVs -- pack a TLV_ID for support checking */
+	err = ftm_pack_tlv_id_support((uint8 *) &p_proxd_iov->tlvs[0],
+		proxd_iovsize - WL_PROXD_IOV_HDR_SIZE,
+		(void *) &tlv_id, &all_tlvsize);
+	if (err != BCME_OK)
+		goto done;
+
+	/* update the iov header, set len to include all TLVs + header */
+	proxd_iovsize = all_tlvsize + WL_PROXD_IOV_HDR_SIZE;
+	p_proxd_iov->len = htol16(proxd_iovsize);
+
+	/* submit a 'get' request to see if the tlv-id is supported or not */
+	err = wlu_var_getbuf(wl, "proxd", p_proxd_iov, proxd_iovsize, (void *) &p_iovresp);
+
+done:
+	/* clean up */
+	free(p_proxd_iov);
+
+	return err;
+
+}
+
+/*
+* send 'proxd' iovar for all ftm get-related commands
+*/
+static int
+ftm_do_get_ioctl(void *wl, wl_proxd_iov_t *p_proxd_iov, uint16 proxd_iovsize,
+	const ftm_subcmd_info_t *p_subcmd_info)
+{
+
+	/* for gets we only need to pass ioc header */
+	wl_proxd_iov_t *p_iovresp = NULL;
+	int status;
+
+	/*  send getbuf proxd iovar */
+	status = wlu_var_getbuf(wl, "proxd", p_proxd_iov, proxd_iovsize, (void *)&p_iovresp);
+	if (status != BCME_OK) {
+#ifdef WL_FTM_DEBUG
+		printf("%s: failed to send getbuf proxd iovar, status=%d\n",
+			__FUNCTION__, status);
+#endif /* WL_FTM_DEBUG */
+		return status;
+	}
+
+	if (p_iovresp != NULL) {
+		int tlvs_len = ltoh16(p_iovresp->len) - WL_PROXD_IOV_HDR_SIZE;
+		if (tlvs_len < 0)
+		{
+#ifdef WL_FTM_DEBUG
+			printf("%s: alert, p_iovresp->len(%d) should not be smaller than %d\n",
+				__FUNCTION__, ltoh16(p_iovresp->len), (int) WL_PROXD_IOV_HDR_SIZE);
+#endif /* WL_FTM_DEBUG */
+			tlvs_len = 0;
+		}
+
+		if (p_subcmd_info->cmdid == WL_PROXD_CMD_GET_VERSION) /* 'wl proxd ftm version' */
+			printf("> version: 0x%x\n", ltoh16(p_iovresp->version));
+
+#ifdef WL_FTM_DEBUG
+		printf("%s: p_iovresp->(tlvs=%p,len=%d), tlvs_len=%d, cmdid=%d(%s) ver=0x%x\n",
+			__FUNCTION__, p_iovresp->tlvs, ltoh16(p_iovresp->len), tlvs_len,
+			ltoh16(p_iovresp->cmd), ftm_cmdid_to_str(ltoh16(p_iovresp->cmd)),
+			ltoh16(p_iovresp->version));
+#endif /* WL_FTM_DEBUG */
+
+		if (tlvs_len > 0)
+		{
+			/* unpack TLVs and invokes the cbfn for processing */
+			status = bcm_unpack_xtlv_buf(p_proxd_iov, (uint8 *)p_iovresp->tlvs,
+				tlvs_len, BCM_XTLV_OPTION_ALIGN32, ftm_unpack_xtlv_cbfn);
+			printf("\n");
+		}
+	}
+
+	return status;
+}
+
+/*
+* common handler for all get-related proxd method commands (no TLVs params for these commands)
+*   wl proxd ftm [session-id] <get-subcmd>
+*      where <get-subcmd> can be "ver", "result", "info", "status",
+*                              "sessions", "counters", "dump"
+* Note, this <get-subcmd> does not accept any parameters (i.e. no <param-name><param-value>)
+*/
+static int
+ftm_common_getcmd_handler(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	int status = BCME_OK;
+	uint16 proxd_iovsize = 0;
+
+#ifdef WL_FTM_DEBUG
+	printf("enter %s: method=%d, session_id=%d, cmdid=%d(%s)\n",
+		__FUNCTION__, method, session_id, p_subcmd_info->cmdid,
+		ftm_cmdid_to_str(p_subcmd_info->cmdid));
+#endif /* WL_FTM_DEBUG */
+
+	/*  alloc mem for ioctl headr + reserved 0 bufsize for tlvs (initialize to zero) */
+	wl_proxd_iov_t *p_proxd_iov;
+	p_proxd_iov = ftm_alloc_getset_buf(method, session_id, p_subcmd_info->cmdid,
+		0, &proxd_iovsize);
+	if (p_proxd_iov == NULL)
+		return BCME_NOMEM;
+
+	if (*argv == NULL) { /* get  */
+		status = ftm_do_get_ioctl(wl, p_proxd_iov, proxd_iovsize, p_subcmd_info);
+	} else {
+		printf("error: proxd ftm %s cmd doesn't accept any parameters\n",
+			p_subcmd_info->name);
+		status = BCME_ERROR;
+	}
+
+	/* clean up */
+	free(p_proxd_iov);
+
+#ifdef WL_FTM_DEBUG
+	if (status != BCME_OK)
+		printf("%s failed: status=%d\n", __FUNCTION__, status);
+#endif /* WL_FTM_DEBUG */
+
+	return status;
+}
+
+/*
+* get proxd ftm-method version (API version)
+* Usage: wl proxd ftm ver
+*
+* Note, 'session-id' is ignore
+*/
+static int
+ftm_subcmd_get_version(void *wl, const ftm_subcmd_info_t *p_subcmd_info, wl_proxd_method_t method,
+	wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar and display the 'version' */
+	return ftm_common_getcmd_handler(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* get session result - may be in progress. Both rtt and aoa results returned (as available).
+*                      Also lci and civic location if available.
+* Usage: wl proxd ftm <session-id> result
+* Note, caller should have verified the session-id before this call.
+*/
+static int
+ftm_subcmd_get_result(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar and display the 'session result' */
+	return ftm_common_getcmd_handler(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* get the global ftm-method info or session-info if session-id is specified.
+* Usage:
+*       wl proxd ftm [<session-id>] info
+*/
+static int
+ftm_subcmd_get_info(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar and display the 'method/session info' */
+	return ftm_common_getcmd_handler(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* get the ftm-method status or session status if session-id is specified.
+* Usage: wl proxd ftm [<session-id>] status
+*/
+static int
+ftm_subcmd_get_status(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar and display the 'method/session status' */
+	return ftm_common_getcmd_handler(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* list all sessions for the ftm method
+* Usage: wl proxd ftm sessions
+*/
+static int
+ftm_subcmd_get_sessions(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar and display the 'sessions' */
+	return ftm_common_getcmd_handler(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* get the ftm-method counters or sessions counters if session-id is specified.
+* Usage:wl proxd ftm [<session-id>] counters
+*/
+static int
+ftm_subcmd_get_counters(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar and display the 'method/session counters' */
+	return ftm_common_getcmd_handler(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* get the global ftm-method ranging-info
+* Usage:
+*       wl proxd ftm ranging-info
+*/
+static int
+ftm_subcmd_get_ranging_info(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar and display the 'ranging info' */
+	return ftm_common_getcmd_handler(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* dump the ftm-method or a session if session-id is specified.
+* Usage: wl proxd ftm [<session-id>] dump
+*/
+static int
+ftm_subcmd_dump(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar and display the 'dump result' */
+	return ftm_common_getcmd_handler(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/* ***************************** set commands ********************* */
+
+/*
+* common handler for set-related proxd method commands which require no TLV as input
+*   wl proxd ftm [session-id] <set-subcmd>
+* e.g.
+*   wl proxd ftm enable -- to enable ftm
+*   wl proxd ftm disable -- to disable ftm
+*   wl proxd ftm <session-id> start -- to start a specified session
+*   wl proxd ftm <session-id> stop  -- to cancel a specified session;
+*                                    state is maintained till session is delete.
+*   wl proxd ftm <session-id> delete -- to delete a specified session
+*   wl proxd ftm [<session-id>] clear-counters -- to clear counters
+*   wl proxd ftm <session-id> burst-request -- on initiator: to send burst request;
+*                                              on target: send FTM frame
+*   wl proxd ftm <session-id> collect
+*   wl proxd ftm tune     (TBD)
+*/
+static int
+ftm_subcmd_setiov_no_tlv(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	uint16 proxd_iovsize;
+	wl_proxd_iov_t *p_proxd_iov;
+	int res;
+
+	UNUSED_PARAMETER(wl);
+
+#ifdef WL_FTM_DEBUG
+	printf("enter %s: method=%d, session_id=%d, cmdid=%d(%s)\n",
+		__FUNCTION__, method, session_id,
+		p_subcmd_info->cmdid, ftm_cmdid_to_str(p_subcmd_info->cmdid));
+#endif /* WL_FTM_DEBUG */
+
+	/* do not accept any parameters */
+	if (*argv != NULL)
+	{
+		printf("error: proxd ftm %s cmd doesn't accept any parameters\n",
+			p_subcmd_info->name);
+		return BCME_USAGE_ERROR;
+	}
+
+	/* allocate and initialize a temp buffer for 'set proxd' iovar */
+	proxd_iovsize = 0;
+	p_proxd_iov = ftm_alloc_getset_buf(method, session_id, p_subcmd_info->cmdid,
+							0, &proxd_iovsize);		/* no TLV */
+	if (p_proxd_iov == NULL)
+		return BCME_NOMEM;
+
+	/* no TLV to pack, simply issue a set-proxd iovar */
+	res = wlu_var_setbuf(wl, "proxd", (void *) p_proxd_iov, proxd_iovsize);
+	if (res != BCME_OK) {
+		printf("error: IOVAR failed, status=%d\n", res);
+	}
+
+	/* clean up */
+	free(p_proxd_iov);
+
+	return res;
+}
+
+/*
+* enable FTM method
+* Usage: wl proxd ftm enable
+*/
+static int
+ftm_subcmd_enable(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar call */
+	return ftm_subcmd_setiov_no_tlv(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* disable FTM method
+* Usage: wl proxd ftm disable
+*/
+static int
+ftm_subcmd_disable(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar call */
+	return ftm_subcmd_setiov_no_tlv(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* start scheduling the burst(s) for the session. Initiates FTM request or await requests on target.
+* Usage: wl proxd ftm <session-id> start
+*
+* Note, caller should have verified the session-id before this call.
+*/
+static int
+ftm_subcmd_start_session(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar call */
+	return ftm_subcmd_setiov_no_tlv(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* cancel the session. State maintained until session is deleted.
+* Usage: wl proxd ftm <session-id> stop
+*
+* Note, caller should have verify the session-id before this call.
+*/
+static int ftm_subcmd_stop_session(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar call */
+	return ftm_subcmd_setiov_no_tlv(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* burst request: on initiator send burst request and process FTM frames.
+*                On target, send FTM frames
+* Usage: wl proxd ftm <session-id> burst-request
+*
+* Note, caller should have verified the session-id before this call.
+*/
+static int
+ftm_subcmd_burst_request(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar call */
+	return ftm_subcmd_setiov_no_tlv(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* delete the session.
+* Usage: wl proxd ftm <session-id> delete
+*
+* Note, caller should have verify the session-id before this call.
+*/
+static int
+ftm_subcmd_delete_session(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar call */
+	return ftm_subcmd_setiov_no_tlv(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* clear counters
+* Usage: wl proxd ftm [<session-id>] clear_counters
+*
+* Note, caller should have verify the session-id before this call.
+*/
+static int
+ftm_subcmd_clear_counters(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* issue an iovar call */
+	return ftm_subcmd_setiov_no_tlv(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* define param-info for global/session 'non-options' configuration for
+*    'wl proxd ftm [<session-id>] config [<param-name> <param-value>]*'
+*/
+typedef struct ftm_config_param_info {
+	char		*name;	/* <param-name> string to identify a configurable item */
+	uint16		tlvid;	/* mapping TLV id for the item */
+	char		*name_helpmsg;	/* help message for the <param-name> config-item */
+	ftm_subcmd_flag_t	cmdflag;	/* supported group(s) */
+} ftm_config_param_info_t;
+
+static const ftm_config_param_info_t ftm_config_param_info[] = {
+	/* "name",			tlv_id				param-name helpmsg */
+	{ "bssidx", WL_PROXD_TLV_ID_BSS_INDEX, "BSS index to use for the session",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "chanspec", WL_PROXD_TLV_ID_CHANSPEC, "channel spec to use",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "tx-power", WL_PROXD_TLV_ID_TX_POWER, "tx power to use in dbm",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "ratespec", WL_PROXD_TLV_ID_RATESPEC, "rate to use",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "num-ftm", WL_PROXD_TLV_ID_BURST_NUM_FTM, "number of FTM frames in a burst",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "num-burst", WL_PROXD_TLV_ID_NUM_BURST, "number of bursts in the session",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "retries", WL_PROXD_TLV_ID_FTM_RETRIES, "number of retries; not 802.11 mac level retries",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "event-mask", WL_PROXD_TLV_ID_EVENT_MASK, "bitmask of subscribed events",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "debug-mask", WL_PROXD_TLV_ID_DEBUG_MASK, "bitmask for logging FTM messages",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "burst-duration", WL_PROXD_TLV_ID_BURST_DURATION, "duration for a single burst",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "burst-period", WL_PROXD_TLV_ID_BURST_PERIOD, "time between bursts",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "ftm-sep", WL_PROXD_TLV_ID_BURST_FTM_SEP, "time between FTM frames in a burst",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "burst-timeout", WL_PROXD_TLV_ID_BURST_TIMEOUT, "timeout",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "init-delay", WL_PROXD_TLV_ID_INIT_DELAY, "delay after start",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "bssid", WL_PROXD_TLV_ID_BSSID, "BSSID used for the session",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "peer", WL_PROXD_TLV_ID_PEER_MAC, "peer mac address",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "rx-max-burst", WL_PROXD_TLV_ID_RX_MAX_BURST, "limit bursts for rx(method only)",
+	FTM_SUBCMD_FLAG_METHOD },
+	/* special 'config options', no matching TLV */
+	{ "options", WL_PROXD_TLV_ID_NONE,
+	"type 'wl proxd -h ftm config options' for more information",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "session-options", WL_PROXD_TLV_ID_NONE,
+	"type 'wl proxd -h ftm config options' for more information",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "avail", WL_PROXD_TLV_ID_NONE,
+	"type 'wl proxd -h ftm config avail' for more information",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "nan-map-id", WL_PROXD_TLV_ID_NAN_MAP_ID, "NAN map id(method only)",
+	FTM_SUBCMD_FLAG_METHOD },
+	{ "dev-addr", WL_PROXD_TLV_ID_DEV_ADDR, "deivce address(method only)",
+	FTM_SUBCMD_FLAG_METHOD },
+	{ "req-retries", WL_PROXD_TLV_ID_FTM_REQ_RETRIES, "number of FTM request retries",
+	FTM_SUBCMD_FLAG_ALL },
+	{ "tpk", WL_PROXD_TLV_ID_TPK, "tpk to be configured", FTM_SUBCMD_FLAG_ALL }
+};
+
+/* map a specified text-string to a proxd time unit
+*
+*  return true if succeeds, otherwise return false.
+*/
+static bool
+ftm_get_tmu_from_str(char *str, wl_proxd_tmu_t *p_tmu)
+{
+	if (stricmp(str, "tu") == 0)
+		*p_tmu = WL_PROXD_TMU_TU;
+	else if (stricmp(str, "s") == 0)
+		*p_tmu = WL_PROXD_TMU_SEC;
+	else if (stricmp(str, "ms") == 0)
+		*p_tmu = WL_PROXD_TMU_MILLI_SEC;
+	else if (stricmp(str, "us") == 0)
+		*p_tmu = WL_PROXD_TMU_MICRO_SEC;
+	else if (stricmp(str, "ns") == 0)
+		*p_tmu = WL_PROXD_TMU_NANO_SEC;
+	else if (stricmp(str, "ps") == 0)
+		*p_tmu = WL_PROXD_TMU_PICO_SEC;
+	else
+		return FALSE;
+
+	return TRUE;
+}
+
+/*
+* get the config_param_info from the table based on 'param-name' for 'wl proxd ftm config' command
+*
+* return NULL if 'param-name' is not supported
+*/
+static const ftm_config_param_info_t *
+ftm_get_config_param_info(char *p_param_name, wl_proxd_session_id_t session_id)
+{
+	int	i;
+	ftm_subcmd_flag_t		search_cmdflag;
+	const ftm_config_param_info_t	*p_config_param_info;
+
+	/* determine if this is for 'session' or 'method' config */
+	search_cmdflag = (session_id == WL_PROXD_SESSION_ID_GLOBAL) ? FTM_SUBCMD_FLAG_METHOD
+		: FTM_SUBCMD_FLAG_SESSION;
+
+	p_config_param_info = &ftm_config_param_info[0];
+	for (i = 0; i < (int) ARRAYSIZE(ftm_config_param_info); i++) {
+		if (stricmp(p_param_name, p_config_param_info->name) == 0) {
+			/* check if this config-param is supported for method/session */
+			if ((p_config_param_info->cmdflag & search_cmdflag) == 0) {
+				/* not supported for this method/session command */
+				return (ftm_config_param_info_t *) NULL;
+			}
+
+			return p_config_param_info;
+		}
+		p_config_param_info++;		/* next */
+	}
+
+	return (ftm_config_param_info_t *) NULL;		/* 'invalid param name' */
+}
+
+/*
+* define param-value info for global/session 'options' configuration for
+*    'wl proxd ftm [<session-id>] config options {[+|-]<param-value>}*'
+*/
+typedef struct ftm_config_options_info {
+	char	*param_value_str;	/* <param-value> str to identify an options-flag */
+	uint32	flags;				/* wl_proxd_flags_t/wl_proxd_session_flags_t */
+	char	*helpmsg;			/* help message for the param-value */
+} ftm_config_options_info_t;
+
+/* global/method config options/flags */
+static const ftm_config_options_info_t ftm_method_options_info[] = {
+	/* param-value-string	wl_proxd_flags_t			helpmsg */
+	{ "rx-enable", WL_PROXD_FLAG_RX_ENABLED,
+	"If enabled, process requests; If disabled, requests will be ignored"},
+	{ "rx-range-req", WL_PROXD_FLAG_RX_RANGE_REQ,
+	"If enabled, process 11mc range requests; If disabled, requests will be ignored" },
+	{ "tx-lci", WL_PROXD_FLAG_TX_LCI, "transmit LCI, if available" },
+	{ "tx-civic", WL_PROXD_FLAG_TX_CIVIC, "tx civic location, if available" },
+	{ "rx-auto-burst", WL_PROXD_FLAG_RX_AUTO_BURST,
+	"If enabled, respond to requests without host action.\n"
+	"\t\t                                     "
+	"If disabled, the request is forwarded to host via an event.\n"
+	"\t\t                                     "
+	"If the event is masked, the request is dropped" },
+	{ "tx-auto-burst", WL_PROXD_FLAG_TX_AUTO_BURST,
+	"If enabled, continue an initiated session with a new burst without host action\n"
+	"\t\t                                     "
+	"until the number of bursts for the session is completed" },
+	{ "avail-publish", WL_PROXD_FLAG_AVAIL_PUBLISH, "publish local availability" },
+	{ "avail-schedule", WL_PROXD_FLAG_AVAIL_SCHEDULE, "schedule local availability" },
+	{ "asap-capable", WL_PROXD_FLAG_ASAP_CAPABLE, "capable of ASAP scheduling"},
+	{ "mburst-followup", WL_PROXD_FLAG_MBURST_FOLLOWUP,
+	"enable multi-burst followup algorithm " },
+	{ "secure", WL_PROXD_FLAG_SECURE,
+	"Enable security for ftm - per BSS" },
+	{ "all", WL_PROXD_FLAG_ALL, "all of the above" }
+};
+
+/* config session options/flags */
+static const ftm_config_options_info_t ftm_session_options_info[] = {
+	/* param-value-string	wl_proxd_session_flags_t	helpmsg */
+	{ "initiator",	WL_PROXD_SESSION_FLAG_INITIATOR, "local device is an initiator" },
+	{ "target",		WL_PROXD_SESSION_FLAG_TARGET, "local device is a target" },
+	{ "one-way",	WL_PROXD_SESSION_FLAG_ONE_WAY, "(initiated) 1-way rtt " },
+	{ "auto-burst",	WL_PROXD_SESSION_FLAG_AUTO_BURST, "created with rx_auto_burst" },
+	{ "immediate", WL_PROXD_SESSION_FLAG_MBURST_NODELAY, "immediate next burst" },
+	{ "rtt-detail",	WL_PROXD_SESSION_FLAG_RTT_DETAIL, "provide rtt detail in results" },
+#ifdef SJL_FIXME
+	{ "aoa",		WL_PROXD_SESSION_FLAG_AOA, "AOA along with RTT" },
+#endif /* SJL_FIXME */
+	{ "rx-auto-burst",	WL_PROXD_SESSION_FLAG_RX_AUTO_BURST,
+	"Same as proxd flags above, applies to the session" },
+	{ "tx-auto-burst",	WL_PROXD_SESSION_FLAG_TX_AUTO_BURST,
+	"Same as proxd flags above, applies to the session" },
+	{ "nan-bss",	WL_PROXD_SESSION_FLAG_NAN_BSS, "Use NAN BSS, if applicable" },
+	{ "ts1", WL_PROXD_SESSION_FLAG_TS1, "FTM1 - ASAP-capable" }, /* readonly */
+#ifdef SJL_FIXME
+	{ "rpt-failure", WL_PROXD_SESSION_FLAG_REPORT_FAILURE,
+	"(target) report not rx distance to host" },
+#endif /* SJL_FIXME */
+	{ "initiator-rpt", WL_PROXD_SESSION_FLAG_INITIATOR_RPT,
+	"tx initiator-report to target" },
+	{ "neutral", WL_PROXD_SESSION_FLAG_NETRUAL, "neutral mode" },
+	{ "seq-en", WL_PROXD_SESSION_FLAG_SEQ_EN, "sequence sampling capture" },
+	{"no-param-override", WL_PROXD_SESSION_FLAG_NO_PARAM_OVRD,
+	"disallow override from target"},
+	{"asap", WL_PROXD_SESSION_FLAG_ASAP, "use ASAP scheduling"},
+	{ "tx-lci-req", WL_PROXD_SESSION_FLAG_REQ_LCI, "transmit LCI request" },
+	{ "tx-civic-req", WL_PROXD_SESSION_FLAG_REQ_CIV, "tx civic location request" },
+	{ "pre-scan", WL_PROXD_SESSION_FLAG_PRE_SCAN, "enable asap pre-scan on initiator" },
+	{ "auto-vhtack", WL_PROXD_SESSION_FLAG_AUTO_VHTACK, "use vhtack based on brcm ie" },
+	{ "vhtack", WL_PROXD_SESSION_FLAG_VHTACK, "vht ack is in use - output only" },
+	{ "burst-duration-nopref", WL_PROXD_SESSION_FLAG_BDUR_NOPREF,
+	"duration for a single burst - no preference" },
+	{ "num-ftm-nopref", WL_PROXD_SESSION_FLAG_NUM_FTM_NOPREF,
+	"number of FTM frames in a burst - no preference" },
+	{ "ftm-sep-nopref", WL_PROXD_SESSION_FLAG_FTM_SEP_NOPREF,
+	"time between FTM frames in a burst - no preference " },
+	{ "num-burst-nopref", WL_PROXD_SESSION_FLAG_NUM_BURST_NOPREF,
+	"number of bursts in a session - no preference " },
+	{ "burst-period-nopref", WL_PROXD_SESSION_FLAG_BURST_PERIOD_NOPREF,
+	"time between bursts - no preference " },
+	{ "all",		WL_PROXD_SESSION_FLAG_ALL, "all of the above" }
+};
+
+static void
+ftm_cmn_display_config_options_value(uint32 flags,
+	const ftm_config_options_info_t *p_table, uint32 num_entries)
+{
+	const ftm_config_options_info_t *p_entry;
+	uint32		i;
+
+	if (flags) {
+		printf(" (");
+
+		/* walk thru the table to find a match indicating
+		the specified param_value_str is valid
+		*/
+		p_entry = p_table;
+		for (i = 0; i < num_entries; i++) {
+			if ((p_entry->flags & flags) == p_entry->flags) {
+				printf(" %s", p_entry->param_value_str);
+			}
+
+			p_entry++;		/* next */
+		}
+
+		printf(" )");
+
+	}
+	printf("\n");
+}
+
+static void
+ftm_unpack_and_display_session_flags(const uint8 *p_data, uint16 tlvid)
+{
+	wl_proxd_session_flags_t flags = ltoh32_ua(p_data);
+
+	printf("> %s: 0x%x", ftm_tlvid_to_logstr(tlvid), flags);
+	/* display the value in a readable format */
+	ftm_cmn_display_config_options_value((uint32) flags,
+		&ftm_session_options_info[0], ARRAYSIZE(ftm_session_options_info));
+}
+
+static void
+ftm_unpack_and_display_config_flags(const uint8 *p_data, uint16 tlvid)
+{
+	wl_proxd_flags_t flags = ltoh32_ua(p_data);
+
+	printf("> %s: 0x%x", ftm_tlvid_to_logstr(tlvid), flags);
+	/* display the value in a readable format */
+	return ftm_cmn_display_config_options_value((uint32) flags,
+		&ftm_method_options_info[0], ARRAYSIZE(ftm_method_options_info));
+}
+
+/* get the method/session config-options info from the table based on 'options param_value_str'
+* Input:
+*       param_value_str -- a 'config options' param-value string to identify a config-options flag
+*       useMethod -- set to true to look up 'config options' table for FTM method
+*                    set to false to look up 'config options' table for a session
+* if succeeds, return a pointer to the config_options_info, otherwise return NULL
+*/
+static const ftm_config_options_info_t *
+ftm_get_config_options_info(char *param_value_str, bool useMethod)
+{
+	int	i;
+	const ftm_config_options_info_t	*p_entry;
+	int	num_entries;
+	if (useMethod) {		/* choose an options table for method command */
+		p_entry = &ftm_method_options_info[0];
+		num_entries = ARRAYSIZE(ftm_method_options_info);
+	}
+	else {					/* choose an options table for sessions command */
+		p_entry = &ftm_session_options_info[0];
+		num_entries = ARRAYSIZE(ftm_session_options_info);
+	}
+
+	/* walk thru the table to find a match indicating the specified param_value_str is valid */
+	for (i = 0; i < num_entries; i++) {
+		if (stricmp(param_value_str, p_entry->param_value_str) == 0)
+			return p_entry;
+		p_entry++;		/* next */
+	}
+
+	return (ftm_config_options_info_t *) NULL;		/* 'invalid param value' */
+}
+
+/*
+* handle 'wl proxd ftm [<session-id>] config options [+|-]param-value'
+*   parse cmd-line, setup method/sessions options/flags TLVs in caller
+*   provided buffer and adjusted-buffer-space if applies.
+* Note, input '<session-id>' is used to determine if config-options is
+*   for 'global/method' or 'sessions'.
+*
+* This function is invoked from ftm_subcmd_config().
+*/
+static int
+ftm_handle_config_options(wl_proxd_session_id_t session_id, char **argv,
+	wl_proxd_tlv_t **p_tlv, uint16 *p_buf_space_left, bool useMethod)
+{
+	bool	bEnable;
+	int		status;
+	char	*p_param_value;
+	uint32 flags = WL_PROXD_FLAG_NONE;
+	uint32 flags_mask = WL_PROXD_FLAG_NONE;
+	uint32 new_mask;		/* cmdline input */
+	const ftm_config_options_info_t *p_options_info;
+
+	UNUSED_PARAMETER(session_id);
+
+	/* check if user provides param-values for 'config options' command */
+	if (*argv == NULL)
+		return BCME_USAGE_ERROR;
+
+	/* <param-value>  followed 'wl proxd ftm [session-id] config options' */
+	while (*argv != NULL) {
+		bEnable = TRUE;		/* default: set the flag if '+/-' is omitted */
+		if ((*argv)[0] == '-' || (*argv)[0] == '+') {
+			bEnable = ((*argv)[0] == '-') ? FALSE : TRUE;
+			p_param_value = *argv + 1;			/* skip the prefix */
+			if (*p_param_value == '\0')
+				return BCME_USAGE_ERROR;
+		}
+		else
+			p_param_value = *argv;
+
+		/* check if 'param-value' (specified in ascii-string) is valid */
+		p_options_info = ftm_get_config_options_info(p_param_value, useMethod);
+		if (p_options_info != (ftm_config_options_info_t *) NULL) {
+			new_mask = p_options_info->flags;
+		}
+		else {
+			/* check if specifed as an intergral number string */
+			new_mask = strtoul(p_param_value, NULL, 0);
+			if (new_mask == 0) {			/* conversion error, abort */
+				printf("error: invalid param-value(%s)\n", p_param_value);
+				return BCME_USAGE_ERROR;	/* param-value is invalid  */
+			}
+		}
+
+		/* update flags mask */
+		flags_mask = flags_mask | new_mask;
+		if (bEnable)
+			flags |= new_mask;	/* set the bit on */
+		else
+			flags &= ~new_mask;	/* set the bit off */
+
+		argv++;					/* continue on next <param-value> */
+	}
+
+#ifdef WL_FTM_DEBUG
+	printf("%s: about to set TLVs for %s-options flags_mask=0x%x flags=0x%x\n",
+		__FUNCTION__, useMethod ? "method" : "sessions", flags_mask, flags);
+#endif /* WL_FTM_DEBUG */
+
+	flags = htol32(flags);
+	flags_mask = htol32(flags_mask);
+
+	/* setup flags_mask TLV */
+	status = bcm_pack_xtlv_entry((uint8 **)p_tlv, p_buf_space_left,
+		useMethod ? WL_PROXD_TLV_ID_FLAGS_MASK : WL_PROXD_TLV_ID_SESSION_FLAGS_MASK,
+		sizeof(uint32), (uint8 *)&flags_mask, BCM_XTLV_OPTION_ALIGN32);
+	if (status != BCME_OK) {
+#ifdef WL_FTM_DEBUG
+		printf("%s: bcm_pack_xltv_entry() for flags_mask failed, status=%d\n",
+			__FUNCTION__, status);
+#endif /* WL_FTM_DEBUG */
+		return status;				/* abort */
+	}
+
+	/* setup flags TLV */
+	status = bcm_pack_xtlv_entry((uint8 **)p_tlv, p_buf_space_left,
+		useMethod ? WL_PROXD_TLV_ID_FLAGS : WL_PROXD_TLV_ID_SESSION_FLAGS,
+		sizeof(uint32), (uint8 *)&flags, BCM_XTLV_OPTION_ALIGN32);
+	if (status != BCME_OK) {
+#ifdef WL_FTM_DEBUG
+		printf("%s: bcm_pack_xltv_entry() for flags failed, status=%d\n",
+			__FUNCTION__, status);
+#endif /* WL_FTM_DEBUG */
+		return status;				/* abort */
+	}
+
+	return BCME_OK;
+}
+
+/*
+	num_burst must be power of 2 (max exponent is 14)
+*/
+static int
+ftm_validate_num_burst(uint16 num_burst, const ftm_config_param_info_t *p_config_param_info)
+{
+#define WL_FTM_MAX_NUM_BURST_EXP	14
+	uint16 exponent;
+	uint64 x_num_burst;
+	int i;
+
+	/* get the exponent value */
+	exponent = 0;
+	x_num_burst = (uint64) num_burst;
+	for (i = 0; i < (int) (sizeof(num_burst) * NBBY); ++i, x_num_burst >>= 1) {
+		if (x_num_burst & 0x1)
+			exponent = i;
+	}
+
+	if (exponent > WL_FTM_MAX_NUM_BURST_EXP) {
+		printf("error:' %s' value is out of range (should not exceed 0x%x)\n",
+			p_config_param_info->name, 1 << WL_FTM_MAX_NUM_BURST_EXP);
+		return BCME_RANGE;
+	}
+
+	if (num_burst != (1 << exponent)) {
+		printf("error: '%s' value must be power of 2\n",
+			p_config_param_info->name);
+		return BCME_RANGE;	/* not power of 2 */
+	}
+
+	return BCME_OK;
+}
+
+/*
+	parse 'param-value' for 'ftm config' command
+*/
+static int
+ftm_config_parse_ul(char **argv, const ftm_config_param_info_t *p_config_param_info,
+	unsigned long int min_value, unsigned long int max_value,
+	unsigned long int *out_data)
+{
+	int status = BCME_OK;
+	unsigned long int	tmp_data_ul;
+
+	tmp_data_ul = strtoul(*argv, NULL, 0);
+	if (tmp_data_ul < min_value || tmp_data_ul > max_value) {
+		printf("error: '%s' value is out of range\n",
+			p_config_param_info->name);
+		return BCME_RANGE;
+	}
+
+	/* validate the arguments */
+	if (p_config_param_info->tlvid == WL_PROXD_TLV_ID_NUM_BURST ||
+		p_config_param_info->tlvid == WL_PROXD_TLV_ID_RX_MAX_BURST) {
+		status = ftm_validate_num_burst((uint16) tmp_data_ul, p_config_param_info);
+		if (status != BCME_OK)
+			return status;
+	}
+
+	/* param-value parsing: success */
+	*out_data = tmp_data_ul;
+
+	return BCME_OK;
+}
+
+/*
+* parse and pack 'chanspec' from a command-line argument
+* Input:
+*	arg_channel: a channel-string
+*	out_channel: buffer to store the result
+*/
+static int
+ftm_config_parse_channel(char *arg_channel, uint32 *out_channel)
+{
+	int	status = BCME_OK;
+	uint32 src_data_channel = 0;	/* default: invalid */
+
+	/* note, chanespec_t is currently defined as 16-bit, however */
+	/* wl-interface use 'uint32' to allow future change for 32-bit */
+	if (arg_channel != (char *) NULL)
+		src_data_channel = (uint32) wf_chspec_aton(arg_channel);
+
+	if (src_data_channel == 0) {
+		printf("error: invalid chanspec\n");
+		status = BCME_BADARG;
+	}
+
+	*out_channel = htol32(src_data_channel);
+	return status;
+}
+
+/*
+* parse and pack 'intvl' param-value from a command-line argument
+* Input:
+*	arg_intvl: a time-intvl string
+*	out_intvl: buffer to store the result
+*/
+static int
+ftm_config_parse_intvl(char *arg_intvl, wl_proxd_intvl_t *out_intvl)
+{
+	wl_proxd_intvl_t	src_data_intvl;
+	char *p_end;
+
+	/* initialize */
+	memset(out_intvl, 0, sizeof(*out_intvl));
+
+	if (arg_intvl == (char *) NULL) {
+		printf("error: time-interval value is not specified\n");
+		return BCME_BADARG;
+	}
+
+	errno = 0;
+	memset(&src_data_intvl, 0, sizeof(src_data_intvl));
+	/* time interval e.g. 10ns */
+	/* get the number */
+	p_end = NULL;
+	src_data_intvl.intvl = htol32(strtoul(arg_intvl, &p_end, 10));
+	if (errno) {
+		printf("error: invalid time interval (errno=%d)\n", errno);
+		return BCME_BADARG;
+	}
+
+	/* get time-unit */
+	src_data_intvl.tmu = WL_PROXD_TMU_TU; /* default */
+	if (*p_end != '\0') {
+		if (!ftm_get_tmu_from_str(p_end, &src_data_intvl.tmu)) {
+			printf("error: invalid time-unit %s\n", p_end);
+			return BCME_BADARG;
+		}
+	}
+	src_data_intvl.tmu = htol16(src_data_intvl.tmu);
+
+	/* return to caller */
+	memcpy(out_intvl, &src_data_intvl, sizeof(*out_intvl));
+
+	return BCME_OK;
+}
+
+/*
+* parse and pack 'intvl' param-value from a command-line argument
+* Input:
+*	arg_tpk: tpk param-value argument string
+*	out_tpk: buffer to store tpk and mac address
+*/
+static int
+ftm_config_parse_tpk_peer(char *arg_tpk, wl_proxd_tpk_t *out_tpk)
+{
+	wl_proxd_tpk_t	src_data_tpk;
+
+	/* initialize */
+	memset(out_tpk, 0, sizeof(*out_tpk));
+
+	if (arg_tpk == (char *) NULL) {
+		printf("error: tpk value is not specified\n");
+		return BCME_BADARG;
+	}
+
+	errno = 0;
+	memset(&src_data_tpk, 0, sizeof(src_data_tpk));
+	/* get link mac address */
+	if (!wl_ether_atoe(arg_tpk, &src_data_tpk.peer))
+		return BCME_USAGE_ERROR;
+	/* get TPK */
+	if (*arg_tpk) {
+		memcpy(&src_data_tpk.peer, arg_tpk, ETHER_ADDR_LEN);
+	}
+
+	/* return to caller */
+	memcpy(out_tpk, &src_data_tpk, sizeof(*out_tpk));
+
+	return BCME_OK;
+}
+
+
+/*
+* parse and pack one 'config avail slot' param-value from a command-line
+* Input:
+*	arg_slot: 'slot' param-value argument string
+*             in "channel:start-tmu:duration-tmu" format
+*	out_avail_slot: buffer to store the result
+*/
+static int
+ftm_config_avail_parse_slot(char *arg_slot, wl_proxd_time_slot_t *out_avail_slot)
+{
+	int arg_idx;
+	const char *tmp_start, *tmp_end;
+	char tmpbuf[128];
+	int len;
+	int	status = BCME_OK;
+
+	if (arg_slot == (char *) NULL) {
+		printf("error: slot value is not specified\n");
+		return BCME_BADARG;
+	}
+
+	/* parse channel:start-tmu:duration-tmu */
+	tmp_start = arg_slot;
+	for (arg_idx = 0; arg_idx < 3; arg_idx++) {
+		tmp_end = strchr(tmp_start, ':');
+		if (tmp_end == NULL) {
+			if (arg_idx != 2 || *tmp_start == '\0') {
+				status = BCME_BADARG;
+				goto done;
+			}
+			/* for last 'duration intvl' */
+			tmp_end = tmp_start + strlen(tmp_start);
+		}
+
+		/* create a temp null-terminated substring */
+		if ((len = tmp_end - tmp_start) >= (int) sizeof(tmpbuf)) {
+			status = BCME_BADARG;
+			goto done;
+		}
+
+		memcpy(tmpbuf, tmp_start, len);
+		tmpbuf[len] = '\0';	/* null-terminate */
+
+		if (arg_idx == 0)
+			status = ftm_config_parse_channel(tmpbuf, &out_avail_slot->chanspec);
+		else if (arg_idx == 1)
+			status = ftm_config_parse_intvl(tmpbuf, &out_avail_slot->start);
+		else /* arg_idx == 2 */
+			status = ftm_config_parse_intvl(tmpbuf, &out_avail_slot->duration);
+
+		if (status != BCME_OK)
+			goto done;
+		/* continue on next element */
+		tmp_start = tmp_end + 1;
+
+	}
+	/* make sure no string beyond 'channel:start-tmu:duration-tmu' */
+	if (*tmp_end != '\0') {
+		printf("error: invalid 'slot' value '%s'\n", tmp_end);
+		status = BCME_BADARG;
+	}
+
+done:
+	if (status == BCME_BADARG)
+		printf("error: invalid value for slot\n");
+
+	return status;
+}
+
+/*
+* parse and pack 'config avail time-ref' param-value from a command-line
+* Input:
+*	arg_tref: 'time-ref' param-value argument string
+*                    in "none|dev-tsf|nan-dw|tbtt" format
+*      out_tref: buffer to store the result
+*/
+static int
+ftm_config_avail_parse_tref(char *arg_tref, wl_proxd_time_ref_t *out_tref)
+{
+	wl_proxd_time_ref_t src_data_tref;
+	const ftm_strmap_entry_t	*p_entry;
+
+	if (arg_tref == (char *) NULL) {
+		printf("error: time-ref value is not specified\n");
+		return BCME_BADARG;
+	}
+
+	/* loop up */
+	p_entry = ftm_get_strmap_info_strkey(arg_tref, &ftm_avail_timeref_value_loginfo[0],
+		ARRAYSIZE(ftm_avail_timeref_value_loginfo));
+	if (p_entry)
+		src_data_tref = p_entry->id;
+	else {
+		printf("error: invalid time-ref value\n");
+		return BCME_BADARG;
+	}
+
+	*out_tref = htol16((uint16) src_data_tref);
+
+	return BCME_OK;
+
+}
+
+#define FTM_AVAIL_MAX_SLOTS		32	/* also in pdftmpvt.h */
+/*
+* parse and pack a list of 'slot-value' for availability
+* Input:
+*	argv -- point to something like "ch1:start-tmu1:duration-tmu1
+*                                    ch2:start-tmu2:duration-tmu2 ..."
+*/
+static int
+ftm_config_avail_parse_all_slots(char **argv, wl_proxd_avail_t *avail, uint16 *out_num_slots)
+{
+	int	err = BCME_OK;
+	uint16	num_slots;
+	wl_proxd_time_slot_t	*avail_slot;
+
+	*out_num_slots = 0;
+
+	num_slots = 0;
+	avail_slot = WL_PROXD_AVAIL_TIMESLOTS(avail);
+	while (*argv != NULL) {	/* parse each slot-value */
+		if (num_slots >= FTM_AVAIL_MAX_SLOTS) {
+			printf("error: number of slots exceed the limit (%d)\n",
+				FTM_AVAIL_MAX_SLOTS);
+			err = BCME_BADARG;	/* too many time-slots */
+			goto done;
+		}
+
+		/* parse channel:start-tmu:duration-tmu */
+		err = ftm_config_avail_parse_slot(*argv, avail_slot);
+		if (err != BCME_OK)
+			goto done;
+
+		num_slots++;
+		avail_slot++;
+
+		++argv;		/* continue on next slot-value */
+	}
+
+	if (num_slots == 0) {
+		printf("error: slot-value is not specified\n");
+		err = BCME_BADARG;
+		goto done;
+	}
+
+	*out_num_slots = num_slots;
+
+done:
+	return err;
+}
+
+/*
+* allocate the availability info
+* if succeeds, an avail-buffer with 'max_slots' will be allocated
+*/
+static int
+ftm_config_avail_alloc(wl_proxd_avail_t **out_avail)
+{
+	uint16 bufsize;
+	wl_proxd_avail_t	*avail;
+
+	/* init */
+	*out_avail = (wl_proxd_avail_t *) NULL;
+
+	bufsize = WL_PROXD_AVAIL_SIZE(avail, FTM_AVAIL_MAX_SLOTS);
+	avail = calloc(1, bufsize);
+	if (avail == NULL) {
+		printf("error: failed to allocate %d bytes of memory for avail\n",
+			bufsize);
+		return BCME_NOMEM;
+	}
+
+	/* initialize */
+	avail->flags = htol16(WL_PROXD_AVAIL_NONE); 	/* don't care, for query only */
+	avail->time_ref = htol16(WL_PROXD_TREF_NONE);
+	avail->max_slots = htol16(FTM_AVAIL_MAX_SLOTS);
+	avail->num_slots = htol16(0);
+
+#define WLU_PROXD_AVAIL_REPEAT_TU 512 /* default interval */
+	avail->repeat.intvl = htol32(WLU_PROXD_AVAIL_REPEAT_TU);
+	avail->repeat.tmu = htol16(WL_PROXD_TMU_TU);
+
+	*out_avail = avail;
+
+	return BCME_OK;
+}
+
+/* Support AVAIL24 */
+/*
+* allocate and convert the availability info to AVAIL24 format
+* if succeeds, an avail-buffer with 'in_avail_num_slots' time slot in AVAIL24
+* format will be allocated.
+*/
+static int
+ftm_config_avail_to_avail24(wl_proxd_avail_t *in_avail,
+	uint16		in_avail_num_slots, wl_proxd_avail24_t **out_avail)
+{
+	uint16 bufsize;
+	wl_proxd_avail24_t	*avail24 = NULL;
+	wl_proxd_time_slot_t *avail_slot, *avail24_slot;
+
+	/* init */
+	*out_avail = (wl_proxd_avail24_t *) NULL;
+
+	bufsize = WL_PROXD_AVAIL24_SIZE(avail24, in_avail_num_slots);
+	avail24 = calloc(1, bufsize);
+	if (avail24 == NULL) {
+		printf("error: failed to allocate %d bytes of memory for avail\n",
+			bufsize);
+		return BCME_NOMEM;
+	}
+
+	/* convert the header */
+	avail24->flags = in_avail->flags;
+	avail24->time_ref = in_avail->time_ref;
+	avail24->max_slots = htol16(in_avail_num_slots);	/* don't care, for query only */
+	avail24->num_slots = avail24->max_slots;
+	avail24->repeat.intvl = in_avail->repeat.intvl;
+	avail24->repeat.tmu = in_avail->repeat.tmu;
+
+	/* convert time-slot */
+	avail_slot = WL_PROXD_AVAIL_TIMESLOTS(in_avail);
+	avail24_slot = WL_PROXD_AVAIL24_TIMESLOTS(avail24); /* &avail24->ts0[0]; */
+
+	memcpy(avail24_slot, avail_slot, in_avail_num_slots * sizeof(avail24->ts0[0]));
+
+	*out_avail = avail24;
+
+	return BCME_OK;
+}
+
+/*
+* parse cmd-line for 'wl proxd ftm [<session-id>] config avail' command
+*	{ [ftm-ref] none |
+*     time-ref dev-tsf|nan-adv|tbtt repeat repeat-tmu slot {channel:start-tmu:duration-tmu}+ }
+* if succeeds, an avail info is allocated (data is packed) and returned.
+* Also, number of time-slots associated with this buffer will be returned
+* in 'out_num_slots'.
+*/
+static int
+ftm_pack_config_avail_from_cmdarg(char **argv,
+	wl_proxd_avail_t **out_avail, uint16 *out_num_slots)
+{
+	wl_proxd_avail_t		*avail = NULL;
+	wl_proxd_time_ref_t		time_ref;
+	uint16					num_slots = 0;
+	int err = BCME_OK;
+
+	/* init */
+	*out_avail = NULL;
+	*out_num_slots = 0;
+
+	/* check if user provides <param-name><param-value> for 'config avail' command */
+	if (*argv == NULL) {
+		err = BCME_USAGE_ERROR;
+		goto done;
+	}
+
+	/* allocate a buffer for parsing cmd-args */
+	err = ftm_config_avail_alloc(&avail);
+	if (err != BCME_OK)
+		goto done;
+
+	/* parse input arguments */
+	num_slots = 0;
+	time_ref = htol16(WL_PROXD_TREF_NONE);	/* default */
+	while (*argv != NULL) {
+		if (stricmp(*argv, "none") == 0) {
+			time_ref = htol16(WL_PROXD_TREF_NONE);
+		}
+		else if (stricmp(*argv, "time-ref") == 0) {
+			++argv;	/* advance to 'param-value' */
+			err = ftm_config_avail_parse_tref(*argv, &time_ref);
+			if (err != BCME_OK)
+				goto done;
+		}
+		else if (stricmp(*argv, "repeat") == 0) {
+			++argv;	/* advance to 'param-value' */
+			err = ftm_config_parse_intvl(*argv, &avail->repeat);
+			if (err != BCME_OK)
+				goto done;
+		}
+		else if (stricmp(*argv, "slot") == 0) {
+			if (time_ref == htol16(WL_PROXD_TREF_NONE)) {
+				printf("error: time-ref is missing or invalid for slot\n");
+				err = BCME_BADARG;
+				goto done;
+			}
+			++argv;	/* advance to 'param-value' */
+
+			err = ftm_config_avail_parse_all_slots(argv, avail, &num_slots);
+			if (err != BCME_OK)
+				goto done;
+			break; /* done parsing */
+		}
+		else {
+			printf("error: invalid param-name (%s)\n", *argv);
+			err = BCME_USAGE_ERROR;	/* param-name is not specified */
+			goto done;
+		}
+
+		++argv;	/* continue on next 'param-name' */
+	}
+
+	avail->time_ref = time_ref;
+	avail->num_slots = htol16(num_slots);
+
+	*out_avail = avail;
+	*out_num_slots = num_slots;
+	avail = (wl_proxd_avail_t *) NULL;
+
+done:
+	if (err != BCME_OK) {
+		if (avail)		/* cleanup */
+			free(avail);
+	}
+
+	return err;
+
+}
+
+/*
+* handle 'wl proxd ftm [<session-id>] config avail
+*	{ [ftm-ref] none |
+*	  time-ref dev-tsf|nan-adv|tbtt repeat repeat-tmu slot {channel:start-tmu:duration-tmu}+ }
+* parse cmd-line, setup local/peer(method/sessions) availability TLVs in caller
+* provided buffer and adjusted-buffer-space if applies.
+* Note, input '<session-id>' is used to determine if config-avail is
+*   for 'local' or 'peer'.
+*
+* This function is invoked from ftm_subcmd_config().
+*/
+static int
+ftm_do_config_avail_iovar(void *wl, wl_proxd_iov_t *p_proxd_iov, uint16 proxd_iovsize,
+	uint16 tlvid, void *avail, int avail_size)
+{
+	int err = BCME_OK;
+	uint16 bufsize;
+	wl_proxd_tlv_t *p_tlv;
+	uint16	buf_space_left;
+	uint16 all_tlvsize;
+
+	/* setup TLVs */
+	bufsize = proxd_iovsize - WL_PROXD_IOV_HDR_SIZE;	/* adjust available size for TLVs */
+	p_tlv = &p_proxd_iov->tlvs[0];
+
+	/* TLV buffer starts with a full size, will decrement for each packed TLV */
+	buf_space_left = bufsize;
+
+	err = bcm_pack_xtlv_entry((uint8 **) &p_tlv, &buf_space_left,
+		tlvid, avail_size, (void *) avail,
+		BCM_XTLV_OPTION_ALIGN32);
+	if (err != BCME_OK) {
+		printf("%s: failed to pack TLVs for availability, status=%d\n",
+			__FUNCTION__, err);
+		goto done;
+	}
+
+	/* update the iov header, set len to include all TLVs + header */
+	all_tlvsize = (bufsize - buf_space_left);
+	p_proxd_iov->len = htol16(all_tlvsize + WL_PROXD_IOV_HDR_SIZE);
+	err = wlu_var_setbuf(wl, "proxd", p_proxd_iov,
+		all_tlvsize + WL_PROXD_IOV_HDR_SIZE);
+
+done:
+	return err;
+}
+
+static int
+ftm_handle_config_avail(void *wl, wl_proxd_iov_t *p_proxd_iov, uint16 proxd_iovsize,
+wl_proxd_session_id_t session_id, char **argv)
+{
+	int	err = BCME_OK;
+	wl_proxd_avail_t	*avail = NULL;
+	wl_proxd_avail24_t	*avail24 = NULL;
+	uint16				num_slots;
+	int					avail_size;
+
+	UNUSED_PARAMETER(session_id);
+
+	/* parse cmd line and alloc/pack the avail info */
+	err = ftm_pack_config_avail_from_cmdarg(argv,
+		&avail, &num_slots);
+	if (err != BCME_OK)
+		goto done;
+
+	/* pack and request to config the avail using the latest AVAIL if supported */
+	err = ftm_is_tlv_id_supported(wl, WL_PROXD_TLV_ID_AVAIL);
+	if (err == BCME_OK) {
+		/* adjust size based on num-slots available */
+		avail_size = WL_PROXD_AVAIL_SIZE(avail, num_slots);
+		err = ftm_do_config_avail_iovar(wl, p_proxd_iov, proxd_iovsize,
+			WL_PROXD_TLV_ID_AVAIL, (void *) avail, avail_size);
+		goto done;
+	}
+
+	/* try AVAIL24 */
+	/* convert to AVAIL24 format */
+	err = ftm_config_avail_to_avail24(avail,
+		num_slots, &avail24);
+	if (err != BCME_OK)
+		goto done;
+
+	/* adjust size based on num-slots available */
+	avail_size = WL_PROXD_AVAIL24_SIZE(avail24, num_slots);
+	err = ftm_do_config_avail_iovar(wl, p_proxd_iov, proxd_iovsize,
+		WL_PROXD_TLV_ID_AVAIL24, (void *) avail24, avail_size);
+
+done:
+	if (avail) /* clean up */
+		free(avail);
+	if (avail24)
+		free(avail24);
+
+	return err;
+}
+
+/* proxd ftm config-category definition */
+typedef enum {
+	FTM_CONFIG_CAT_GENERAL = 1,	/* generial configuration */
+	FTM_CONFIG_CAT_OPTIONS = 2,	/* 'config options' */
+	FTM_CONFIG_CAT_AVAIL = 3,		/* 'config avail' */
+	FTM_CONFIG_CAT_SESSION_OPTIONS  = 4
+} ftm_config_category_t;
+
+/*
+* parse the config-category from a command-line
+* Input:
+*   arg_type: a config-category string after 'wl proxd ftm config' from the command-line
+*/
+static ftm_config_category_t
+ftm_parse_config_category(char *arg_category)
+{
+	if (stricmp(arg_category, "options") == 0)
+		return FTM_CONFIG_CAT_OPTIONS;
+	if (stricmp(arg_category, "avail") == 0)
+		return FTM_CONFIG_CAT_AVAIL;
+	if (stricmp(arg_category, "session-options") == 0)
+		return FTM_CONFIG_CAT_SESSION_OPTIONS;
+
+	return FTM_CONFIG_CAT_GENERAL;
+}
+
+/*
+* 'wl proxd ftm config' handler for general-configuration:
+*        wl proxd ftm [<session-id>] config [<param-name> <param-value>]+
+*/
+static int
+ftm_handle_config_general(wl_proxd_session_id_t session_id, char **argv,
+wl_proxd_tlv_t **p_tlv, uint16 *p_buf_space_left)
+{
+	int					status = BCME_OK;
+	/* data from command line as 'src' */
+	unsigned long int	tmp_data_ul;
+	uint8				src_data_uint8;
+	uint16				src_data_uint16;
+	uint32				src_data_uint32;
+	struct ether_addr	src_data_mac = ether_null;
+	wl_proxd_intvl_t	src_data_intvl;
+	wl_proxd_tpk_t		src_data_tpk;
+
+	void		*p_src_data;
+	uint16	src_data_size;	/* size of data pointed by p_src_data as 'source' */
+	const ftm_config_param_info_t *p_config_param_info;
+
+	/* parse the cmd-line, scan thru all <param-name> <param-value> */
+	while (*argv != NULL) {
+		/* look up 'config-param-info' based on 'param-name' */
+		p_config_param_info = ftm_get_config_param_info(*argv, session_id);
+		if (p_config_param_info == (ftm_config_param_info_t *) NULL) {
+			printf("error: invalid param-name (%s)\n", *argv);
+			status = BCME_USAGE_ERROR;	/* param-name is not specified */
+			break;
+		}
+
+		/* parse 'param-value' */
+		if (*(argv + 1) == NULL) {
+			printf("error: invalid param-value\n");
+			status = BCME_USAGE_ERROR;	/* param-value is not specified */
+			break;
+		}
+		++argv;
+
+		/* parse param-value, setup tlv-data */
+		p_src_data = (void *) NULL;
+		src_data_size = 0;
+		switch (p_config_param_info->tlvid) {
+		case WL_PROXD_TLV_ID_BSS_INDEX:		/* uint8 */
+		case WL_PROXD_TLV_ID_NAN_MAP_ID:
+		case WL_PROXD_TLV_ID_FTM_REQ_RETRIES:
+		case WL_PROXD_TLV_ID_FTM_RETRIES:
+			src_data_uint8 = atoi(*argv);
+			p_src_data = (void *) &src_data_uint8;
+			src_data_size = sizeof(uint8);
+			break;
+
+		case WL_PROXD_TLV_ID_BURST_NUM_FTM:	/* uint16 */
+		case WL_PROXD_TLV_ID_NUM_BURST:
+		case WL_PROXD_TLV_ID_RX_MAX_BURST:
+			if ((status = ftm_config_parse_ul(argv, p_config_param_info,
+				(unsigned long int) 0, (unsigned long int) 0xffff,
+				&tmp_data_ul)) != BCME_OK)
+				break;
+			src_data_uint16 = htol16((uint16) tmp_data_ul);
+			p_src_data = (void *) &src_data_uint16;
+			src_data_size = sizeof(uint16);
+			break;
+
+		case WL_PROXD_TLV_ID_TX_POWER:		/* uint32 */
+		case WL_PROXD_TLV_ID_RATESPEC:
+		case WL_PROXD_TLV_ID_EVENT_MASK:	/* wl_proxd_event_mask_t/uint32 */
+		case WL_PROXD_TLV_ID_DEBUG_MASK:	/* allow in 0x######## format */
+			if ((status = ftm_config_parse_ul(argv, p_config_param_info,
+				(unsigned long int) 0, (unsigned long int) 0xffffffff,
+				&tmp_data_ul)) != BCME_OK)
+				break;
+			/* get the bitmask */
+			src_data_uint32 = htol32((uint32) tmp_data_ul);
+			p_src_data = &src_data_uint32;
+			src_data_size = sizeof(uint32);
+			break;
+
+		case WL_PROXD_TLV_ID_CHANSPEC:		/* chanspec_t --> 32bit */
+			status = ftm_config_parse_channel(*argv, &src_data_uint32);
+			if (status == BCME_OK) {
+				p_src_data = (void *) &src_data_uint32;
+				src_data_size = sizeof(uint32);
+			}
+			break;
+
+		case WL_PROXD_TLV_ID_BSSID:		/* mac address */
+		case WL_PROXD_TLV_ID_PEER_MAC:
+		case WL_PROXD_TLV_ID_DEV_ADDR:
+			src_data_mac = ether_null;
+			if (!wl_ether_atoe(*argv, &src_data_mac)) {
+				printf("error: invalid MAC address parameter\n");
+				status = BCME_USAGE_ERROR;
+				break;
+			}
+			p_src_data = &src_data_mac;
+			src_data_size = sizeof(src_data_mac);
+			break;
+
+		case WL_PROXD_TLV_ID_BURST_DURATION:	/* wl_proxd_intvl_t */
+		case WL_PROXD_TLV_ID_BURST_PERIOD:
+		case WL_PROXD_TLV_ID_BURST_FTM_SEP:
+		case WL_PROXD_TLV_ID_BURST_TIMEOUT:
+		case WL_PROXD_TLV_ID_INIT_DELAY:
+			status = ftm_config_parse_intvl(*argv, &src_data_intvl);
+			if (status == BCME_OK) {
+				p_src_data = (void *) &src_data_intvl;
+				src_data_size = sizeof(src_data_intvl);
+			}
+			break;
+
+		case WL_PROXD_TLV_ID_TPK:
+			status = ftm_config_parse_tpk_peer(*argv, &src_data_tpk);
+			if (status == BCME_OK) {
+				p_src_data = (void *) &src_data_tpk;
+				src_data_size = sizeof(src_data_tpk);
+			}
+			break;
+
+		default:
+			/* not supported now */
+			status = BCME_USAGE_ERROR;
+			break;
+		}
+
+		if (status != BCME_OK)
+			break;				/* abort */
+
+		status = bcm_pack_xtlv_entry((uint8 **) p_tlv, p_buf_space_left,
+			p_config_param_info->tlvid, src_data_size, p_src_data,
+			BCM_XTLV_OPTION_ALIGN32);
+		if (status != BCME_OK)
+		{
+#ifdef WL_FTM_DEBUG
+			printf("%s: bcm_pack_xltv_entry() failed, status=%d\n",
+				__FUNCTION__, status);
+#endif /* WL_FTM_DEBUG */
+			break;				/* abort */
+		}
+
+		argv++;	/* continue on next <param-name><param-value> */
+	}
+
+	return status;
+
+}
+
+/*
+* 'wl proxd ftm config' handler, there are two formats:
+* For options/flags config, use
+*        wl proxd ftm [<session-id>] config options { [+|-]<param-value> }+
+* for non-options/flags config, use
+*        wl proxd ftm [<session-id>] config [<param-name> <param-value>]+
+*/
+static int
+ftm_subcmd_config(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	ftm_config_category_t	category;
+	uint16 proxd_iovsize;
+	wl_proxd_iov_t *p_proxd_iov;
+	int status = BCME_OK;
+	uint16 bufsize;
+	wl_proxd_tlv_t *p_tlv;
+	uint16	buf_space_left;
+	uint16 all_tlvsize;
+
+	if (*argv == NULL) {
+		printf("error: config command requires parameters\n");
+		/* display 'proxd -h ftm config' helpmsg */
+		ftm_display_config_help();
+		return BCME_OK;	/* no need to show 'proxd'-level help */
+	}
+
+	/* allocate a buffer for proxd-ftm config via 'set' iovar */
+	p_proxd_iov = ftm_alloc_getset_buf(method, session_id,
+		p_subcmd_info->cmdid, FTM_IOC_BUFSZ, &proxd_iovsize);
+	if (p_proxd_iov == (wl_proxd_iov_t *) NULL)
+		return BCME_NOMEM;
+
+	/* setup TLVs */
+	bufsize = proxd_iovsize - WL_PROXD_IOV_HDR_SIZE;	/* adjust available size for TLVs */
+	p_tlv = &p_proxd_iov->tlvs[0];
+
+	/* TLV buffer starts with a full size, will decrement for each packed TLV */
+	buf_space_left = bufsize;
+
+	/* parse the cmd-line,  get the config-category and dispatch to the handler */
+	/* to parse the parameters based on the 'config-category' */
+	category = ftm_parse_config_category(*argv);
+	if (category == FTM_CONFIG_CAT_OPTIONS) {
+		/* for 'wl proxd ftm [session-id] config options' */
+		/* dispatch to setup TLVs for method/session options/flags */
+		status = ftm_handle_config_options(session_id, ++argv, &p_tlv,
+			&buf_space_left, session_id != WL_PROXD_SESSION_ID_GLOBAL ? FALSE : TRUE);
+	} else if (category == FTM_CONFIG_CAT_SESSION_OPTIONS) {
+		status = ftm_handle_config_options(session_id, ++argv, &p_tlv,
+			&buf_space_left, FALSE);
+	} else if (category == FTM_CONFIG_CAT_AVAIL) {
+		status = ftm_handle_config_avail(wl, p_proxd_iov, proxd_iovsize,
+			session_id, ++argv);
+	}
+	else
+		status = ftm_handle_config_general(session_id, argv, &p_tlv,
+			&buf_space_left);
+
+	if (status == BCME_OK && category != FTM_CONFIG_CAT_AVAIL) {
+		/* update the iov header, set len to include all TLVs + header */
+		all_tlvsize = (bufsize - buf_space_left);
+		p_proxd_iov->len = htol16(all_tlvsize + WL_PROXD_IOV_HDR_SIZE);
+		status = wlu_var_setbuf(wl, "proxd", p_proxd_iov,
+			all_tlvsize + WL_PROXD_IOV_HDR_SIZE);
+	}
+
+	if (status == BCME_USAGE_ERROR) {
+		if (category == FTM_CONFIG_CAT_OPTIONS)
+			ftm_display_config_options_help();
+		else if (category == FTM_CONFIG_CAT_AVAIL)
+			ftm_display_config_avail_help();
+		else
+			ftm_display_config_help();
+		status = BCME_OK;	/* reset to avoid showing 'proxd'-level help */
+	}
+
+	/* clean up */
+	free(p_proxd_iov);
+
+#ifdef WL_FTM_DEBUG
+	if (status != BCME_OK)
+		printf("error: exit %s, status = %d\n", __FUNCTION__, status);
+#endif /* WL_FTM_DEBUG */
+
+	return status;
+}
+
+static void
+ftm_display_cmd_help(const ftm_subcmd_info_t *p_subcmd_info,
+const char *cmd_params)
+{
+	if (p_subcmd_info == (ftm_subcmd_info_t *) NULL)
+		return;
+
+	if (p_subcmd_info->helpmsg == (char *) NULL)
+		return;
+
+	/* print help messages for a specific FTM sub-command */
+	printf("\n\t%s\n", p_subcmd_info->helpmsg);
+
+	/* display cmd usage (these commands require no parameters) */
+	printf("\tUsage: wl proxd ftm ");
+	if (p_subcmd_info->cmdflag & FTM_SUBCMD_FLAG_SESSION) {
+		if (p_subcmd_info->cmdflag & FTM_SUBCMD_FLAG_METHOD)
+			printf("[<session-id>] ");
+		else
+			printf("<session-id> ");
+	}
+	printf("%s%s\n\n",
+		p_subcmd_info->name, cmd_params ? cmd_params : "");
+
+}
+
+/*
+* pack tlvs for 'wl proxd ftm start-ranging [-d] <sid1> <sid2> ...'
+*   parse cmd-line, setup TLVs in caller provided buffer,
+*   adjusted buffer-space if applies.
+* This function is invoked from ftm_subcmd_start_ranging().
+*/
+static int
+ftm_pack_sids_from_cmdarg(char **argv,
+	wl_proxd_tlv_t **p_tlv, uint16 *p_buf_space_left)
+{
+	char		**tmp_argv;
+	uint16		num_sids;
+	int			err = BCME_OK;
+	uint16		ranging_sids_size;
+	wl_proxd_session_id_list_t *ranging_sids = NULL;
+	wl_proxd_session_id_t sid;
+	uint16		count;
+
+	/* figout out number of session-id from the input */
+	tmp_argv = argv;
+	num_sids = 0;
+	while (*tmp_argv != NULL) {
+		tmp_argv++;
+		num_sids++;
+	}
+	if (num_sids == 0) {
+		err = BCME_USAGE_ERROR;
+		goto done;
+	}
+
+	/* allocate a temp buffer for parsing cmd-args */
+	ranging_sids_size = OFFSETOF(wl_proxd_session_id_list_t, ids) +
+		num_sids * sizeof(wl_proxd_session_id_t);
+	ranging_sids = calloc(1, ranging_sids_size);
+	if (ranging_sids == (wl_proxd_session_id_list_t *) NULL) {
+		printf("error: failed to allocate %d bytes of memory for ranging\n",
+			ranging_sids_size);
+		err = BCME_NOMEM;
+		goto done;
+	}
+
+	/* get session-ids followed 'wl proxd ftm start-ranging [-d]' */
+	count = 0;
+	while (*argv != NULL) {
+		sid = (uint16) atoi(*argv);
+		ranging_sids->ids[count++] = htol16(sid);
+		argv++;			/* continue on next session-id */
+	}
+
+	ranging_sids->num_ids = htol16(num_sids);
+	err = bcm_pack_xtlv_entry((uint8 **) p_tlv, p_buf_space_left,
+		WL_PROXD_TLV_ID_SESSION_ID_LIST, ranging_sids_size,
+		(uint8 *)ranging_sids, BCM_XTLV_OPTION_ALIGN32);
+
+	if (err != BCME_OK) {
+		printf("%s: failed to pack ranging-ids in xtlv, err=%d\n",
+			__FUNCTION__, err);
+		goto done;
+	}
+
+done:
+	/* clean up */
+	if (ranging_sids)
+		free(ranging_sids);
+
+	return err;
+}
+
+/*
+* pack tlvs for 'wl proxd ftm start-ranging [-d] <sid1> <sid2> ...'
+*   parse cmd-line, setup TLVs in caller provided buffer,
+*   adjusted buffer-space if applies.
+* This function is invoked from ftm_subcmd_start_ranging().
+*/
+static int
+ftm_pack_ranging_config_from_cmdarg(char **argv,
+wl_proxd_tlv_t **p_tlv, uint16 *p_buf_space_left)
+{
+	int			err = BCME_OK;
+	wl_proxd_ranging_flags_t		flags;
+	wl_proxd_ranging_flags_t		flags_mask;
+
+	/* parse the ranging-flags '-d' followed 'wl proxd ftm start-ranging' if available */
+	flags = WL_PROXD_RANGING_FLAG_NONE;
+	while (*argv != NULL) {
+		if (stricmp(*argv, "-d") != 0)
+			break;	/* skip to handle 'sids' arguments */
+
+		flags = WL_PROXD_RANGING_FLAG_DEL_SESSIONS_ON_STOP;
+		argv++;			/* continue on next session-id */
+	}
+
+	/* pack ranging-flags/mask in xTLVs if provided */
+	if (flags != WL_PROXD_RANGING_FLAG_NONE) {
+		/* setup ranging flags TLV */
+		err = bcm_pack_xtlv_entry((uint8 **) p_tlv, p_buf_space_left,
+			WL_PROXD_TLV_ID_RANGING_FLAGS,
+			sizeof(uint16), (uint8 *)&flags, BCM_XTLV_OPTION_ALIGN32);
+		if (err != BCME_OK) {
+			printf("%s: failed to pack ranging-flags in xtlv, err=%d\n",
+				__FUNCTION__, err);
+			goto done;				/* abort */
+		}
+
+		/* setup ranging flags_mask TLV */
+		flags_mask = WL_PROXD_RANGING_FLAG_ALL;
+		err = bcm_pack_xtlv_entry((uint8 **) p_tlv, p_buf_space_left,
+			WL_PROXD_TLV_ID_RANGING_FLAGS_MASK,
+			sizeof(uint16), (uint8 *)&flags_mask, BCM_XTLV_OPTION_ALIGN32);
+		if (err != BCME_OK) {
+			printf("%s: failed to pack ranging flags_mask in xtlv, err=%d\n",
+				__FUNCTION__, err);
+			goto done;				/* abort */
+		}
+	}
+
+	/* parse the 'sids' followed 'wl proxd ftm start-ranging [-d]' and
+	* pack the parameters in xTLVs if available
+	*/
+	err = ftm_pack_sids_from_cmdarg(argv, p_tlv, p_buf_space_left);
+
+done:
+	if (err != BCME_OK)
+		printf("%s failed, err = %d\n",
+		__FUNCTION__, err);
+	return err;
+}
+
+/*
+* 'wl proxd ftm start-ranging' handler
+*        wl proxd ftm start-ranging [-d] <sid1> <sid2> ...
+*/
+static int
+ftm_subcmd_start_ranging(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	wl_proxd_iov_t *p_proxd_iov = NULL;
+	uint16 proxd_iovsize;
+	uint16 bufsize;
+	wl_proxd_tlv_t *p_tlv;
+	uint16	buf_space_left;
+	int err = BCME_OK;
+	uint16 all_tlvsize;
+
+	UNUSED_PARAMETER(wl);
+
+	/* this should apply to a method command */
+	if (*argv == NULL || session_id != WL_PROXD_SESSION_ID_GLOBAL) {
+		printf("error: start-ranging command requires parameters\n");
+		err = BCME_USAGE_ERROR;
+		goto done;
+	}
+
+	/* allocate a buffer for proxd-ftm config via 'set' iovar */
+	p_proxd_iov = ftm_alloc_getset_buf(method, session_id,
+		p_subcmd_info->cmdid, FTM_IOC_BUFSZ, &proxd_iovsize);
+	if (p_proxd_iov == (wl_proxd_iov_t *) NULL) {
+		err = BCME_NOMEM;
+		goto done;
+	}
+
+	/* setup TLVs */
+	bufsize = proxd_iovsize - WL_PROXD_IOV_HDR_SIZE;	/* adjust available size for TLVs */
+	p_tlv = &p_proxd_iov->tlvs[0];
+
+	/* TLV buffer starts with a full size, will decrement for each packed TLV */
+	buf_space_left = bufsize;
+
+	/* parse the cmd-line, pack the parameters in TLVs */
+	err = ftm_pack_ranging_config_from_cmdarg(argv, &p_tlv,
+		&buf_space_left);
+	if (err != BCME_OK)
+		goto done;
+
+	/* update the iov header, set len to include all TLVs + header */
+	all_tlvsize = (bufsize - buf_space_left);
+	p_proxd_iov->len = htol16(all_tlvsize + WL_PROXD_IOV_HDR_SIZE);
+	err = wlu_var_setbuf(wl, "proxd", p_proxd_iov,
+		all_tlvsize + WL_PROXD_IOV_HDR_SIZE);
+
+done:
+	/* clean up */
+	if (p_proxd_iov)
+		free(p_proxd_iov);
+
+	if (err == BCME_USAGE_ERROR) {
+		/* display 'proxd -h ftm' helpmsg */
+		ftm_display_cmd_help(p_subcmd_info, "[-d] <sid1> <sid2> ...");
+		err = BCME_OK;	/* reset to avoid showing 'proxd'-level help */
+	}
+
+	return err;
+}
+
+/*
+* 'wl proxd ftm stop-ranging' handler,
+*        wl proxd ftm stop-ranging
+*/
+static int
+ftm_subcmd_stop_ranging(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	/* this should apply to a method command */
+	if (session_id != WL_PROXD_SESSION_ID_GLOBAL) {
+		printf("error: no session-id is allowed for stop-ranging\n");
+		/* display 'proxd -h ftm stop-ranging ' helpmsg */
+		ftm_display_cmd_help(p_subcmd_info, "");
+		return BCME_OK;	/* no need to show 'proxd'-level help */
+	}
+
+	/* issue an iovar call */
+	return ftm_subcmd_setiov_no_tlv(wl, p_subcmd_info, method, session_id, argv);
+}
+
+/*
+* display help-messages for 'wl proxd -h ftm'
+*/
+static void
+ftm_display_method_help()
+{
+	int i;
+	int max_cmdname_len = 20;
+	const ftm_subcmd_info_t *p_subcmd_info;
+
+	/* a header */
+	printf("\n\tProximity Detection using FTM\n");
+	printf("\tUsage: wl proxd ftm [<session-id>] <cmd> [<param-name> <param-value>]*\n");
+	printf("\t\t<session-id>: specify a session; If omitted, <cmd> applies to FTM method\n");
+	printf("\t\t<cmd>: specify a command from the following list,\n");
+
+	/* show the command list and the help messages for each FTM command */
+	p_subcmd_info = &ftm_cmdlist[0];
+	for (i = 0; i < (int) ARRAYSIZE(ftm_cmdlist); i++) {
+		printf("\t\t  %*s: %s\n", max_cmdname_len, p_subcmd_info->name,
+			p_subcmd_info->helpmsg);
+		p_subcmd_info++;
+	}
+
+	printf("\t\t<param-name> <param-value>: <cmd>-specific parameters\n\n");
+
+	printf("\t\ttype 'wl proxd -h ftm config' for configuration command usage.\n");
+	printf("\t\ttype 'wl proxd -h ftm config options' "
+		"for options-configuration command usage.\n");
+	printf("\t\ttype 'wl proxd -h ftm config avail' "
+		"for availability-configuration command usage.\n");
+	printf("\t\ttype 'wl proxd -h ftm <cmd>' for others command usage.\n\n");
+
+	/* show examples */
+	printf("\tExample: wl proxd ftm enable\n\n");
+
+	return;
+}
+
+/*
+* display help-messages for 'wl proxd -h ftm config'
+*/
+static void
+ftm_display_config_help()
+{
+	int i;
+	int max_param_name_len = 20;
+	const ftm_config_param_info_t *p_config_param_info;
+
+	/* a header */
+	printf("\n\tConfigure Proximity Detection using FTM\n");
+	printf("\tUsage: wl proxd ftm [<session-id>] config { <param-name> <param-value> }+ \n");
+	printf("\t\t<session-id>: specify a session id; If omitted, configure global items\n");
+	/* print helpmsg for each config-item */
+	printf("\t\t<param-name> <param-value>: configuration parameters from the following\n");
+	p_config_param_info = &ftm_config_param_info[0];
+	for (i = 0; i < (int) ARRAYSIZE(ftm_config_param_info); i++) {
+		printf("\t\t  %*s: %s\n", max_param_name_len, p_config_param_info->name,
+			p_config_param_info->name_helpmsg);
+
+		p_config_param_info++;
+	}
+
+	/* show examples */
+	printf("\n\tExample: wl proxd ftm config retries 10\n");
+	printf("\t         wl proxd ftm 1 config retries 10\n");
+}
+
+/*
+* display help-messages for 'wl proxd -h ftm config options'
+*/
+static void
+ftm_display_config_options_help()
+{
+	int i;
+	int max_option_name_len = 20;
+	const ftm_config_options_info_t	*p_config_options_info;
+
+	/* a header */
+	printf("\n\tConfigure-Options Proximity Detection using FTM\n");
+	printf("\tUsage: wl proxd ftm [<session-id>] config options { [+|-]<param-value> }+ \n");
+	printf("\t\t<session-id>: specify a session id; If omitted, set the global options\n");
+	printf("\t\t+|- prefix: to add or remove an option\n");
+	printf("\t\t<param-value>: specify an option\n");
+
+	/* print helpmsg for each global option flag */
+	printf("\t\t\tConfigurable options for a FTM method:\n");
+	p_config_options_info = &ftm_method_options_info[0];
+	for (i = 0; i < (int) ARRAYSIZE(ftm_method_options_info); i++) {
+		printf("\t\t  %*s (0x%08x): %s\n", max_option_name_len,
+			p_config_options_info->param_value_str,
+			p_config_options_info->flags, p_config_options_info->helpmsg);
+		p_config_options_info++;
+	}
+
+	/* print helpmsg for each session option flag */
+	printf("\n\t\t\tConfigurable options for a specific session:\n");
+	p_config_options_info = &ftm_session_options_info[0];
+	for (i = 0; i < (int) ARRAYSIZE(ftm_session_options_info); i++) {
+		printf("\t\t  %*s (0x%08x): %s\n", max_option_name_len,
+			p_config_options_info->param_value_str,
+			p_config_options_info->flags, p_config_options_info->helpmsg);
+		p_config_options_info++;
+	}
+
+	/* show examples */
+	printf("\n\tExample: wl proxd ftm config options +rx-enable\n");
+	printf("\t         wl proxd ftm config options +0x00000001\n");
+	printf("\t         wl proxd ftm 1 config options +rx-auto-burst -rtt-detail\n\n");
+
+	return;
+}
+
+/*
+* display help-messages for 'wl proxd -h ftm config avail'
+*/
+static void
+ftm_display_config_avail_help()
+{
+	/* a header */
+	printf("\n\tConfigure-availability Proximity Detection using FTM\n");
+	printf("\t\tUsage: wl proxd ftm [<session-id>] config avail\n");
+	printf("\t\t      { [time-ref] none |\n");
+	printf("\t\t        time-ref <timeref-value> repeat <repeat-tmu> slot {<slot-value>}+ }\n");
+	printf("\t\t<session-id>: a session id; If omitted, set the local availability\n");
+	printf("\t\t              otherwise, set the peer availability\n");
+	printf("\t\tnone or time-ref none: to clear availability\n");
+	printf("\t\t<timeref-value>: a timer reference. Possible values are:\n");
+	printf("\t\t              dev-tsf | nan-dw | tbtt\n");
+	printf("\t\t<repeat-tmu>: repeat period in time-interval format\n");
+	printf("\t\t<slot-value>: a time slot in channel:start-tmu:duration-tmu\n");
+	printf("\t\t              channel   -- a channel (see 'wl chanspec')\n");
+	printf("\t\t              start-tmu -- start time in time-interval format\n");
+	printf("\t\t                           (a number followed by a time unit)\n");
+	printf("\t\t              duration-tmu -- duration in time-interval format\n");
+	printf("\t\t              Time uints are:\n");
+	printf("\t\t                s (seconds) | ms (milliseconds) | us (microseconds)\n");
+	printf("\t\t                ns (nanoseconds) | ps (picoseconds) | tu (for TUs,default)\n");
+	printf("\t\tMore than one <slot-value>' can be specified for setting\n");
+	printf("\t\tmultiple time slots\n");
+
+	/* show examples */
+	printf("\n\tExample: wl proxd ftm config avail none\n");
+	printf("\t         wl proxd ftm config avail time-ref dev-tsf slot 11:100s:100tu\n");
+	printf("\t         wl proxd ftm 1 config avail time-ref dev-tsf slot 11:200s:300tu");
+	printf(" 11:600s:400tu\n");
+
+	return;
+}
+
+/*
+* handle
+*        wl proxd -h
+*        wl proxd -h ftm
+*        wl proxd -h ftm <cmd>
+*        wl proxd -h ftm config options
+* Output:
+*        BCME_USAGE_ERROR -- caller should bring up 'proxd' level help messages
+*        BCME_OK          -- this func displays context-help for FTM method,
+*                            caller does not need to show any help messages.
+*/
+static int
+ftm_handle_help(char **argv)
+{
+	const ftm_subcmd_info_t *p_subcmd_info;
+
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	if (stricmp(*argv, "ftm") != 0)	/* check 'wl proxd -h ftm' */
+		return BCME_USAGE_ERROR;
+
+	++argv;
+	if (*argv == NULL) {
+		/* show help messages for 'wl proxd -h ftm' */
+		ftm_display_method_help();
+		return BCME_OK;
+	}
+
+	/* parse 'wl proxd -h ftm <cmd>' */
+	p_subcmd_info = ftm_get_subcmd_info(*argv);
+	if (p_subcmd_info != NULL) {
+		if (p_subcmd_info->cmdid == WL_PROXD_CMD_CONFIG) {
+			/* help for 'wl proxd -h ftm config' */
+			++argv;
+			if (*argv != NULL) {		/* parse 'wl proxd -h ftm config options' */
+				if (stricmp(*argv, "options") == 0) {
+					/* display help for 'wl proxd -h ftm config options' */
+					ftm_display_config_options_help();
+					return BCME_OK;
+				}
+				if (stricmp(*argv, "avail") == 0) {
+					/* display help for 'wl proxd -h ftm config avail' */
+					ftm_display_config_avail_help();
+					return BCME_OK;
+				}
+			}
+
+			/* display help for 'wl proxd -h ftm config' */
+			ftm_display_config_help();
+			return BCME_OK;
+
+		}
+		else {
+			/* print help messages for a specific FTM sub-command */
+			ftm_display_cmd_help(p_subcmd_info, "");
+			return BCME_OK;
+		}
+	}
+
+	/* invalid <cmd>, display help messages for FTM method */
+	ftm_display_method_help();
+	return BCME_OK;
+}
+
+static const ftm_strmap_entry_t ftm_event_type_loginfo[] = {
+	/* wl_proxd_event_type_t,			text-string */
+	{ WL_PROXD_EVENT_NONE,				"none" },
+	{ WL_PROXD_EVENT_SESSION_CREATE,	"session create" },
+	{ WL_PROXD_EVENT_SESSION_START,		"session start" },
+	{ WL_PROXD_EVENT_FTM_REQ,			"FTM req" },
+	{ WL_PROXD_EVENT_BURST_START,		"burst start" },
+	{ WL_PROXD_EVENT_BURST_END,			"burst end" },
+	{ WL_PROXD_EVENT_SESSION_END,		"session end" },
+	{ WL_PROXD_EVENT_SESSION_RESTART,	"session restart" },
+	{ WL_PROXD_EVENT_BURST_RESCHED,		"burst rescheduled" },
+	{ WL_PROXD_EVENT_SESSION_DESTROY,	"session destroy" },
+	{ WL_PROXD_EVENT_RANGE_REQ,			"range request" },
+	{ WL_PROXD_EVENT_FTM_FRAME,			"FTM frame" },
+	{ WL_PROXD_EVENT_DELAY,				"delay" },
+	{ WL_PROXD_EVENT_VS_INITIATOR_RPT,	"initiator-report " }, /* rx initiator-rpt */
+	{ WL_PROXD_EVENT_RANGING,			"ranging " },
+	{ WL_PROXD_EVENT_LCI_MEAS_REP,		"LCI measurement report" },
+	{ WL_PROXD_EVENT_CIVIC_MEAS_REP,	"civic measurement report" },
+	{ WL_PROXD_EVENT_START_WAIT,		"start wait" },
+};
+
+#if defined(linux)
+static const ftm_strmap_entry_t*
+ftm_get_event_type_loginfo(wl_proxd_event_type_t	event_type)
+{
+	/* look up 'event-type' from a predefined table  */
+	return ftm_get_strmap_info((int32) event_type,
+		ftm_event_type_loginfo, ARRAYSIZE(ftm_event_type_loginfo));
+}
+
+/*
+* check FTM event
+*    return -1: if event's version does not match. In this case,
+*				caller should continue the event checking.
+*    return 0: this func reports receving a new-version FTM-event and
+*				caller should skip the checking for this event.
+*/
+static int
+ftm_event_check(bcm_event_t *p_bcm_event)
+{
+	int status;
+	wl_proxd_event_t	*p_event;
+	uint16 version;
+	wl_proxd_event_type_t event_type;
+	const ftm_strmap_entry_t *p_loginfo;
+	int tlvs_len;
+
+	/* move to bcm event payload, which is proxd event structure */
+	p_event = (wl_proxd_event_t *) (p_bcm_event + 1);
+	version = ltoh16(p_event->version);
+	if (version < WL_PROXD_API_VERSION) {
+#ifdef WL_FTM_DEBUG
+		printf("ignore non-ftm event version = 0x%x < WL_PROXD_API_VERSION (0x%x)\n",
+			version, WL_PROXD_API_VERSION);
+#endif /* WL_FTM_DEBUG */
+		return -1;	/* let caller handle the old version */
+	}
+
+	event_type = (wl_proxd_event_type_t) ltoh16(p_event->type);
+#ifdef WL_FTM_DEBUG
+	printf("event_type=0x%x, ntoh16()=0x%x, ltoh16()=0x%x",
+		p_event->type, ntoh16(p_event->type), ltoh16(p_event->type));
+#endif /* WL_FTM_DEBUG */
+	p_loginfo = ftm_get_event_type_loginfo(event_type);
+	if (p_loginfo == NULL) {
+		printf("receive an invalid FTM event %d\n", event_type);
+		return 0;					/* ignore this event */
+	}
+
+	/* get TLVs len, skip over event header */
+	tlvs_len = ltoh16(p_event->len) - OFFSETOF(wl_proxd_event_t, tlvs);
+	printf("receive '%s' event: version=0x%x len=%d method=%s sid=%d tlvs_len=%d\n",
+		p_loginfo->text,
+		version,
+		ltoh16(p_event->len),
+		ftm_method_value_to_logstr(ltoh16(p_event->method)),
+		ltoh16(p_event->sid),
+		tlvs_len);
+
+	/* print event contents TLVs */
+	if (tlvs_len > 0) {
+		/* unpack TLVs and invokes the cbfn to print the event content TLVs */
+		status = bcm_unpack_xtlv_buf((void *) NULL, (uint8 *)&p_event->tlvs[0],
+			tlvs_len, BCM_XTLV_OPTION_ALIGN32, ftm_unpack_xtlv_cbfn);
+		if (status != BCME_OK)
+			printf("Failed to unpack xtlv for an event\n");
+	}
+
+	return 0; /* indicate we have processed this FTM event */
+}
+#endif /* linux */
+#ifdef WL_FTM_DEBUG
+/*
+* Format an 'event' bitmask to a text-string to caller-provided buffer
+*/
+static void
+ftm_format_event_mask(wl_proxd_event_type_t event, char *p_strbuf, int bufsize)
+{
+	int i, nChars;
+	int event_enabled_count = 0;
+
+	memset(p_strbuf, 0, bufsize);
+
+	char *p_tmpbuf = p_strbuf;
+	const ftm_strmap_entry_t *p_loginfo = &ftm_event_type_loginfo[0];
+	for (i = 0; i < (int) ARRAYSIZE(ftm_event_type_loginfo); i++) {
+		if (WL_PROXD_EVENT_ENABLED(event, (wl_proxd_event_type_t) p_loginfo->id)) {
+			if (event_enabled_count == 0) {
+				if ((nChars = snprintf(p_tmpbuf, bufsize, "(")) < 0)
+					return;	/* error, ignore */
+				bufsize -= nChars;
+				p_tmpbuf += nChars;
+			}
+
+			nChars = snprintf(p_tmpbuf, bufsize, "'%s' ", p_loginfo->text);
+			if (nChars < 0)
+				return;			/* abort if error */
+			bufsize -= nChars;
+			p_tmpbuf += nChars;
+			event_enabled_count++;
+		}
+		p_loginfo++;
+	}
+
+	if (event_enabled_count > 0)
+		snprintf(p_tmpbuf, bufsize, ")");
+}
+#endif /* WL_FTM_DEBUG */
+
+/*
+* 'wl proxd ftm tune' handler,
+*	wl proxd ftm tune
+*/
+static int
+ftm_handle_tune_options(char **argv, wl_proxd_tlv_t **p_tlv, uint16 *p_buf_space_left,
+	wl_proxd_params_tof_tune_t *tof_tune)
+{
+	miniopt_t to;
+	int opt_err;
+	int ret = BCME_USAGE_ERROR;
+
+	if (*argv == NULL)
+		return BCME_USAGE_ERROR;
+
+	miniopt_init(&to, "tune", NULL, FALSE);
+	while ((opt_err = miniopt(&to, argv)) != -1) {
+		if (opt_err == 1) {
+			return BCME_USAGE_ERROR;
+		}
+		argv += to.consumed;
+		ret = proxd_tune_set_param_from_opt("proxd ftm tune", &to, tof_tune);
+	}
+#ifdef WL_FTM_DEBUG
+	prhex("tune_opt", (uint8*)tof_tune, sizeof(wl_proxd_params_tof_tune_t));
+#endif /* WL_FTM_DEBUG */
+	ret = bcm_pack_xtlv_entry((uint8 **)p_tlv, p_buf_space_left,
+		WL_PROXD_TLV_ID_TUNE, sizeof(wl_proxd_params_tof_tune_t), (uint8*)tof_tune,
+		BCM_XTLV_OPTION_ALIGN32);
+	if (ret != BCME_OK) {
+		printf("%s: failed to pack proxd ftm tune in xtlv, err=%d\n",
+			__FUNCTION__, ret);
+		return ret;
+	}
+
+	return BCME_OK;
+}
+
+/* Used for getting the current options before setting the new ones only */
+static int
+ftm_tune_cbfn(void *ctx, const uint8 *p_data, uint16 tlvid, uint16 len)
+{
+	wl_proxd_params_tof_tune_t *tunep = (wl_proxd_params_tof_tune_t *)ctx;
+
+	if (tlvid == WL_PROXD_TLV_ID_TUNE) {
+#ifdef WL_FTM_DEBUG
+		prhex("ftm_tune_cbbn", p_data, len);
+#endif /* WL_FTM_DEBUG */
+		if (len < sizeof(wl_proxd_params_tof_tune_t)) {
+			/* FW has older version */
+			memcpy(&tunep->Ki, p_data, len);
+		} else {
+			memcpy(tunep, p_data, sizeof(wl_proxd_params_tof_tune_t));
+		}
+	}
+	return BCME_OK;
+}
+
+static int
+ftm_subcmd_tune(void *wl, const ftm_subcmd_info_t *p_subcmd_info,
+	wl_proxd_method_t method, wl_proxd_session_id_t session_id, char **argv)
+{
+	uint16 proxd_tune_method;
+	uint16 proxd_iovsize;
+	wl_proxd_iov_t *p_proxd_iov, *p_iovresp;
+	uint16 bufsize;
+	wl_proxd_tlv_t *p_tlv;
+	uint16 buf_space_left;
+	uint16 all_tlvsize = 0;
+	int ret = BCME_OK;
+	wl_proxd_params_tof_tune_t	tof_tune;	/* TOF tune parameters */
+	memset(&tof_tune, 0, sizeof(tof_tune));
+
+	/* this should apply to a method command */
+	if (session_id != WL_PROXD_SESSION_ID_GLOBAL) {
+		printf("error: no session-id is allowed for tune\n");
+		return BCME_OK;
+	}
+
+	/* skip the command name and check if mandatory exists */
+	if (!*argv) {
+		fprintf(stderr, "missing mandatory parameter \'method\'\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* parse method */
+	proxd_tune_method = (uint16)atoi(argv[0]);
+	if (proxd_tune_method == 0) {
+		fprintf(stderr, "invalid parameter \'method\'\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* only supports PROXD_TOF_METHOD */
+	if (proxd_tune_method == PROXD_RSSI_METHOD)
+		return BCME_OK;
+
+	if (!*++argv) {
+		/* get */
+		return ftm_common_getcmd_handler(wl, p_subcmd_info, method, session_id, argv);
+	} else {
+		/* allocate iovar getset buffer */
+		p_proxd_iov = ftm_alloc_getset_buf(method, session_id,
+			p_subcmd_info->cmdid, sizeof(wl_proxd_params_tof_tune_t),
+				&proxd_iovsize);
+		if (p_proxd_iov == (wl_proxd_iov_t *) NULL)
+			return BCME_NOMEM;
+		bufsize = proxd_iovsize - WL_PROXD_IOV_HDR_SIZE;
+		p_tlv = &p_proxd_iov->tlvs[0];
+		buf_space_left = bufsize;
+
+		/* get current tune params */
+		ret = wlu_var_getbuf(wl, "proxd", p_proxd_iov, proxd_iovsize,
+			(void *)&p_iovresp);
+		if (ret != BCME_OK) {
+#ifdef WL_FTM_DEBUG
+			printf("%s: failed to send getbuf proxd iovar, status=%d\n",
+				__FUNCTION__, ret);
+#endif /* WL_FTM_DEBUG */
+			goto done;
+		}
+		if (p_iovresp != NULL) {
+			int tlvs_len = ltoh16(p_iovresp->len) - WL_PROXD_IOV_HDR_SIZE;
+			if (tlvs_len > 0) {
+				ret = bcm_unpack_xtlv_buf(&tof_tune, (uint8 *)p_iovresp->tlvs,
+					tlvs_len, BCM_XTLV_OPTION_ALIGN32, ftm_tune_cbfn);
+			}
+		}
+
+		/* handle options */
+		ret = ftm_handle_tune_options(argv, &p_tlv, &buf_space_left, &tof_tune);
+		if (ret == BCME_OK) {
+			/* prep to transport xtlv */
+			all_tlvsize = bufsize - buf_space_left;
+			p_proxd_iov->len = htol16(all_tlvsize + WL_PROXD_IOV_HDR_SIZE);
+			ret = wlu_var_setbuf(wl, "proxd", p_proxd_iov,
+				all_tlvsize + WL_PROXD_IOV_HDR_SIZE);
+		}
+	}
+
+done:
+	/* clean up */
+	free(p_proxd_iov);
+#ifdef wL_FTM_DEBUG
+	if (ret != BCME_OK)
+		printf("error: exit %s, status = %d\n", __FUNCTION__, ret);
+#endif /* WL_FTM_DEBUG */
+
+	return ret;
+}
+
+static int
+proxd_tune_display(wl_proxd_params_tof_tune_t *tof_tune, uint16 len)
+{
+	int err = BCME_OK;
+	int i, version = 0;
+
+	if (!tof_tune)
+		return err;
+
+	printf("Ki=%d \n", dtoh32(tof_tune->Ki));
+	printf("Kt=%d \n", dtoh32(tof_tune->Kt));
+	printf("vhtack=%d \n", dtoh16(tof_tune->vhtack));
+	printf("seq_en=%d\n", dtoh16(tof_tune->seq_en));
+	printf("core=%d\n", tof_tune->core);
+	printf("sw_adj=%d\n", dtoh16(tof_tune->sw_adj));
+	printf("hw_adj=%d\n", dtoh16(tof_tune->hw_adj));
+	printf("minDT = %d\n", tof_tune->minDT);
+	printf("maxDT = %d\n", tof_tune->maxDT);
+	printf("threshold_log2=%d %d %d seqtx %d seqrx %d 2g %d seqtx5g20 %d"
+		" seqrx5g20 %d seqtx2g20 %d seqrx2g20 %d\n",
+		dtoh16(tof_tune->N_log2[TOF_BW_20MHZ_INDEX]),
+		dtoh16(tof_tune->N_log2[TOF_BW_40MHZ_INDEX]),
+		dtoh16(tof_tune->N_log2[TOF_BW_80MHZ_INDEX]),
+		dtoh16(tof_tune->N_log2[TOF_BW_SEQTX_INDEX]),
+		dtoh16(tof_tune->N_log2[TOF_BW_SEQRX_INDEX]),
+		dtoh16(tof_tune->N_log2_2g),
+		dtoh16(tof_tune->seq_5g20.N_tx_log2),
+		dtoh16(tof_tune->seq_5g20.N_rx_log2),
+		dtoh16(tof_tune->seq_2g20.N_tx_log2),
+		dtoh16(tof_tune->seq_2g20.N_rx_log2));
+	printf("threshold_scale=%d %d %d seqtx %d seqrx %d 2g %d seqtx5g20 %d"
+		" seqrx5g20 %d seqtx2g20 %d seqrx2g20 %d\n",
+		dtoh16(tof_tune->N_scale[TOF_BW_20MHZ_INDEX]),
+		dtoh16(tof_tune->N_scale[TOF_BW_40MHZ_INDEX]),
+		dtoh16(tof_tune->N_scale[TOF_BW_80MHZ_INDEX]),
+		dtoh16(tof_tune->N_scale[TOF_BW_SEQTX_INDEX]),
+		dtoh16(tof_tune->N_scale[TOF_BW_SEQRX_INDEX]),
+		dtoh16(tof_tune->N_scale_2g),
+		dtoh16(tof_tune->seq_5g20.N_tx_scale),
+		dtoh16(tof_tune->seq_5g20.N_rx_scale),
+		dtoh16(tof_tune->seq_2g20.N_tx_scale),
+		dtoh16(tof_tune->seq_2g20.N_rx_scale));
+	printf("total_frmcnt=%d \n", tof_tune->totalfrmcnt);
+	printf("reserve_media=%d \n", tof_tune->rsv_media);
+	printf("flags=0x%x \n", dtoh16(tof_tune->flags));
+	for (i = 0; i < TOF_BW_NUM; i++) {
+		printf("window length %dMHz = %d\n",
+			(20 << i), tof_tune->w_len[i]);
+		printf("window offset %dMHz = %d\n",
+			(20 << i), tof_tune->w_offset[i]);
+	}
+	printf("seq window length 5G-20MHz = %2d 2G-20MHz = %2d\n",
+		tof_tune->seq_5g20.w_len,
+		tof_tune->seq_2g20.w_len);
+	printf("seq window offset 5G-20MHz = %2d 2G-20MHz = %2d\n",
+		tof_tune->seq_5g20.w_offset,
+		tof_tune->seq_2g20.w_offset);
+	printf("frame count=%d %d %d seq %d\n",
+		tof_tune->ftm_cnt[TOF_BW_20MHZ_INDEX],
+		tof_tune->ftm_cnt[TOF_BW_40MHZ_INDEX],
+		tof_tune->ftm_cnt[TOF_BW_80MHZ_INDEX],
+		tof_tune->ftm_cnt[TOF_BW_SEQTX_INDEX]);
+
+	if (len == sizeof(wl_proxd_params_tof_tune_t)) {
+		version = dtoh32(tof_tune->version);
+		switch (version) {
+		case WL_PROXD_TUNE_VERSION_1:
+			printf("bitflip threshold=%u\n", dtoh16(tof_tune->bitflip_thresh));
+			printf("SNR threshold=%u\n", dtoh16(tof_tune->snr_thresh));
+			printf("2G receive sensitivity threshold=%d\n", tof_tune->recv_2g_thresh);
+			printf("ACS GDV threshold=%u\n", dtoh32(tof_tune->acs_gdv_thresh));
+			printf("ACS RSSI threshold=%d\n", tof_tune->acs_rssi_thresh);
+			printf("Smoothing window enable=%u\n", tof_tune->smooth_win_en);
+			break;
+		default:
+			break;
+		}
+	}
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_randmac.c b/wl/src/wl/exe/wluc_randmac.c
new file mode 100644
index 0000000..01cd0e8
--- /dev/null
+++ b/wl/src/wl/exe/wluc_randmac.c
@@ -0,0 +1,807 @@
+/*
+ * wl randmac command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id$
+ */
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifdef WIN32
+#define bzero(b, len)   memset((b), 0, (len))
+#endif
+
+#ifdef LINUX
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* LINUX */
+
+#include <miniopt.h>
+#include <errno.h>
+
+#define RANDMAC_IOC_BUFSZ				2048
+#define WL_RANDMAC_IOV_VERSION_SIZE		(sizeof(wl_randmac_version_t))
+#define WL_RANDMAC_IOV_CONFIG_SIZE		(sizeof(wl_randmac_config_t))
+#define WL_RANDMAC_IOV_STATS_SIZE		(sizeof(wl_randmac_stats_t))
+
+static cmd_func_t wl_randmac;
+
+typedef struct randmac_subcmd_info randmac_subcmd_info_t;
+typedef int (randmac_subcmd_handler_t)(void *wl, const randmac_subcmd_info_t *p_subcmd_info,
+	char **argv);
+
+struct randmac_subcmd_info {
+	char						*name;	/* subcmd-name */
+	wl_randmac_subcmd_t			subcmd_id;	/* id */
+	wl_randmac_method_t			method;
+	randmac_subcmd_handler_t	*handler;		/* subcmd handler */
+	char				*helpmsg;	/* message for wl randmac -h config */
+};
+
+typedef struct randmac_config_method_param_info {
+	char		*name;
+	uint16		value;
+} randmac_config_method_param_info_t;
+
+static const randmac_config_method_param_info_t randmac_config_methods[] = {
+	/* Name				Value */
+	{ "None",			WL_RANDMAC_USER_NONE },
+	{ "FTM",			WL_RANDMAC_USER_FTM },
+	{ "NAN",			WL_RANDMAC_USER_NAN },
+	{ "SCAN",			WL_RANDMAC_USER_SCAN },
+	{ "ALL",			0xFFFF },
+};
+
+typedef struct randmac_config_param_info {
+	char		*name;			/* <param-name> identify configuration item */
+	wl_randmac_tlv_id_t		tlvid;			/* map config item TLV id */
+	char		*name_helpmsg;	/* help message */
+} randmac_config_param_info_t;
+
+static const randmac_config_param_info_t randmac_config_param_info[] = {
+	/* Name			TLV ID			Help Message */
+	{"mac-addr",	WL_RANDMAC_TLV_ADDR,	"Random MAC/OUI as xx:xx:xx:xx:xx:xx" },
+	{"bitmask", WL_RANDMAC_TLV_MASK, "Bitmask yy:yy:yy:yy:yy:yy" },
+	{"method", WL_RANDMAC_TLV_METHOD, "Methods using random MAC FTM|NAN|SCAN" }
+};
+
+static cmd_t wl_randmac_cmds[] = {
+	{ "randmac", wl_randmac, WLC_GET_VAR, WLC_SET_VAR,
+	"\tEnable/Disable MAC Address Randomization\n"
+	"\t0 : disable\n"
+	"\t1 : enable\n"
+	"\tUsage: wl randmac enable\n\n"
+	"\t\t wl randmac disable\n\n"
+	"config [<param-name><param-value>...]\n"
+	"\tGet/Set MAC address (OUI), bitmask, method\n\n"
+	"\tGet current configuration\n"
+	"\tUsage: wl randmac config\n"
+	"\tSet or update new configuration\n"
+	"\tUsage: wl randmac config mac-addr <xx:xx:xx:xx:xx:xx> bitmask <yy:yy:yy:yy:yy:yy> "
+	"<method [ALL|FTM|NAN|SCAN]>"
+	"version"
+	"\tGet version\n\n"
+	"\tUsage: wl randmac version\n\n"
+	"getstats"
+	"\tGet statistics\n\n"
+	"\tUsage: wl randmac getstats\n\n"
+	"clearstats"
+	"\tClear statistics\n\n"
+	"\tUsage: wl randmac clearstats\n\n" },
+
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+static wl_randmac_t *randmac_alloc_getset_buf(wl_randmac_subcmd_t subcmd_id,
+	uint16 subcmd_bufsize);
+static int wl_randmac_subcmd_method_handler(void *wl, cmd_t *cmd, char **argv);
+static int randmac_common_getcmd_handler(void *wl,
+	const randmac_subcmd_info_t *p_subcmd_info, char **argv);
+static int randmac_do_get_ioctl(void *wl, wl_randmac_t *p_iov, uint16 iov_len,
+	const randmac_subcmd_info_t *p_subcmd_info);
+static int randmac_handle_help(char **argv);
+static void randmac_display_config_help();
+
+/* module initialization */
+void
+wluc_randmac_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register randmac commands */
+	wl_module_cmds_register(wl_randmac_cmds);
+}
+
+static int
+wl_randmac(void *wl, cmd_t *cmd, char **argv)
+{
+	uint16 randmac_iovsize;
+	wl_randmac_t *p_randmac_iov = NULL;
+	int ret;
+
+	/* skip the command name and check if NULL */
+	if (argv[1] == NULL) {
+		wl_randmac_t *iov_resp;
+		randmac_iovsize = 0;
+		p_randmac_iov = randmac_alloc_getset_buf(WL_RANDMAC_SUBCMD_ENABLE,
+			randmac_iovsize);
+		/* Get wl randmac */
+		if (!p_randmac_iov) {
+			ret = BCME_NOMEM;
+			goto done;
+		}
+		ret = wlu_var_getbuf(wl, cmd->name, p_randmac_iov, sizeof(*p_randmac_iov),
+			(void *)&iov_resp);
+		if (ret != BCME_OK) {
+			goto done;
+		}
+
+		printf(">%s\n",
+			(iov_resp->subcmd_id == WL_RANDMAC_SUBCMD_ENABLE) ? "Enabled" : "Disabled");
+		goto done;
+
+	} else {
+		/* Set */
+		argv++;
+		ret = wl_randmac_subcmd_method_handler(wl, cmd, argv);
+	}
+done:
+	if (p_randmac_iov) {
+		free(p_randmac_iov);
+	}
+	return ret;
+}
+
+/* declare randmac subcommand handlers randmac_subcmd_xxxx() */
+/* e.g. static randmac_cmd_handler_t randmac_subcmd_get_version; */
+#define RANDMAC_SUBCMD_FUNC(suffix) randmac_subcmd_ ##suffix
+#define DECL_CMDHANDLER(X) static randmac_subcmd_handler_t randmac_subcmd_##X
+
+/* get */
+DECL_CMDHANDLER(get_version);		/* method-only */
+
+/* set */
+DECL_CMDHANDLER(enable);			/* method */
+DECL_CMDHANDLER(disable);			/* method */
+DECL_CMDHANDLER(config);			/* method */
+DECL_CMDHANDLER(getstats);			/* method */
+DECL_CMDHANDLER(clearstats);		/* method */
+
+static const randmac_subcmd_info_t randmac_subcmdlist[] = {
+	/* Name		Subcommand		Method		Handler		Help */
+	{"version", WL_RANDMAC_SUBCMD_GET_VERSION, WL_RANDMAC_USER_NONE,
+	RANDMAC_SUBCMD_FUNC(get_version), "Get randmac method API version information" },
+	{"enable", WL_RANDMAC_SUBCMD_ENABLE, WL_RANDMAC_USER_NONE,
+	RANDMAC_SUBCMD_FUNC(enable), "Enable randmac method"},
+	{"disable", WL_RANDMAC_SUBCMD_ENABLE, WL_RANDMAC_USER_NONE,
+	RANDMAC_SUBCMD_FUNC(disable), "Disable randmac method"},
+	{"config", WL_RANDMAC_SUBCMD_CONFIG, WL_RANDMAC_USER_NONE,
+	RANDMAC_SUBCMD_FUNC(config),
+	"Configure random MAC OUI, bitmask to randomize MAC address and method"},
+	{"getstats", WL_RANDMAC_SUBCMD_STATS, WL_RANDMAC_USER_NONE,
+	RANDMAC_SUBCMD_FUNC(getstats),
+	"Get MAC randomization method statistics"},
+	{"clearstats", WL_RANDMAC_SUBCMD_CLEAR_STATS, WL_RANDMAC_USER_NONE,
+	RANDMAC_SUBCMD_FUNC(clearstats), "Clear MAC randomization method statistics"},
+};
+
+const randmac_subcmd_info_t *
+randmac_get_subcmd_info(char *cmdname)
+{
+	int i;
+	const randmac_subcmd_info_t *p_subcmd_info;
+
+	/* Search subcmd name */
+	p_subcmd_info = &randmac_subcmdlist[0];
+	for (i = 0; i < (int)ARRAYSIZE(randmac_subcmdlist); i++) {
+		if (stricmp(p_subcmd_info->name, cmdname) == 0)
+			return p_subcmd_info;
+		p_subcmd_info++;
+	}
+
+	return NULL;
+}
+
+static int
+randmac_subcmd_get_version(void *wl,
+	const randmac_subcmd_info_t *p_subcmd_info, char **argv)
+{
+	/* Issue IOVAR and display version information */
+	return randmac_common_getcmd_handler(wl, p_subcmd_info, argv);
+}
+/*
+* 'wl randmac ascii-method' handler
+*     handle 'wl randmac <cmdname> [<param-name><param-value>]*'
+*/
+static int
+wl_randmac_subcmd_method_handler(void *wl, cmd_t *cmd, char **argv)
+{
+	const randmac_subcmd_info_t *p_subcmd_info;
+
+	/* ignore the command name 'proxd' */
+	UNUSED_PARAMETER(cmd);
+
+	/*
+	 * check for "wl randmac -h config" or
+	 * "wl randmac help config" --> display the usage
+	 */
+	if (!stricmp(*argv, "-h") || !stricmp(*argv, "help"))  {
+		return randmac_handle_help(++argv); /* return BCME_USAGE_ERROR; */
+	}
+
+	/*
+	 * search for the specified <cmdname> from the
+	 * pre-defined supported cmd list
+	 */
+	p_subcmd_info = randmac_get_subcmd_info(*argv);
+	if (p_subcmd_info == NULL) {
+		/* cannot find the cmd in the randmac_subcmdlist */
+		return BCME_USAGE_ERROR;
+	}
+
+	/* dispatch cmd to appropriate handler */
+	if (p_subcmd_info->handler) {
+		return p_subcmd_info->handler(wl, p_subcmd_info, ++argv);
+	} else {
+		return BCME_USAGE_ERROR;
+	}
+
+	return BCME_OK;
+
+}
+
+/* ***************************** set commands ********************* */
+
+/* randmac config-category definition */
+typedef enum {
+	RANDMAC_CONFIG_CAT_GENERAL = 1,	/* generial configuration */
+} randmac_config_category_t;
+
+/*
+* display help-messages for 'wl randmac -h config'
+*/
+static void
+randmac_display_method_help()
+{
+	int i;
+	int max_cmdname_len = 20;
+	const randmac_subcmd_info_t *p_subcmd_info;
+
+	/* a header */
+	printf("\n\tMAC Address Randomization\n");
+	printf("\tUsage: wl randmac <cmd> [<param-name> <param-value>]*\n");
+	printf("\t\t<cmd>: specify a command from the following list,\n");
+
+	/* show the command list and the help messages for each FTM command */
+	p_subcmd_info = &randmac_subcmdlist[0];
+	for (i = 0; i < (int) ARRAYSIZE(randmac_subcmdlist); i++) {
+		printf("\t\t  %*s: %s\n", max_cmdname_len, p_subcmd_info->name,
+			p_subcmd_info->helpmsg);
+		p_subcmd_info++;
+	}
+
+	printf("\t\t<param-name> <param-value>: <cmd>-specific parameters\n\n");
+
+	printf("\t\ttype 'wl randmac -h config' for configuration command usage.\n");
+
+	/* show examples */
+	printf("\tExample: wl randmac [0/1 0 - Disable, 1 - Enable]\n\n");
+	printf("\tExample: wl randmac config "
+		"[Random MAC Address/OUI<xx:xx:xx:xx:xx:xx>] "
+		"[Bitmask to randmize MAC Address<yy:yy:yy:yy:yy:yy>] [Method <FTM>]\n\n");
+
+	return;
+}
+
+/*
+* display help-messages for 'wl randmac -h config'
+*/
+static void
+randmac_display_config_help()
+{
+	int i;
+	int max_param_name_len = 20;
+	const randmac_config_param_info_t *p_config_param_info;
+
+	/* a header */
+	printf("\n\tConfigure MAC Address Randomization feature\n");
+	printf("\tUsage: wl randmac config { <param-name> <param-value> }+ \n");
+	/* print helpmsg for each config-item */
+	printf("\t\t<param-name> <param-value>: "
+		"configuration parameters from the following\n");
+	p_config_param_info = &randmac_config_param_info[0];
+	for (i = 0; i < (int) ARRAYSIZE(randmac_config_param_info); i++) {
+		printf("\t\t  %*s: %s\n", max_param_name_len, p_config_param_info->name,
+			p_config_param_info->name_helpmsg);
+
+		p_config_param_info++;
+	}
+
+	/* show examples */
+	printf("\n\tExample: wl randmac config mac-addr <xx:xx:xx:xx:xx:xx> "
+		"bitmask <yy:yy:yy:yy:yy:yy> method <FTM>\n");
+}
+
+/*
+* handle
+*        wl randmac -h
+*        wl randmac -h config
+* Output:
+*        BCME_USAGE_ERROR -- caller should bring up 'randmac' level help messages
+*        BCME_OK          -- this func displays context-help for RANDMAC method,
+*                            caller does not need to show any help messages.
+*/
+static int
+randmac_handle_help(char **argv)
+{
+	if (!*argv)
+		return BCME_USAGE_ERROR;
+
+	if (stricmp(*argv, "config") != 0)	/* check 'wl randmac -h config' */
+		return BCME_USAGE_ERROR;
+
+	++argv;
+	if (*argv == NULL) {
+		/* show help messages for 'wl randmac -h config' */
+		randmac_display_config_help();
+		return BCME_OK;
+	}
+
+	/* invalid <cmd>, display help messages for RANDMAC method */
+	randmac_display_method_help();
+	return BCME_OK;
+}
+
+static randmac_config_category_t
+randmac_parse_config_category(char *arg_category)
+{
+	BCM_REFERENCE(arg_category);
+	return RANDMAC_CONFIG_CAT_GENERAL;
+}
+
+static const randmac_config_param_info_t *
+randmac_get_config_param_info(char *p_param_name)
+{
+	int i;
+	const randmac_config_param_info_t   *p_config_param_info;
+
+	p_config_param_info = &randmac_config_param_info[0];
+	for (i = 0; i < (int) ARRAYSIZE(randmac_config_param_info); i++) {
+		if (stricmp(p_param_name, p_config_param_info->name) == 0) {
+			return p_config_param_info;
+		}
+		p_config_param_info++;      /* next */
+	}
+	return (randmac_config_param_info_t *) NULL;	/* 'invalid param name' */
+}
+
+static uint16
+randmac_parse_method(char *method_name)
+{
+	int i = 0;
+	const randmac_config_method_param_info_t *p_method_param_info;
+
+	p_method_param_info = &randmac_config_methods[0];
+
+	for (; i < (int) ARRAYSIZE(randmac_config_methods); i++) {
+		if (stricmp(method_name, p_method_param_info->name) == 0) {
+			return p_method_param_info->value;
+		}
+		p_method_param_info++;
+	}
+
+	return 0;
+}
+
+static int
+randmac_handle_config_general(char **argv, wl_randmac_config_t *p_config)
+{
+	int     status = BCME_OK;
+	const randmac_config_param_info_t *p_config_param_info;
+	char *method_name;
+
+	/* check if user provides param-values for 'config options' command */
+	if (*argv == NULL)
+		return BCME_USAGE_ERROR;
+
+	/* <param-value>  followed 'wl proxd ftm [session-id] config options' */
+	while (*argv != NULL) {
+		/* look up 'config-param-info' based on 'param-name' */
+		p_config_param_info = randmac_get_config_param_info(*argv);
+		if (p_config_param_info == (randmac_config_param_info_t *) NULL) {
+			printf("error: invalid param-name (%s)\n", *argv);
+			status = BCME_USAGE_ERROR;  /* param-name is not specified */
+			break;
+		}
+
+		/* parse 'param-value' */
+		if (*(argv + 1) == NULL) {
+			printf("error: invalid param-value\n");
+			status = BCME_USAGE_ERROR;  /* param-value is not specified */
+			break;
+		}
+		++argv;
+
+		/* parse param-value */
+		switch (p_config_param_info->tlvid) {
+		case WL_RANDMAC_TLV_ADDR:
+			p_config->addr = ether_null;
+			if (!wl_ether_atoe(*argv, &p_config->addr)) {
+				printf("error: invalid MAC address parameter\n");
+				status = BCME_USAGE_ERROR;
+				break;
+			}
+			p_config->flags |= WL_RANDMAC_FLAGS_ADDR;
+			break;
+
+		case WL_RANDMAC_TLV_MASK:
+			p_config->addr_mask = ether_null;
+			if (!wl_ether_atoe(*argv, &p_config->addr_mask)) {
+				printf("error: invalid MAC address parameter\n");
+				status = BCME_USAGE_ERROR;
+				break;
+			}
+			p_config->flags |= WL_RANDMAC_FLAGS_MASK;
+			break;
+
+		case WL_RANDMAC_TLV_METHOD:
+			method_name = *argv;
+			p_config->method |= randmac_parse_method(method_name);
+			p_config->flags |= WL_RANDMAC_FLAGS_METHOD;
+			break;
+
+		default:
+			/* not supported */
+			status = BCME_USAGE_ERROR;
+			break;
+		}
+
+		if (status != BCME_OK)
+			break;              /* abort */
+
+		++argv; /* Next param */
+	}
+
+	return status;
+}
+
+static int
+randmac_subcmd_disable(void *wl, const randmac_subcmd_info_t *p_subcmd_info,
+	char **argv)
+{
+	return randmac_subcmd_enable(wl, p_subcmd_info, argv);
+}
+
+static int
+randmac_subcmd_enable(void *wl, const randmac_subcmd_info_t *p_subcmd_info,
+	char **argv)
+{
+	wl_randmac_t *p_iov = NULL;
+	int status = BCME_OK;
+	uint16  iov_len = WL_RANDMAC_IOV_HDR_SIZE;
+
+	BCM_REFERENCE(*argv);
+	/* allocate a buffer for randmac config via 'set' iovar */
+	p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len);
+	if (p_iov == (wl_randmac_t *) NULL) {
+		status = BCME_NOMEM;
+		goto done;
+	}
+
+	if (!(stricmp("enable", p_subcmd_info->name))) {
+		p_iov->subcmd_id = WL_RANDMAC_SUBCMD_ENABLE;
+	} else if (!(stricmp("disable", p_subcmd_info->name))) {
+		p_iov->subcmd_id = WL_RANDMAC_SUBCMD_DISABLE;
+	} else {
+		randmac_display_method_help();
+	}
+	p_iov->version = WL_RANDMAC_API_VERSION;
+	p_iov->len = iov_len;
+	status = wlu_var_setbuf(wl, "randmac", p_iov, iov_len);
+
+done:
+	if (p_iov) {
+		/* clean up */
+		free(p_iov);
+	}
+	return status;
+}
+
+static int
+randmac_subcmd_config(void *wl, const randmac_subcmd_info_t *p_subcmd_info,
+	char **argv)
+{
+	wl_randmac_t *p_iov = NULL;
+	int status = BCME_OK;
+	wl_randmac_config_t *p_config;
+	uint16  iov_len = WL_RANDMAC_IOV_HDR_SIZE;
+	randmac_config_category_t category;
+
+	if (*argv == NULL) {
+		status = randmac_common_getcmd_handler(wl, p_subcmd_info, argv);
+		goto done;
+	}
+
+	/* allocate a buffer for randmac config via 'set' iovar */
+	iov_len += sizeof(*p_config);
+	p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len);
+	if (p_iov == (wl_randmac_t *) NULL) {
+		status = BCME_NOMEM;
+		goto done;
+	}
+
+	/* setup config data */
+	p_config = (wl_randmac_config_t *)&p_iov->data[0];
+
+	/* parse the cmd-line,  get the config-category and dispatch to the handler */
+	/* to parse the parameters based on the 'config-category' */
+	category = randmac_parse_config_category(*argv);
+	if (category == RANDMAC_CONFIG_CAT_GENERAL)
+		status = randmac_handle_config_general(argv, p_config);
+
+	if (status == BCME_USAGE_ERROR) {
+		randmac_display_config_help();
+	} else {
+		p_iov->version = WL_RANDMAC_API_VERSION;
+		p_iov->subcmd_id = WL_RANDMAC_SUBCMD_CONFIG;
+		p_iov->len = WL_RANDMAC_IOV_CONFIG_SIZE;
+		status = wlu_var_setbuf(wl, "randmac", p_iov, iov_len);
+	}
+
+done:
+	if (p_iov) {
+		/* clean up */
+		free(p_iov);
+	}
+	return status;
+}
+
+static int
+randmac_subcmd_getstats(void *wl, const randmac_subcmd_info_t *p_subcmd_info,
+	char **argv)
+{
+	return randmac_common_getcmd_handler(wl, p_subcmd_info, argv);
+}
+
+static int
+randmac_subcmd_clearstats(void *wl, const randmac_subcmd_info_t *p_subcmd_info,
+	char **argv)
+{
+	wl_randmac_t *p_iov;
+	int status = BCME_OK;
+	uint16  iov_len = WL_RANDMAC_IOV_HDR_SIZE;
+
+	BCM_REFERENCE(*argv);
+	/* allocate a buffer for randmac config via 'set' iovar */
+	p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len);
+	if (p_iov == (wl_randmac_t *) NULL) {
+		status = BCME_NOMEM;
+		goto done;
+	}
+
+	p_iov->version = WL_RANDMAC_API_VERSION;
+	p_iov->subcmd_id = WL_RANDMAC_SUBCMD_CLEAR_STATS;
+	p_iov->len = iov_len;
+	status = wlu_var_setbuf(wl, "randmac", p_iov, iov_len);
+
+done:
+	if (p_iov) {
+		/* clean up */
+		free(p_iov);
+	}
+	return status;
+}
+
+static wl_randmac_t *
+randmac_alloc_getset_buf(wl_randmac_subcmd_t subcmd_id, uint16 subcmd_bufsize)
+{
+	uint16 randmac_iovsize;
+	wl_randmac_t *p_randmac_iov = (wl_randmac_t *)NULL;
+
+	BCM_REFERENCE(subcmd_id);
+	/* header + subcommand */
+	randmac_iovsize = sizeof(wl_randmac_t) + subcmd_bufsize;
+
+	p_randmac_iov = calloc(1, randmac_iovsize);
+	if (p_randmac_iov == NULL) {
+		printf("error: failed to allocate %d bytes of memory\n", randmac_iovsize);
+		return NULL;
+	}
+
+	/* setup randmac method iovar header */
+	p_randmac_iov->version = htol16(WL_RANDMAC_API_VERSION);
+	/* caller may adjust it based on subcommand */
+	p_randmac_iov->len = htol16(randmac_iovsize);
+	p_randmac_iov->subcmd_id = htol16(subcmd_id);
+
+	return p_randmac_iov;
+}
+
+static int
+randmac_common_getcmd_handler(void *wl, const randmac_subcmd_info_t *p_subcmd_info,
+	char **argv)
+{
+	int status = BCME_OK;
+	uint16 iov_len = WL_RANDMAC_IOV_HDR_SIZE;
+	wl_randmac_t *p_iov = (wl_randmac_t *) NULL;
+
+	BCM_REFERENCE(*argv);
+	switch (p_subcmd_info->subcmd_id) {
+	case WL_RANDMAC_SUBCMD_GET_VERSION:
+		iov_len += WL_RANDMAC_IOV_VERSION_SIZE;
+		p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len);
+		break;
+
+	case WL_RANDMAC_SUBCMD_CONFIG:
+		iov_len += WL_RANDMAC_IOV_CONFIG_SIZE;
+		p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len);
+		break;
+
+	case WL_RANDMAC_SUBCMD_STATS:
+		iov_len += WL_RANDMAC_IOV_STATS_SIZE;
+		p_iov = randmac_alloc_getset_buf(p_subcmd_info->subcmd_id, iov_len);
+		break;
+
+	default:
+		/* Unknown subcommand */
+		break;
+	}
+
+	if (p_iov != NULL) {
+		/* get */
+		status = randmac_do_get_ioctl(wl, p_iov, iov_len, p_subcmd_info);
+	}
+
+	/* Clean up memory */
+	free(p_iov);
+
+	return status;
+}
+
+static int
+randmac_do_get_ioctl(void *wl, wl_randmac_t *p_iov, uint16 iov_len,
+const randmac_subcmd_info_t *p_subcmd_info)
+{
+	/* for gets we only need to pass ioc header */
+	wl_randmac_t *p_iovresp = NULL;
+	int status;
+	/*  send getbuf proxd iovar */
+	status = wlu_var_getbuf(wl, "randmac", p_iov, iov_len, (void *)&p_iovresp);
+	if (status != BCME_OK) {
+		return status;
+	}
+
+	if (p_iovresp != NULL) {
+		switch (p_subcmd_info->subcmd_id) {
+		case WL_RANDMAC_SUBCMD_GET_VERSION:
+			{
+				wl_randmac_version_t *p_iov_ver;
+				p_iov_ver = (wl_randmac_version_t *)(&p_iovresp->data[0]);
+				printf("> Version: 0x%04x\n", p_iov_ver->version);
+			}
+			break;
+
+		case WL_RANDMAC_SUBCMD_DISABLE:
+		case WL_RANDMAC_SUBCMD_ENABLE:
+			{
+				printf(">%s\n",
+					(p_subcmd_info->subcmd_id == WL_RANDMAC_SUBCMD_ENABLE) ?
+					"Enabled" : "Disabled");
+			}
+			break;
+
+		case WL_RANDMAC_SUBCMD_CONFIG:
+			{
+				uint32 i = 0;
+				const randmac_config_method_param_info_t *methods_info;
+				wl_randmac_config_t *p_iov_config;
+				p_iov_config = (wl_randmac_config_t *)(&p_iovresp->data[0]);
+				printf(">MAC Address:%02x:%02x:%02x:%02x:%02x:%02x\n",
+					p_iov_config->addr.octet[0],
+					p_iov_config->addr.octet[1],
+					p_iov_config->addr.octet[2],
+					p_iov_config->addr.octet[3],
+					p_iov_config->addr.octet[4],
+					p_iov_config->addr.octet[5]);
+				printf(">Bitmask:%02x:%02x:%02x:%02x:%02x:%02x\n",
+					p_iov_config->addr_mask.octet[0],
+					p_iov_config->addr_mask.octet[1],
+					p_iov_config->addr_mask.octet[2],
+					p_iov_config->addr_mask.octet[3],
+					p_iov_config->addr_mask.octet[4],
+					p_iov_config->addr_mask.octet[5]);
+				if (p_iov_config->method == WL_RANDMAC_USER_NONE) {
+					printf("> Method: None\n");
+				} else if (p_iov_config->method == WL_RANDMAC_USER_ALL) {
+					printf(">Method: All\n");
+				} else {
+					printf(">Method:");
+					while (p_iov_config->method) {
+						if (p_iov_config->method & (1 << i)) {
+							methods_info =
+								&randmac_config_methods[i + 1];
+							printf(" %s ", methods_info->name);
+							p_iov_config->method &= ~(1 << i);
+						}
+						i++;
+					}
+					printf("\n");
+				}
+			}
+			break;
+		case WL_RANDMAC_SUBCMD_STATS:
+			{
+				wl_randmac_stats_t *pstats =
+					(wl_randmac_stats_t *)(&p_iovresp->data[0]);
+				printf(">MAC randomization set calls success:\t %u\n",
+					pstats->set_ok);
+				printf(">MAC randomization set calls failed:\t %u\n",
+					pstats->set_fail);
+				printf(">MAC randomization set requests:\t %u\n",
+					pstats->set_reqs);
+				printf(">MAC randomization reset requests:\t %u\n",
+					pstats->reset_reqs);
+				printf(">MAC randomization restore calls success:%u\n",
+					pstats->restore_ok);
+				printf(">MAC randomization restore calls failed: %u\n",
+					pstats->restore_fail);
+				printf(">MAC randomization events sent:\t\t %u\n",
+					pstats->events_sent);
+				printf(">MAC randomization events received:\t %u\n",
+					pstats->events_rcvd);
+				printf("\n");
+			}
+			break;
+
+		default:
+			/* Unknown response */
+			break;
+		}
+	}
+
+	return status;
+}
diff --git a/wl/src/wl/exe/wluc_relmcast.c b/wl/src/wl/exe/wluc_relmcast.c
new file mode 100644
index 0000000..bdd00ce
--- /dev/null
+++ b/wl/src/wl/exe/wluc_relmcast.c
@@ -0,0 +1,607 @@
+/*
+ * wl rmc command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_relmcast.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+#include <miniopt.h>
+
+static cmd_func_t wl_mcast_ackmac, wl_mcast_ackreq, wl_mcast_status;
+static cmd_func_t wl_mcast_actf_time, wl_mcast_rssi_thresh, wl_mcast_stats;
+static cmd_func_t wl_mcast_rssi_delta, wl_mcast_vsie, wl_mcast_ar_timeout;
+
+static cmd_t wl_rmc_cmds[] = {
+	{ "rmc_ackmac", wl_mcast_ackmac, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get ACK required multicast mac address\n"
+	"\tusage: wl rmc_ackmac -i [index] -t [multicast mac address]"
+	},
+	{ "rmc_ackreq", wl_mcast_ackreq, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get ACK rmc_mode 0 disable, 1 enable transmitter, 2 enable initiator \n"
+	"\tusage: wl rmc_ackreq [mode]"
+	},
+	{ "rmc_txrate", wl_phy_rate, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get a fixed transmit rate for the reliable multicast:\n"
+	"\tvalid values for 802.11ac are (6, 9, 12, 18, 24, 36, 48, 54)\n"
+	"\t-1 (default) means automatically determine the best rate"
+	},
+	{ "rmc_status", wl_mcast_status, WLC_GET_VAR, -1,
+	"Display reliable multicast client status"
+	},
+	{ "rmc_actf_time", wl_mcast_actf_time, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get mcast action frame tx time period in ms\n"
+	"\tusage: wl rmc_actf_time [value]"
+	},
+	{ "rmc_ar_timeout", wl_mcast_ar_timeout, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get rmc active receiver timeout in ms\n"
+	"\tusage: wl rmc_ar_timeout [duration in ms]"
+	},
+	{ "rmc_rssi_thresh", wl_mcast_rssi_thresh, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get minimum rssi needed for a station to be an active receiver\n"
+	"\tusage: wl rmc_rssi_thresh [value]"
+	},
+	{ "rmc_stats", wl_mcast_stats, WLC_GET_VAR, WLC_SET_VAR,
+	"Display/Clear reliable multicast client statistical counters\n"
+	"\tusage: wl rmc_stats [arg]"
+	},
+	{ "rmc_rssi_delta", wl_mcast_rssi_delta, WLC_GET_VAR, WLC_SET_VAR,
+	"Display/Set RSSI delta to switch receive leader\n"
+	"\tusage: wl rmc_rssi_delta [arg]"
+	},
+	{ "rmc_vsie", wl_mcast_vsie, WLC_GET_VAR, WLC_SET_VAR,
+	"Display/Set vendor specific IE contents\n"
+	"\tusage: wl rmc_vsie [OUI] [Data]"
+	},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_rmc_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register rmc commands */
+	wl_module_cmds_register(wl_rmc_cmds);
+}
+
+static int
+wl_mcast_ackmac(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	int i, err;
+	uint8 num_tr;
+	wl_rmc_entry_t ackmac_params;
+	wl_rmc_entry_table_t tablelist;
+	void *ptr = NULL;
+	wl_rmc_trans_in_network_t *reply = NULL;
+	miniopt_t to;
+	struct ether_addr* ea = NULL;
+	bool index_set = FALSE; bool mac_set = FALSE;
+
+	/* muticast mac address - ipv4 & ipv6 resp. */
+	uint8 mc_mac[6]		 = {0x1, 0x0, 0x5e, 0x7f, 0xff, 0xff};
+	uint8 mc_mac_ipv6[6] = {0x33, 0x33, 0x0, 0x0, 0x0, 0x0};
+
+	/* index will tell us what to do */
+
+	if (!*++argv) {
+		/* Get and display all entries in the table */
+		if ((ret = wlu_var_getbuf(wl, cmd->name,
+		             NULL,
+		             0,
+		             &ptr)) < 0) {
+			return ret;
+		}
+		reply = (wl_rmc_trans_in_network_t*)ptr;
+		num_tr = reply->num_tr;
+
+		printf("\n Num of transmitters %02x ", num_tr);
+		printf("\n Transmitter Mac \t AR  Mac");
+		printf("\t rmc_ar_timeout\t amt_idx   flag ");
+
+		for (i = 0; (i < WL_RMC_MAX_NUM_TRS) && (i < num_tr); i++) {
+			printf("\n %s \t", wl_ether_etoa(&reply->trs[i].tr_mac));
+			printf(" %s \t", wl_ether_etoa(&reply->trs[i].ar_mac));
+			printf(" %d \t %d      %04x",
+				reply->trs[i].artmo, reply->trs[i].amt_idx, reply->trs[i].flag);
+		}
+
+		printf("\n");
+		return 0;
+	}
+
+	miniopt_init(&to, cmd->name, NULL, FALSE);
+
+	while ((err = miniopt(&to, argv)) != -1) {
+		if (err == 1) {
+			return BCME_USAGE_ERROR;
+		}
+		argv += to.consumed;
+		/* Index for multicast address in RMC table */
+		if (to.opt == 'i') {
+		/* wl rmc_ackmac -i 8 -t <control multi-cast address> */
+		/* this is used to change the AF multi-cast address   */
+			if (!to.good_int || ((to.val != 8) && to.val)) {
+				fprintf(stderr, "%s: Invalid mode value\n", cmd->name);
+				err = -1;
+				goto exit;
+			}
+			tablelist.index = to.val;
+			index_set = TRUE;
+		}
+
+		/* Add multicast address with index "i" to RMC table */
+		if (to.opt == 't') {
+			if (!wl_ether_atoe(to.valstr, &ackmac_params.addr)) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as a MAC address\n",
+					cmd->name, to.valstr);
+				err = -1;
+				goto exit;
+			}
+			mac_set = TRUE;
+		}
+	}
+
+	if (index_set) {
+		if (!mac_set) {
+			printf("\n Invalid without mac address");
+			ret =  BCME_USAGE_ERROR;
+		} else if (tablelist.index == 8) {
+			/* Index 8 is for changing the destination  address of the AF */
+			/* This multi-cast address is the da of the action frame that */
+			/* is sent out periodically                                   */
+			memcpy(&tablelist.entry[0].addr, &ackmac_params.addr,
+				sizeof(struct ether_addr));
+
+			/* insert to list */
+			ea = &tablelist.entry[0].addr;
+			tablelist.entry[0].flag = RELMCAST_ENTRY_OP_ENABLE;
+
+			/* for ipv4, initial three bytes in mc address are standard &
+			    2 bytes for ipv6
+			 */
+			if ((!memcmp(ea, mc_mac, 3) && !(ea->octet[3] & 0x80)) ||
+			     !memcmp(ea, mc_mac_ipv6, 2)) {
+
+				fprintf(stderr,
+					    "\nAdding multi-cast mac %s\n", wl_ether_etoa(ea));
+
+				return wlu_var_setbuf(wl, cmd->name,
+				         &tablelist,
+				         sizeof(wl_rmc_entry_table_t));
+
+			} else {
+
+				fprintf(stderr, "multicast mac started with"
+					"01:00:5e:0... or 33:33:...\n");
+				ret = BCME_BADARG;
+
+			}
+		} else {
+			printf("\n Invalid index ");
+			ret = BCME_USAGE_ERROR;
+		}
+	}
+exit:
+	return ret;
+}
+
+static int
+wl_mcast_ackreq(void *wl, cmd_t *cmd, char **argv)
+{
+	const char* fn_name = "wl_mcast_ackreq";
+	int err, i = 0;
+	uint argc;
+	char *endptr = NULL;
+	void *ptr = NULL;
+	uint8 *reply_mode = NULL;
+	uint8 params_mode, old_mode;
+	wl_relmcast_status_t status;
+
+	memset(&params_mode, 0, sizeof(uint8));
+	/* toss the command name */
+	argv++;
+
+	if ((err = wlu_var_getbuf_sm(wl, cmd->name, &params_mode,
+		sizeof(uint8), &ptr))  != BCME_OK) {
+		fprintf(stderr, "Error getting variable %s\n", argv[0]);
+		return err;
+	}
+
+	reply_mode = (uint8 *)ptr;
+	old_mode = *reply_mode;
+
+	if (!*argv) {
+		fprintf(stderr, "%s mode %d \n", fn_name, *reply_mode);
+		return err;
+	}
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	/* required arg: mode disable, enable  or initiator enabled */
+	if (argc < 1)
+		return -1;
+
+	/* get the new ackreq mode */
+	params_mode = strtol(argv[0], &endptr, 0);
+
+	if ((*endptr != '\0') || (params_mode > WL_RMC_MODE_INITIATOR))
+		return -1;
+
+	if (argc > 1) {
+		fprintf(stderr,
+			"%s: could not parse extra argument %s:\n",
+			fn_name, argv[1]);
+
+		err = -1;
+		goto exit;
+	}
+
+	if ((err = wlu_var_setbuf(wl, cmd->name, &params_mode, sizeof(uint8))) != BCME_OK) {
+		goto out_of_here;
+	}
+
+	if (params_mode == WL_RMC_MODE_INITIATOR ||
+	   ((params_mode == WL_RMC_MODE_RECEIVER) &&
+	   (old_mode == WL_RMC_MODE_INITIATOR))) {
+
+		for (i = 0; i <= 10; i++) {
+			/* check status of the RCV bit to make sure ack are receive */
+			if ((err = wlu_iovar_get(wl, "rmc_status",
+			                    (void *) &status,
+			                    (sizeof(wl_relmcast_status_t)))) < 0) {
+				return (err);
+			}
+
+			if (status.err != (uint16)BCME_NOTREADY) {
+				if (status.err == (uint16)BCME_RXFAIL) {
+					fprintf(stderr, "%s: error in setting mode: no ack receive"
+					        "%d tx code %d \n",
+					         fn_name,  params_mode, status.err);
+
+					err = -1;
+				} else {
+					err = 0;
+				}
+				goto out_of_here;
+			}
+
+			/* Allow ample time (by staying in loop) to get ACK
+			   for previous TX frame
+			*/
+			{
+				volatile uint16 busycnt = -1;
+				/* There is no system call for sleep that will work for */
+				/*  all os flavors. When there is a common sleep call we */
+				/*  can replace the following busy wait loop */
+				while (--busycnt)
+					;
+				busycnt = -1;
+			}
+		} /* for loop */
+	}
+out_of_here:
+	if ((err < 0) || (i > 10))
+		fprintf(stderr, "%s: Error setting %d err %d \n", fn_name, params_mode, err);
+	else
+		fprintf(stderr, "%s: setting %d err %d \n", fn_name, params_mode, err);
+exit:
+	return 0;
+}
+
+
+static int
+wl_mcast_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, i;
+	wl_relmcast_status_t status;
+
+	if (!*++argv) {
+		/* Get */
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &status,
+			(sizeof(wl_relmcast_status_t)))) < 0)
+			return (err);
+
+		if (status.ver != WL_RMC_VER) {
+			printf("Wrong Version %d %d\n", WL_RMC_VER, status.ver);
+		} else if (status.num == 0) {
+			printf("No clients associated\n");
+		} else {
+				for (i = 0; i < status.num; i++) {
+					printf("%s\t%d\t%c%c%c\n",
+						wl_ether_etoa(&status.clients[i].addr),
+						status.clients[i].rssi,
+						((status.clients[i].flag &
+					        WL_RMC_FLAG_ACTIVEACKER) ? 'A' : ' '),
+						((status.clients[i].flag &
+					        WL_RMC_FLAG_INBLACKLIST) ? 'B' : ' '),
+						((status.clients[i].flag &
+					        WL_RMC_FLAG_RELMCAST) ? 'R' : ' '));
+				}
+				printf("Notification Frame TimePeriod: %d ms\n", status.actf_time);
+		}
+	} else {
+		printf("Cannot set reliable multicast status\n");
+	}
+
+	return 0;
+}
+
+static int
+wl_mcast_actf_time(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error = -1;
+	const char *name = cmd->name;
+
+	/* toss the command name from the args */
+	argv++;
+
+	if (!*argv) {
+		error = wlu_iovar_getint(wl, name, &val);
+		if (error < 0)
+			return (error);
+		printf("Action Frame tx time period: %dms\n", val);
+
+	} else {
+
+		val = (uint16)strtol(*argv, NULL, 10); /* 10 is for base 10 (decimal) */
+
+		if (val >= WL_RMC_ACTF_TIME_MIN &&
+			val <= WL_RMC_ACTF_TIME_MAX) {
+
+			error = wlu_iovar_setint(wl, name, val);
+
+		} else {
+
+			printf("\"Out of range\": valid range %dms - %dms\n",
+			                               WL_RMC_ACTF_TIME_MIN,
+			                               WL_RMC_ACTF_TIME_MAX);
+		}
+	}
+	return error;
+}
+
+static int
+wl_mcast_ar_timeout(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error = -1;
+	const char *name = cmd->name;
+
+	/* toss the command name from the args */
+	argv++;
+
+	if (!*argv) {
+		error = wlu_iovar_getint(wl, name, &val);
+		if (error < 0)
+			return (error);
+		printf("Active Receiver time out: %dms\n", val);
+
+	} else {
+		val = (uint16)strtol(*argv, NULL, 10);
+		if (val >= WL_RMC_ARTMO_MIN &&
+			val <= WL_RMC_ARTMO_MAX)
+			error = wlu_iovar_setint(wl, name, val);
+		else
+			printf("\"Out of range\": valid range %dms - %dms\n",
+			WL_RMC_ARTMO_MIN,
+			WL_RMC_ARTMO_MAX);
+	}
+	return error;
+}
+
+static int
+wl_mcast_rssi_thresh(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error = -1;
+	const char *name = cmd->name;
+
+	/* toss the command name from the args */
+	argv++;
+
+	if (!*argv) {
+		error = wlu_iovar_getint(wl, name, &val);
+		if (error < 0)
+			return (error);
+		printf("rmc rssi: %d\n", val);
+
+	} else {
+		val = (int8)strtol(*argv, NULL, 10);
+		error = wlu_iovar_setint(wl, name, val);
+	}
+
+	return error;
+}
+
+static int
+wl_mcast_stats(void *wl, cmd_t *cmd, char **argv)
+{
+#define	PRCNT(name)	pbuf += sprintf(pbuf, "%s %u ", #name, dtoh16(cnts_v.name))
+#define	PRCNT32(name)	pbuf += sprintf(pbuf, "%s %u ", #name, dtoh32(cnts_v.name))
+	wl_rmc_cnts_t *cnts = NULL;
+	wl_rmc_cnts_t cnts_v;
+	int err = BCME_OK;
+	uint8 argval, argc;
+	char *pbuf = buf;
+	char *endptr = NULL;
+	void *ptr = NULL;
+
+	if (!*++argv) {
+		/* no arg - get and display all values */
+
+		if ((err = wlu_var_getbuf (wl, cmd->name, &cnts_v, sizeof(wl_rmc_cnts_t),  &ptr)))
+			return (err);
+
+		cnts = (wl_rmc_cnts_t*)ptr;
+
+		memcpy((wl_rmc_cnts_t*)&cnts_v, cnts, sizeof(wl_rmc_cnts_t));
+		cnts_v.version = dtoh16(cnts->version);
+		cnts_v.length = dtoh16(cnts->length);
+
+		if (cnts_v.version != WL_RMC_CNT_VERSION) {
+			printf("\tIncorrect version of counters struct: expected %d; got %d\n",
+			        WL_RMC_CNT_VERSION, cnts->version);
+
+			return -1;
+		}
+
+		PRCNT(dupcnt); PRCNT(ackreq_err); PRCNT(af_tx_err); PRNL();
+		PRCNT(null_tx_err); PRCNT(af_unicast_tx_err); PRCNT(mc_no_amt_slot); PRNL();
+		PRCNT(mc_not_mirrored); PRCNT(mc_existing_tr); PRCNT(mc_exist_in_amt); PRNL();
+		PRCNT(mc_utilized); PRCNT(mc_taken_other_tr); PRCNT32(rmc_rx_frames_mac); PRNL();
+		PRCNT32(rmc_tx_frames_mac); PRCNT32(mc_ar_role_selected);
+		PRCNT32(mc_ar_role_deleted); PRNL();
+		PRCNT32(mc_noacktimer_expired); PRCNT32(mc_null_ar_cnt);
+		PRCNT(mc_no_wl_clk); PRNL();
+		PRCNT(mc_tr_cnt_exceeded); PRNL();
+		fputs(buf, stdout);
+
+	} else {
+
+			/* arg count */
+			for (argc = 0; argv[argc]; argc++)
+				;
+			argval = strtol(argv[0], &endptr, 0);
+			if (argval == 255) {
+			/* arg is -1, clear all the values */
+				fprintf(stderr, "clearing rmc counters\n");
+				err = wlu_var_setbuf(wl, cmd->name, &cnts_v, sizeof(wl_rmc_cnts_t));
+
+			} else {
+				fprintf(stderr, "Invalid arg, only -1"
+					"is allowed to clear counters\n");
+				err = BCME_BADARG;
+			}
+	}
+	return err;
+}
+
+static int
+wl_mcast_rssi_delta(void *wl, cmd_t *cmd, char **argv)
+{
+	int val, error = -1;
+	const char *name = cmd->name;
+
+	/* toss the command name from the args */
+	argv++;
+
+	if (!*argv) {
+		error = wlu_iovar_getint(wl, name, &val);
+		if (error < 0)
+			return (error);
+		printf("rmc rssi delta: %d\n", val);
+
+	} else {
+		val = (uint16)strtol(*argv, NULL, 10);
+		if (val >= 0) /* rssi delta value should be a whole number */
+			error = wlu_iovar_setint(wl, name, val);
+		else
+			printf("\"Out of range\": rmc rssi delta should be >=0\n");
+	}
+	return error;
+}
+
+static int
+wl_mcast_vsie(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = 0;
+	void *ptr = NULL;
+	wl_rmc_vsie_t *reply = NULL;
+	wl_rmc_vsie_t vsie;
+	char *parse = NULL;
+	char tmp[4];
+	int idx, cnt;
+
+	if (!*++argv) {
+
+		/* Get and display all entries in the table */
+		if ((ret = wlu_var_getbuf(wl, cmd->name,
+		             NULL,
+		             0,
+		             &ptr)) < 0) {
+			return ret;
+		}
+
+		reply = (wl_rmc_vsie_t*)ptr;
+
+		printf("0x%x%x%x 0x%x", reply->oui[0], reply->oui[1],
+			reply->oui[2], reply->payload);
+
+	} else {
+
+		parse = *argv++;
+
+		/* remove "0x" from the input string which is in hex */
+		if (strlen(parse)/2 > DOT11_OUI_LEN) {
+			if (!strncmp("0x", parse, strlen("0x")) ||
+			    !strncmp("0X", parse, strlen("0X"))) {
+				parse += strlen("0x");
+			}
+		}
+
+		/* if OUI string is not 6 characters, simply reject */
+		if (strlen(parse) != DOT11_OUI_LEN * 2)
+			return BCME_ERROR;
+
+		/* parse oui string */
+		for (idx = 0; idx < DOT11_OUI_LEN; idx++) {
+			for (cnt = 0; cnt < 2; cnt++) {
+				tmp[cnt] = *parse++;
+			}
+			tmp[cnt] = '\0';
+			vsie.oui[idx] = (uint8)(strtoul(tmp, NULL, 16));
+		}
+
+		/* second argument is missing!! */
+		if (!*argv) {
+			return BCME_ERROR;
+		}
+
+		vsie.payload = (uint16)(strtoul(*argv, NULL, 16));
+		ret = wlu_var_setbuf(wl, cmd->name, &vsie, sizeof(vsie));
+	}
+
+	return ret;
+}
diff --git a/wl/src/wl/exe/wluc_rrm.c b/wl/src/wl/exe/wluc_rrm.c
new file mode 100644
index 0000000..80b07b0
--- /dev/null
+++ b/wl/src/wl/exe/wluc_rrm.c
@@ -0,0 +1,913 @@
+/*
+ * wl rrm command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_rrm.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_rrm;
+static cmd_func_t wl_rrm_nbr_req;
+static cmd_func_t wl_rrm_bcn_req;
+static cmd_func_t wl_rrm_chload_req;
+static cmd_func_t wl_rrm_noise_req;
+static cmd_func_t wl_rrm_frame_req;
+static cmd_func_t wl_rrm_stat_req;
+static cmd_func_t wl_rrm_stat_rpt;
+static cmd_func_t wl_rrm_lm_req;
+static cmd_func_t wl_rrm_nbr_list;
+static cmd_func_t wl_rrm_nbr_del_nbr;
+static cmd_func_t wl_rrm_nbr_add_nbr;
+
+static cmd_func_t wl_rrm_config;
+
+static cmd_t wl_rrm_cmds[] = {
+	{ "rrm", wl_rrm, WLC_GET_VAR, WLC_SET_VAR,
+	"enable or disable RRM feature\n"
+	"\tUsage: wl rrm [0/1] to disable/enable RRM feature"},
+	{ "rrm_bcn_req", wl_rrm_bcn_req, -1, WLC_SET_VAR,
+	"send 11k beacon measurement request\n"
+	"\tUsage: wl rrm_bcn_req [bcn mode] [da] [duration] [random int] [channel] [ssid]"
+	" [repetitions]"},
+	{ "rrm_chload_req", wl_rrm_chload_req, -1, WLC_SET_VAR,
+	"send 11k channel load measurement request\n"
+	"\tUsage: wl rrm_chload_req [regulatory] [da] [duration] [random int] [channel]"
+	" [repetitions]"},
+	{ "rrm_noise_req", wl_rrm_noise_req, -1, WLC_SET_VAR,
+	"send 11k noise measurement request\n"
+	"\tUsage: wl rrm_noise_req [regulatory] [da] [duration] [random int] [channel]"
+	" [repetitions] "},
+	{ "rrm_frame_req", wl_rrm_frame_req, -1, WLC_SET_VAR,
+	"send 11k frame measurement request\n"
+	"\tUsage: wl rrm_frame_req [regulatory] [da] [duration] [random int] [channel] [ta]"
+	" [repetitions]"},
+	{ "rrm_stat_req", wl_rrm_stat_req, -1, WLC_SET_VAR,
+	"send 11k stat measurement request\n"
+	"\tUsage: wl rrm_stat_req [da] [random int] [duration] [peer] [group id] [repetitions]"},
+	{ "rrm_stat_rpt", wl_rrm_stat_rpt, -1, WLC_GET_VAR,
+	"Read 11k stat measurement report from STA\n"
+	"\tUsage: wl rrm_stat_rpt [mac]"},
+	{ "rrm_lm_req", wl_rrm_lm_req, -1, WLC_SET_VAR,
+	"send 11k link measurement request\n"
+	"\tUsage: wl rrm_lm_req [da]"},
+	{ "rrm_nbr_req", wl_rrm_nbr_req, -1, WLC_SET_VAR,
+	"send 11k neighbor report measurement request\n"
+	"\tUsage: wl rrm_nbr_req [ssid]"},
+	{ "rrm_nbr_list", wl_rrm_nbr_list, WLC_GET_VAR, -1,
+	"get 11k neighbor report list\n"
+	"\tUsage: wl rrm_nbr_list"},
+	{ "rrm_nbr_del_nbr", wl_rrm_nbr_del_nbr, -1, WLC_SET_VAR,
+	"delete node from 11k neighbor report list\n"
+	"\tUsage: wl rrm_nbr_del_nbr [bssid]"},
+	{ "rrm_nbr_add_nbr", wl_rrm_nbr_add_nbr, -1, WLC_SET_VAR,
+	"add node to 11k neighbor report list\n"
+	"\tUsage: wl rrm_nbr_add_nbr [bssid] [bssid info] [regulatory] [channel] [phytype]"},
+	{ "rrm_config", wl_rrm_config, -1, WLC_SET_VAR,
+	"Configure information (LCI/Civic location) for self\n"
+	"\tUsage: wl rrm_config lci [lci_location]\n"
+	"\tUsage: wl rrm_config civic [civic_location]"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_rrm_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register rrm commands */
+	wl_module_cmds_register(wl_rrm_cmds);
+}
+
+/* RM Enable Capabilities */
+static dbg_msg_t rrm_msgs[] = {
+	{DOT11_RRM_CAP_LINK,	"Link_Measurement"},				/* bit0 */
+	{DOT11_RRM_CAP_NEIGHBOR_REPORT,	"Neighbor_Report"},			/* bit1 */
+	{DOT11_RRM_CAP_PARALLEL,	"Parallel_Measurement"},		/* bit2 */
+	{DOT11_RRM_CAP_REPEATED,	"Repeated_Measurement"},		/* bit3 */
+	{DOT11_RRM_CAP_BCN_PASSIVE,	"Beacon_Passive"},			/* bit4 */
+	{DOT11_RRM_CAP_BCN_ACTIVE,	"Beacon_Active"},			/* bit5 */
+	{DOT11_RRM_CAP_BCN_TABLE,	"Beacon_Table"},			/* bit6 */
+	{DOT11_RRM_CAP_BCN_REP_COND,	"Beacon_measurement_Reporting_Condition"}, /* bit7 */
+	{DOT11_RRM_CAP_FM,	"Frame_Measurement"},				/* bit8 */
+	{DOT11_RRM_CAP_CLM,	"Channel_load_Measurement"},			/* bit9 */
+	{DOT11_RRM_CAP_NHM,	"Noise_Histogram_measurement"},			/* bit10 */
+	{DOT11_RRM_CAP_SM,	"Statistics_Measurement"},			/* bit11 */
+	{DOT11_RRM_CAP_LCIM,	"LCI_Measurement"},				/* bit12 */
+	{DOT11_RRM_CAP_LCIA,	"LCI_Azimuth"},					/* bit13 */
+	{DOT11_RRM_CAP_TSCM,	"Tx_Stream_Category_Measurement"},		/* bit14 */
+	{DOT11_RRM_CAP_TTSCM,	"Triggered_Tx_stream_Category_Measurement"},	/* bit15 */
+	{DOT11_RRM_CAP_AP_CHANREP,	"AP_Channel_Report"},			/* bit16 */
+	{DOT11_RRM_CAP_RMMIB,	"RM_MIB"},					/* bit17 */
+	/* bit 18-26, unused */
+	{DOT11_RRM_CAP_MPTI,	"Measurement_Pilot_Transmission_Information"},	/* bit27 */
+	{DOT11_RRM_CAP_NBRTSFO,	"Neighbor_Report_TSF_Offset"},			/* bit28 */
+	{DOT11_RRM_CAP_RCPI,	"RCPI_Measurement"},				/* bit29 */
+	{DOT11_RRM_CAP_RSNI,	"RSNI_Measurement"},				/* bit30 */
+	{DOT11_RRM_CAP_BSSAAD,	"BSS_Average_Access_Delay"},			/* bit31 */
+	{DOT11_RRM_CAP_BSSAAC,	"BSS_Available_Admission_Capacity"},		/* bit32 */
+	{DOT11_RRM_CAP_AI,	"Antenna_Information"},				/* bit33 */
+	{DOT11_RRM_CAP_FTM_RANGE,	"FTM_Range_Reporting"},			/* bit34 */
+	{DOT11_RRM_CAP_CIVIC_LOC,	"Civic_Location_Measurement"},		/* bit35 */
+	{0,		NULL}
+};
+
+static bool rrm_input_validation(uint val, uint hval, dbg_msg_t *dbg_msg)
+{
+	int i;
+	uint32 flag = 0;
+
+	if ((val == 0) && (hval == 0))
+		return TRUE;
+
+	for (i = 0; dbg_msg[i].value <= DOT11_RRM_CAP_BSSAAD; i++)
+		flag |= 1 << dbg_msg[i].value;
+	flag = ~flag;
+	if (val & flag)
+		return FALSE;
+
+	flag = 0;
+	if (hval != 0) {
+		for (; dbg_msg[i].value; i++) {
+			flag |= 1 << (dbg_msg[i].value - DOT11_RRM_CAP_BSSAAC);
+		}
+		flag = ~flag;
+		if (hval & flag)
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+static int
+wl_rrm(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, i;
+	uint hval = 0, val = 0, len, found, rmcap_del = 0, rmcap2_del = 0;
+	uint rmcap_add = 0, rmcap2_add = 0;
+	char *endptr = NULL;
+	dbg_msg_t *dbg_msg = rrm_msgs;
+	void *ptr = NULL;
+	dot11_rrm_cap_ie_t rrm_cap, *reply;
+	uint high = 0, low = 0, bit = 0, hbit = 0;
+	const char *cmdname = "rrm";
+	char *s = NULL;
+	char t[32], c[32] = "0x";
+
+	UNUSED_PARAMETER(cmd);
+
+	err = wlu_var_getbuf_sm(wl, cmdname, &rrm_cap, sizeof(rrm_cap), &ptr);
+	if (err < 0)
+		return err;
+	reply = (dot11_rrm_cap_ie_t *)ptr;
+
+	high = reply->cap[4];
+	low = reply->cap[0] | (reply->cap[1] << 8) | (reply->cap[2] << 16) | (reply->cap[3] << 24);
+	if (!*++argv) {
+		if (high != 0)
+			printf("0x%x%08x", high, low);
+		else
+			printf("0x%x ", low);
+		for (i = 0; ((bit = dbg_msg[i].value) <= DOT11_RRM_CAP_BSSAAD); i++) {
+			if (low & (1 << bit))
+				printf(" %s", dbg_msg[i].string);
+		}
+		for (; (hbit = dbg_msg[i].value); i++) {
+			if (high & (1 << (hbit - DOT11_RRM_CAP_BSSAAC)))
+				printf(" %s", dbg_msg[i].string);
+		}
+		printf("\n");
+
+		return err;
+	}
+	while (*argv) {
+		s = *argv;
+
+		found = 0;
+		if (*s == '+' || *s == '-')
+			s++;
+		else {
+			/* used for clearing previous value */
+			rmcap_del = ~0;
+			rmcap2_del = ~0;
+		}
+		val = strtoul(s, &endptr, 0);
+		/* Input is decimal number or hex with prefix 0x and > 32 bits */
+		if (val == 0xFFFFFFFF) {
+			if (!(*s == '0' && *(s+1) == 'x')) {
+				fprintf(stderr,
+				"Msg bits >32 take only numerical input in hex\n");
+				val = 0;
+			} else {
+				/* Input number with prefix 0x */
+				len = strlen(s);
+				hval = strtoul(strncpy(t, s, len-8), &endptr, 0);
+				*endptr = 0;
+				s = s + strlen(t);
+				s = strcat(c, s);
+				val = strtoul(s, &endptr, 0);
+				/* Input number > 64bit */
+				if (hval == 0xFFFFFFFF) {
+					fprintf(stderr, "Invalid entry for RM Capabilities\n");
+					hval = 0;
+					val = 0;
+				}
+			}
+		}
+		/* validet the input number */
+		if (!rrm_input_validation(val, hval, dbg_msg))
+			goto usage;
+		/* Input is a string */
+		if (*endptr != '\0') {
+			for (i = 0; ((bit = dbg_msg[i].value) <= DOT11_RRM_CAP_BSSAAD); i++) {
+				if (stricmp(dbg_msg[i].string, s) == 0) {
+					found = 1;
+					break;
+				}
+			}
+			if (!found) {
+				for (; (hbit = dbg_msg[i].value); i++) {
+					if (stricmp(dbg_msg[i].string, s) == 0)
+						break;
+				}
+				if (hbit)
+					hval = 1 << (hbit - DOT11_RRM_CAP_BSSAAC);
+				else
+					hval = 0;
+			} else {
+				val = 1 << bit;
+			}
+			if (!val && !hval)
+			      goto usage;
+		}
+		if (**argv == '-') {
+			rmcap_del |= val;
+			if (!found)
+				rmcap2_del |= hval;
+		}
+		else {
+			rmcap_add |= val;
+			if (!found)
+				rmcap2_add |= hval;
+		}
+		++argv;
+	}
+
+	low &= ~rmcap_del;
+	high &= ~rmcap2_del;
+	low |= rmcap_add;
+	high |= rmcap2_add;
+
+	rrm_cap.cap[4] = high;
+	rrm_cap.cap[0] = low & 0x000000ff;
+	rrm_cap.cap[1] = (low & 0x0000ff00) >> 8;
+	rrm_cap.cap[2] = (low & 0x00ff0000) >> 16;
+	rrm_cap.cap[3] = (low & 0xff000000) >> 24;
+
+	err = wlu_var_setbuf(wl, cmdname, &rrm_cap, sizeof(dot11_rrm_cap_ie_t));
+	return err;
+
+usage:
+	fprintf(stderr, "msg values may be a list of numbers or names from the following set.\n");
+	fprintf(stderr, "Use a + or - prefix to make an incremental change.");
+	for (i = 0; (bit = dbg_msg[i].value) <= DOT11_RRM_CAP_BSSAAD; i++) {
+		fprintf(stderr, "\n0x%04x %s", (1 << bit), dbg_msg[i].string);
+	}
+	for (; (hbit = dbg_msg[i].value); i++) {
+		hbit -= DOT11_RRM_CAP_BSSAAC;
+		fprintf(stderr, "\n0x%x00000000 %s", (1 << hbit), dbg_msg[i].string);
+	}
+	fprintf(stderr, "\n");
+	return BCME_OK;
+}
+
+static int
+wl_rrm_stat_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_stat_req";
+	statreq_t sreq_buf;
+
+	UNUSED_PARAMETER(cmd);
+	memset(&sreq_buf, 0, sizeof(statreq_t));
+
+	if (argv[1]) {
+		/* da */
+		if (!wl_ether_atoe(argv[1], &sreq_buf.da)) {
+			printf("wl_rrm_stat_req parsing da failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* random interval */
+	if (argv[2]) {
+		sreq_buf.random_int = htod32(strtoul(argv[2], NULL, 0));
+	}
+	/* duration */
+	if (argv[3]) {
+		sreq_buf.dur = htod32(strtoul(argv[3], NULL, 0));
+	}
+	/* peer address */
+	if (argv[4]) {
+		if (!wl_ether_atoe(argv[4], &sreq_buf.peer)) {
+			printf("wl_rrm_stat_req parsing peer failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* group id */
+	if (argv[5]) {
+		sreq_buf.group_id =
+			htod32(strtoul(argv[5], NULL, 0));
+	}
+	/* repetitions */
+	if (argv[6]) {
+		sreq_buf.reps = htod32(strtoul(argv[6], NULL, 0));
+	}
+	err = wlu_iovar_set(wl, cmdname, &sreq_buf, sizeof(sreq_buf));
+	return err;
+}
+
+static int
+wl_rrm_stat_rpt(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret = BCME_USAGE_ERROR;
+	statrpt_t *rpt_ptr, rpt;
+	int cnt;
+
+	if (!*++argv) return -1;
+
+	/* get sta mac address */
+	if (!wl_ether_atoe(*argv++, &rpt.addr))
+		goto done;
+
+	rpt.ver = htod16(WL_RRM_RPT_VER);
+	memset(buf, 0, WLC_IOCTL_MEDLEN);
+	if ((ret = wlu_iovar_getbuf(wl, cmd->name, (void *) &rpt,
+		sizeof(rpt), buf, WLC_IOCTL_MEDLEN)) < 0) {
+		fprintf(stderr, "ERROR: cmd:%s\n", cmd->name);
+		goto done;
+	}
+
+	/* display the sta info */
+	rpt_ptr = (statrpt_t *)buf;
+	rpt_ptr->ver = dtoh16(rpt_ptr->ver);
+
+	/* Report unrecognized version */
+	if (rpt_ptr->ver != WL_RRM_RPT_VER) {
+		fprintf(stderr, "ERROR: Mismatch ver[%d] Driver ver[%d]\n",
+			WL_RRM_RPT_VER, rpt_ptr->ver);
+		goto done;
+	}
+
+	printf("ver:%d timestamp:%u flag:%d len:%d\n",
+		rpt_ptr->ver, dtoh32(rpt_ptr->timestamp),
+		dtoh16(rpt_ptr->flag), rpt_ptr->len);
+	for (cnt = 0; cnt < rpt_ptr->len; cnt++) {
+		if (cnt % 8 == 0)
+			printf("\n[%d]:", cnt);
+		printf("[0x%02x][%d] ", rpt_ptr->data[cnt], (signed char)(rpt_ptr->data[cnt]));
+	}
+	printf("\n");
+
+done:
+	return ret;
+}
+
+static int
+wl_rrm_frame_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_frame_req";
+	framereq_t freq_buf;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(&freq_buf, 0, sizeof(framereq_t));
+	if (argv[1]) {
+		/* Regulatory class */
+		freq_buf.reg = htod32(strtoul(argv[1], NULL, 0));
+	}
+
+	/* da */
+	if (argv[2]) {
+		if (!wl_ether_atoe(argv[2], &freq_buf.da)) {
+			printf("wl_rrm_frame_req parsing da failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* duration */
+	if (argv[3]) {
+		freq_buf.dur = htod32(strtoul(argv[3], NULL, 0));
+	}
+	/* random interval */
+	if (argv[4]) {
+		freq_buf.random_int = htod32(strtoul(argv[4], NULL, 0));
+	}
+	/* channel */
+	if (argv[5]) {
+		freq_buf.chan = htod32(strtoul(argv[5], NULL, 0));
+	}
+	/* transmit address */
+	if (argv[6]) {
+		if (!wl_ether_atoe(argv[6], &freq_buf.ta)) {
+			printf("wl_rrm_frame_req parsing ta failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* repetitions */
+	if (argv[7]) {
+		freq_buf.reps = htod32(strtoul(argv[7], NULL, 0));
+	}
+	err = wlu_iovar_set(wl, cmdname, &freq_buf, sizeof(freq_buf));
+	return err;
+}
+
+static int
+wl_rrm_chload_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_chload_req";
+	rrmreq_t chreq_buf;
+
+	UNUSED_PARAMETER(cmd);
+	memset(&chreq_buf, 0, sizeof(rrmreq_t));
+
+	if (argv[1]) {
+		/* Regulatory class */
+		chreq_buf.reg = htod32(strtoul(argv[1], NULL, 0));
+	}
+	/* da */
+	if (argv[2]) {
+		if (!wl_ether_atoe(argv[2], &chreq_buf.da)) {
+			printf("wl_rrm_chload_req parsing da failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* duration */
+	if (argv[3]) {
+		chreq_buf.dur = htod32(strtoul(argv[3], NULL, 0));
+	}
+	/* random interval */
+	if (argv[4]) {
+		chreq_buf.random_int = htod32(strtoul(argv[4], NULL, 0));
+	}
+	/* channel */
+	if (argv[5]) {
+		chreq_buf.chan = htod32(strtoul(argv[5], NULL, 0));
+	}
+	/* repetitions */
+	if (argv[6]) {
+		chreq_buf.reps = htod32(strtoul(argv[6], NULL, 0));
+	}
+	err = wlu_iovar_set(wl, cmdname, &chreq_buf, sizeof(chreq_buf));
+	return err;
+}
+
+static int
+wl_rrm_noise_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_noise_req";
+	rrmreq_t nreq_buf;
+
+	UNUSED_PARAMETER(cmd);
+	printf("wl_rrm_noise_req\n");
+
+	memset(&nreq_buf, 0, sizeof(rrmreq_t));
+	if (argv[1]) {
+		/* Regulatory class */
+		nreq_buf.reg = htod32(strtoul(argv[1], NULL, 0));
+	}
+	/* da */
+	if (argv[2]) {
+		if (!wl_ether_atoe(argv[2], &nreq_buf.da)) {
+			printf("wl_rrm_noise_req parsing da failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* duration */
+	if (argv[3]) {
+		nreq_buf.dur = htod32(strtoul(argv[3], NULL, 0));
+
+	}
+	/* random interval */
+	if (argv[4]) {
+		nreq_buf.random_int = htod32(strtoul(argv[4], NULL, 0));
+	}
+	/* channel */
+	if (argv[5]) {
+		nreq_buf.chan = htod32(strtoul(argv[5], NULL, 0));
+	}
+	/* repetitions */
+	if (argv[6]) {
+		nreq_buf.reps = htod32(strtoul(argv[6], NULL, 0));
+	}
+	err = wlu_iovar_set(wl, cmdname, &nreq_buf, sizeof(nreq_buf));
+	return err;
+}
+
+static int
+wl_rrm_bcn_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	uint8 mode = 0;
+	const char *cmdname = "rrm_bcn_req";
+	bcnreq_t bcnreq_buf;
+	wlc_ssid_t ssid;
+
+	UNUSED_PARAMETER(cmd);
+	memset(&bcnreq_buf, 0, sizeof(bcnreq_t));
+
+	if (argv[1]) {
+		/* bcn mode: ACTIVE/PASSIVE/SCAN_CACHE */
+		mode = htod32(strtoul(argv[1], NULL, 0));
+		if (mode > 2) {
+			printf("wl_rrm_bcn_req parsing bcn mode failed\n");
+			return BCME_BADARG;
+		}
+		bcnreq_buf.bcn_mode = mode;
+	}
+	/* da */
+	if (argv[2]) {
+		if (!wl_ether_atoe(argv[2], &bcnreq_buf.da)) {
+			printf("wl_rrm_bcn_req parsing da failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	/* duration */
+	if (argv[3]) {
+		bcnreq_buf.dur = htod32(strtoul(argv[3], NULL, 0));
+	}
+
+	/* random interval */
+	if (argv[4]) {
+		bcnreq_buf.random_int = htod32(strtoul(argv[4], NULL, 0));
+	}
+
+	/* channel */
+	if (argv[5]) {
+		bcnreq_buf.channel = htod32(strtoul(argv[5], NULL, 0));
+	}
+	printf("wl_rrm_bcn_req:bcn mode: %d, duration: %d, "
+			"chan: %d\n", mode,
+			bcnreq_buf.dur, bcnreq_buf.channel);
+
+	/* SSID */
+	if (argv[6]) {
+		uint32 len;
+
+		len = strlen(argv[6]);
+		if (len > DOT11_MAX_SSID_LEN) {
+			printf("ssid too long\n");
+			return BCME_BADARG;
+		}
+		memset(&ssid, 0, sizeof(wlc_ssid_t));
+		memcpy(ssid.SSID, argv[6], len);
+		ssid.SSID_len = len;
+		memcpy(&bcnreq_buf.ssid, &ssid, sizeof(wlc_ssid_t));
+	}
+
+	/* repetitions */
+	if (argv[7]) {
+		bcnreq_buf.reps = htod32(strtoul(argv[7], NULL, 0));
+	}
+
+	err = wlu_iovar_set(wl, cmdname, &bcnreq_buf, sizeof(bcnreq_buf));
+	return err;
+}
+
+static int
+wl_rrm_lm_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_lm_req";
+
+	struct ether_addr da;
+	UNUSED_PARAMETER(cmd);
+
+	if (argv[1]) {
+		if (!wl_ether_atoe(argv[1], &da)) {
+			printf("wl_rrm_lm_req parsing arg1 failed\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	err = wlu_iovar_set(wl, cmdname, &da, sizeof(da));
+	return err;
+}
+
+static int
+wl_rrm_nbr_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wlc_ssid_t ssid;
+
+	UNUSED_PARAMETER(cmd);
+
+	strcpy(buf, "rrm_nbr_req");
+	buflen = strlen("rrm_nbr_req") + 1;
+
+	if (*++argv) {
+		uint32 len;
+
+		len = strlen(*argv);
+		if (len > DOT11_MAX_SSID_LEN) {
+			printf("ssid too long\n");
+			return BCME_BADARG;
+		}
+		memset(&ssid, 0, sizeof(wlc_ssid_t));
+		memcpy(ssid.SSID, *argv, len);
+		ssid.SSID_len = len;
+		memcpy(&buf[buflen], &ssid, sizeof(wlc_ssid_t));
+		buflen += sizeof(wlc_ssid_t);
+	}
+
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+/* For mapping customer's user space command, two calls of the same iovar. */
+static int
+wl_rrm_nbr_list(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0, buflen, i;
+	uint16 list_cnt;
+	nbr_element_t *nbr_elt;
+	uint8 *ptr;
+
+	UNUSED_PARAMETER(cmd);
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "rrm_nbr_list");
+	buflen = strlen("rrm_nbr_list") + 1;
+
+	if (*++argv != NULL)
+		return BCME_USAGE_ERROR;
+
+	if ((err = wlu_get(wl, WLC_GET_VAR, buf, buflen)) < 0)
+		return err;
+
+	list_cnt = *(uint16 *)buf;
+
+	if (list_cnt == 0)
+		return err;
+
+	memset(buf, 0, WLC_IOCTL_MAXLEN);
+	strcpy(buf, "rrm_nbr_list");
+	buflen = strlen("rrm_nbr_list") + 1;
+
+	memcpy(&buf[buflen], &list_cnt, sizeof(uint16));
+
+	printf("RRM Neighbor Report List:\n");
+
+	if ((err = wlu_get(wl, WLC_GET_VAR, buf, WLC_IOCTL_MAXLEN)) < 0)
+		return err;
+
+	ptr = (uint8 *)buf;
+
+	for (i = 0; i < list_cnt; i++) {
+		nbr_elt = (nbr_element_t *)ptr;
+		printf("AP %2d: ", i + 1);
+		printf("bssid %02x:%02x:%02x:%02x:%02x:%02x ", nbr_elt->bssid.octet[0],
+			nbr_elt->bssid.octet[1], nbr_elt->bssid.octet[2], nbr_elt->bssid.octet[3],
+			nbr_elt->bssid.octet[4], nbr_elt->bssid.octet[5]);
+
+		printf("bssid_info %08x ", load32_ua(&nbr_elt->bssid_info));
+		printf("reg %2d channel %3d phytype %d\n", nbr_elt->reg,
+			nbr_elt->channel, nbr_elt->phytype);
+
+		ptr += TLV_HDR_LEN + DOT11_NEIGHBOR_REP_IE_FIXED_LEN;
+	}
+
+	return err;
+}
+
+static int
+wl_rrm_nbr_del_nbr(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	const char *cmdname = "rrm_nbr_del_nbr";
+	struct ether_addr ea;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv == NULL) {
+		printf("no bssid specified\n");
+		return BCME_USAGE_ERROR;
+	} else {
+		if (!wl_ether_atoe(*argv, &ea)) {
+			printf("Incorrect bssid format\n");
+			return BCME_ERROR;
+		}
+		err = wlu_iovar_set(wl, cmdname, &ea, sizeof(ea));
+	}
+
+	return err;
+}
+
+static int
+wl_rrm_nbr_add_nbr(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = 0;
+	const char *cmdname = "rrm_nbr_add_nbr";
+	nbr_element_t nbr_elt;
+
+	UNUSED_PARAMETER(cmd);
+	memset(&nbr_elt, 0, sizeof(nbr_element_t));
+
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (argc != 6)
+		return BCME_USAGE_ERROR;
+
+	/* bssid */
+	if (!wl_ether_atoe(argv[1], &nbr_elt.bssid)) {
+		printf("wl_rrm_nbr_add_nbr parsing bssid failed\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* bssid info */
+	nbr_elt.bssid_info = htod32(strtoul(argv[2], NULL, 0));
+
+	/* Regulatory class */
+	nbr_elt.reg = htod32(strtoul(argv[3], NULL, 0));
+
+	/* channel */
+	nbr_elt.channel = htod32(strtoul(argv[4], NULL, 0));
+
+	/* phytype */
+	nbr_elt.phytype = htod32(strtoul(argv[5], NULL, 0));
+
+	nbr_elt.id = DOT11_MNG_NEIGHBOR_REP_ID;
+	nbr_elt.len = DOT11_NEIGHBOR_REP_IE_FIXED_LEN;
+
+	err = wlu_iovar_set(wl, cmdname, &nbr_elt, TLV_HDR_LEN + DOT11_NEIGHBOR_REP_IE_FIXED_LEN);
+	return err;
+}
+
+static int
+wl_rrm_parse_location(char *loc_arg, char *bufptr, int buflen)
+{
+	int len = 0;
+	char *ptr = loc_arg;
+	char hex[] = "XX";
+
+	if (!loc_arg) {
+		printf("%s: Location data is missing\n", __FUNCTION__);
+		len = -1;
+		goto done;
+	}
+
+	len = strlen(loc_arg)/2;
+	if ((len <= 0) || (len > buflen)) {
+		len = -1;
+		goto done;
+	}
+
+	if ((uint16)strlen(ptr) != len*2) {
+		printf("%s: Invalid length. Even number of characters expected.\n",
+			__FUNCTION__);
+		len = -1;
+		goto done;
+	}
+
+	while (*ptr) {
+		strncpy(hex, ptr, 2);
+		*bufptr++ = (char) strtoul(hex, NULL, 16);
+		ptr += 2;
+	}
+done:
+	return len;
+}
+
+
+static int
+wl_rrm_self_lci_civic(void *wl, cmd_t *cmd, char **argv, int argc, int cmd_id)
+{
+	int err = BCME_OK;
+	int len = 0;
+	char *bufptr;
+	wl_rrm_config_ioc_t *rrm_config_cmd = NULL;
+	wl_rrm_config_ioc_t rrm_config_param;
+	int malloc_len = sizeof(*rrm_config_cmd) + TLV_BODY_LEN_MAX -
+		DOT11_MNG_IE_MREP_FIXED_LEN;
+
+	rrm_config_cmd = (wl_rrm_config_ioc_t *) calloc(1, malloc_len);
+	if (rrm_config_cmd == NULL) {
+		printf("Failed to allocate buffer of %d bytes\n", malloc_len);
+		err = BCME_NOMEM;
+		goto done;
+	}
+
+	rrm_config_cmd->id = cmd_id;
+
+	if (argc == 3) {
+		bufptr = (char *)&rrm_config_cmd->data[0];
+		len = wl_rrm_parse_location(argv[1], bufptr, TLV_BODY_LEN_MAX -
+				DOT11_MNG_IE_MREP_FIXED_LEN);
+		if (len <= 0) {
+			printf("%s: parsing location arguments failed\n", __FUNCTION__);
+			err = BCME_USAGE_ERROR;
+			goto done;
+		}
+
+		rrm_config_cmd->len = len;
+		err = wlu_iovar_set(wl, cmd->name, (void *)rrm_config_cmd,
+				WL_RRM_CONFIG_MIN_LENGTH + len);
+		goto done;
+
+	} else if (argc == 2) {
+		memset(&rrm_config_param, 0, sizeof(rrm_config_param));
+		rrm_config_param.id = cmd_id;
+		err = wlu_iovar_getbuf(wl, cmd->name, (void *)&rrm_config_param,
+				sizeof(rrm_config_param), (void *)rrm_config_cmd, malloc_len);
+		if (err < 0) {
+			printf("wlu_iov_get for \"%s\" returned error %d\n", cmd->name, err);
+			goto done;
+		}
+
+		prhex(cmd_id == WL_RRM_CONFIG_GET_CIVIC ? "Self Civic data" : "Self LCI data",
+			rrm_config_cmd->data, rrm_config_cmd->len);
+		printf("\n");
+	} else {
+		err = BCME_USAGE_ERROR;
+	}
+done:
+	if (rrm_config_cmd)
+		free(rrm_config_cmd);
+
+	return err;
+}
+
+static int
+wl_rrm_config(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_OK;
+	int argc = 0;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!argv[1]) {
+		printf("%s: no element type given, must be lci or civic\n", __FUNCTION__);
+		err = BCME_USAGE_ERROR;
+		goto done;
+	}
+
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	if (strcmp(argv[1], "lci") == 0) {
+		argv++;
+		err = wl_rrm_self_lci_civic(wl, cmd, argv, argc,
+				(argc == 3) ? WL_RRM_CONFIG_SET_LCI : WL_RRM_CONFIG_GET_LCI);
+	} else if (strcmp(argv[1], "civic") == 0) {
+		argv++;
+		err = wl_rrm_self_lci_civic(wl, cmd, argv, argc,
+				(argc == 3) ? WL_RRM_CONFIG_SET_CIVIC : WL_RRM_CONFIG_GET_CIVIC);
+	} else {
+		printf("%s: incorrect element type, not lci or civic\n", __FUNCTION__);
+		err = BCME_USAGE_ERROR;
+	}
+done:
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_rsdb.c b/wl/src/wl/exe/wluc_rsdb.c
new file mode 100644
index 0000000..f5745e6
--- /dev/null
+++ b/wl/src/wl/exe/wluc_rsdb.c
@@ -0,0 +1,358 @@
+/*
+ * wl rsdb command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_rsdb.c $
+ */
+#ifdef WLRSDB
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <wlioctl.h>
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_rsdb_caps;
+static cmd_func_t wl_rsdb_bands;
+static cmd_func_t wl_rsdb_config;
+
+static int wl_parse_infra_mode_list(char *list_str, uint8* list, int list_num);
+static int wl_parse_SIB_param_list(char *list_str, uint32* list, int list_num);
+
+static cmd_t wl_rsdb_cmds[] = {
+	{"rsdb_caps", wl_rsdb_caps, WLC_GET_VAR, -1,
+	"Get rsdb capabilities for given chip\n"
+	"\tUsage : wl rsdb_caps"},
+	{"rsdb_bands", wl_rsdb_bands, WLC_GET_VAR, -1,
+	"Get band of each wlc/core"
+	"\tUsage : wl rsdb_bands"},
+	{"rsdb_config", wl_rsdb_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set rsdb config\n"
+	"\t wl rsdb_config -n <NonInfraMode> -i <Infra(2G),Infra(5G)> -p <SIB(2G),SIB(5G)> \n"
+	"\t-n : <NonInfraMode> Default mode of operation of the device "
+	"\t-i : <InfraMode> target mode of operation for Infra 2G/5G connection"
+	"\t-p : <allowSIBParallelScan> Allow 2G/5G SIB parallel passive scan"
+	"\t SDB op Modes:"
+	"\t\tWLC_SDB_MODE_NOSDB_MAIN = 1 :NoSDB mode and Infra is on core 0"
+	"\t\tWLC_SDB_MODE_NOSDB_AUX = 2 :NoSDB mode and Infra is on core 1 "
+	"\t\tWLC_SDB_MODE_SDB_MAIN = 3 : SDB mode and infra on core-0"
+	"\t\tWLC_SDB_MODE_SDB_AUX = 4 : SDB mode and infra on core-1"
+	"\t\tWLC_SDB_MODE_SDB_AUTO = 5 : SDB mode and auto infra"
+	"Ex : rsdb_config -n 5 -i 5,1 -p 1,1"
+	},
+	{ NULL, NULL, 0, 0, NULL },
+};
+static char *buf;
+
+/* module initialization */
+void
+wluc_rsdb_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register scan commands */
+	wl_module_cmds_register(wl_rsdb_cmds);
+}
+
+static const struct {
+	uint8 state;
+	char name[28];
+} sdb_op_modes[] = {
+	{WLC_SDB_MODE_NOSDB_MAIN, "NOSDB_MAIN"},
+	{WLC_SDB_MODE_NOSDB_AUX, "NOSDB_AUX"},
+	{WLC_SDB_MODE_SDB_MAIN, "SDB_MAIN"},
+	{WLC_SDB_MODE_SDB_AUX, "SDB_AUX"},
+	{WLC_SDB_MODE_SDB_AUTO, "SDB_AUTO"}
+};
+
+static const char *
+wlc_sdb_op_mode_name(uint8 state)
+{
+	uint i;
+	for (i = 0; i < ARRAYSIZE(sdb_op_modes); i++) {
+		if (sdb_op_modes[i].state == state)
+			return sdb_op_modes[i].name;
+	}
+	return "UNKNOWN";
+}
+static const struct {
+	uint8 state;
+	char name[28];
+} rsdb_band_names[] = {
+	{WLC_BAND_AUTO, "AUTO"},
+	{WLC_BAND_2G, "2G"},
+	{WLC_BAND_5G, "5G"},
+	{WLC_BAND_ALL, "ALL"},
+	{WLC_BAND_INVALID, "INVALID"}
+};
+static const char *
+wlc_rsdb_band_name(uint8 state)
+{
+	uint i;
+	for (i = 0; i < ARRAYSIZE(rsdb_band_names); i++) {
+		if (rsdb_band_names[i].state == state)
+			return rsdb_band_names[i].name;
+	}
+	return "UNKNOWN";
+}
+static int
+wl_rsdb_caps(void *wl, cmd_t *cmd, char **argv)
+{
+		int err, i;
+		rsdb_caps_response_t *rsdb_caps_ptr = NULL;
+
+		argv++;
+		printf("in rsdb caps\n");
+		if (*argv == NULL) {
+			/* get */
+			err = wlu_var_getbuf_sm(wl, cmd->name, NULL, 0, (void *)&rsdb_caps_ptr);
+			if (err < 0) {
+				printf("%s(): wlu_var_getbuf failed %d \r\n", __FUNCTION__, err);
+			} else {
+				if (rsdb_caps_ptr->ver != WL_RSDB_CAPS_VER) {
+					printf("Bad version : %d\n", rsdb_caps_ptr->ver);
+					return BCME_VERSION;
+				}
+				if (rsdb_caps_ptr->len >= WL_RSDB_CAPS_FIXED_LEN) {
+					printf("**RSDB CAPABILITIES**\n");
+					printf("RSDB: %d\n", rsdb_caps_ptr->rsdb);
+					printf("Num of cores: %d\n", rsdb_caps_ptr->num_of_cores);
+					printf("Flags: ");
+					if (rsdb_caps_ptr->flags & SYNCHRONOUS_OPERATION_TRUE)
+						printf("\tSynchronous Operation supported\n");
+					printf("\n");
+					/* Add in more capabilites here */
+					for (i = 0; i < rsdb_caps_ptr->num_of_cores; i++) {
+						printf("Num of chains in core-%d: %d\n", i,
+						rsdb_caps_ptr->num_chains[i]);
+					}
+				}
+			}
+		} else {
+			/* set not allowed */
+			return USAGE_ERROR;
+		}
+		return err;
+}
+
+static int
+wl_rsdb_bands(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint8 i;
+	rsdb_bands_t *ptr;
+
+	memset(&ptr, 0, sizeof(*ptr));
+	argv++;
+
+	if (*argv == NULL) {
+		/* get */
+		err = wlu_var_getbuf_sm(wl, cmd->name, NULL, 0, (void *)&ptr);
+		if (err < 0) {
+			printf("%s(): wlu_var_getbuf_sm failed %d \r\n", __FUNCTION__, err);
+		} else {
+			/* Check return value of version */
+			if (ptr->ver != WL_RSDB_BANDS_VER) {
+				printf("Bad version : %d\n", ptr->ver);
+				return BCME_VERSION;
+			}
+			if (ptr->len >= WL_RSDB_BANDS_FIXED_LEN) {
+				printf("Num of cores:%d\n", ptr->num_cores);
+				for (i = 0; i < ptr->num_cores; i++) {
+					printf("WLC[%d]: %s\n", i,
+						wlc_rsdb_band_name(ptr->band[i]));
+				}
+			}
+		}
+	} else {
+		/* set not allowed */
+		return USAGE_ERROR;
+	}
+	return err;
+}
+static int
+wl_rsdb_config(void *wl, cmd_t *cmd, char **argv)
+{
+	rsdb_config_t rsdb_config;
+	int err, i;
+	char opt, *p, *endptr = NULL;
+
+	memset(&rsdb_config, 0, sizeof(rsdb_config));
+
+	if (!*++argv) {
+		if ((err = wlu_iovar_get(wl, cmd->name, &rsdb_config,
+			sizeof(rsdb_config))) < 0) {
+			return err;
+		}
+		if (rsdb_config.ver != WL_RSDB_CONFIG_VER) {
+			err = BCME_VERSION;
+			goto exit;
+		}
+		if (rsdb_config.len >= WL_RSDB_CONFIG_LEN) {
+
+			printf("NonInfraMode:%s\n",
+				wlc_sdb_op_mode_name(rsdb_config.non_infra_mode));
+
+			for (i = 0; i < MAX_BANDS; i++) {
+				printf("InfraMode(%s):%s\n", (i == 0) ? "2G":"5G",
+					wlc_sdb_op_mode_name(rsdb_config.infra_mode[i]));
+			}
+			for (i = 0; i < MAX_BANDS; i++) {
+				printf("SIB Scan(%s):", (i == 0) ? "2G":"5G");
+				printf("%s\n",
+					(rsdb_config.flags[i] & ALLOW_SIB_PARALLEL_SCAN) ?
+						"ENABLED":"DISABLED");
+			}
+			printf("Current_mode: %s\n",
+				wlc_sdb_op_mode_name(rsdb_config.current_mode));
+		}
+	} else {
+			/* Get the existing config and change only the fields passed */
+			if ((err = wlu_iovar_get(wl, cmd->name, &rsdb_config,
+				sizeof(rsdb_config))) < 0) {
+				return err;
+			}
+			if (rsdb_config.ver != WL_RSDB_CONFIG_VER) {
+				err = BCME_VERSION;
+				goto exit;
+			}
+			while ((p = *argv) != NULL) {
+				argv++;
+				opt = '\0';
+
+				if (!strncmp(p, "-", 1)) {
+					if ((strlen(p) > 2) || (*argv == NULL)) {
+						fprintf(stderr, "Invalid option %s \n", p);
+						err = BCME_USAGE_ERROR;
+						goto exit;
+					}
+				} else {
+					fprintf(stderr, "Invalid option %s \n", p);
+					err = BCME_USAGE_ERROR;
+					goto exit;
+				}
+				opt = p[1];
+
+			switch (opt) {
+				case 'n':
+					rsdb_config.non_infra_mode = (uint8)strtol(*argv,
+						&endptr, 0);
+					argv++;
+					break;
+				case 'i':
+					wl_parse_infra_mode_list(*argv, rsdb_config.infra_mode,
+						MAX_BANDS);
+					argv++;
+					break;
+				case 'p':
+					wl_parse_SIB_param_list(*argv, rsdb_config.flags,
+						MAX_BANDS);
+					argv++;
+				break;
+				default:
+					fprintf(stderr, "Invalid option %s \n", p);
+					err = BCME_USAGE_ERROR;
+					goto exit;
+			}
+		}
+		rsdb_config.len = WL_RSDB_CONFIG_LEN;
+		if ((err = wlu_var_setbuf(wl, cmd->name, &rsdb_config,
+			sizeof(rsdb_config))) < 0) {
+			return err;
+		}
+	}
+
+exit:
+	return err;
+}
+
+static int
+wl_parse_infra_mode_list(char *list_str, uint8* list, int list_num)
+{
+	int num;
+	int val;
+	char* str;
+	char* endptr = NULL;
+
+	if (list_str == NULL)
+		return -1;
+
+	str = list_str;
+	num = 0;
+	while (*str != '\0') {
+		val = (int)strtol(str, &endptr, 0);
+		if (endptr == str) {
+			fprintf(stderr,
+				"could not parse list number starting at"
+				" substring \"%s\" in list:\n%s\n",
+				str, list_str);
+			return -1;
+		}
+		str = endptr + strspn(endptr, " ,");
+
+		if (num == list_num) {
+			fprintf(stderr, "too many members (more than %d) in list:\n%s\n",
+				list_num, list_str);
+			return -1;
+		}
+
+		list[num++] = (uint16)val;
+	}
+
+	return num;
+}
+
+static int
+wl_parse_SIB_param_list(char *list_str, uint32* list, int list_num)
+{
+	int num;
+	int val;
+	char* str;
+	char* endptr = NULL;
+
+	if (list_str == NULL)
+		return -1;
+
+	str = list_str;
+	num = 0;
+	while (*str != '\0') {
+		val = (int)strtol(str, &endptr, 0);
+		if (endptr == str) {
+			fprintf(stderr,
+				"could not parse list number starting at"
+				" substring \"%s\" in list:\n%s\n",
+				str, list_str);
+			return -1;
+		}
+		str = endptr + strspn(endptr, " ,");
+
+		if (num == list_num) {
+			fprintf(stderr, "too many members (more than %d) in list:\n%s\n",
+				list_num, list_str);
+			return -1;
+		}
+
+		list[num++] = (uint16)val;
+	}
+	return num;
+}
+#endif /* WLRSDB */
diff --git a/wl/src/wl/exe/wluc_scan.c b/wl/src/wl/exe/wluc_scan.c
new file mode 100644
index 0000000..c5306b3
--- /dev/null
+++ b/wl/src/wl/exe/wluc_scan.c
@@ -0,0 +1,511 @@
+/*
+ * wl scan command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_scan.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifdef EXTENDED_SCAN
+static cmd_func_t wl_extdscan;
+static int wl_parse_extdchannel_list(char* list_str,
+	chan_scandata_t* channel_list, int channel_num);
+#endif
+static cmd_func_t wl_scanmac;
+
+static cmd_t wl_scan_cmds[] = {
+	{ "scancache_clear", wl_var_void, -1, WLC_SET_VAR,
+	"clear the scan cache"},
+#ifdef EXTENDED_SCAN
+	{ "extdscan", wl_extdscan, -1, WLC_SET_VAR,
+	"Initiate an extended scan.\n"
+	"\tDefault to an active scan across all channels for any SSID.\n"
+	"\tOptional args: list of SSIDs to scan.\n"
+	"\tOptions:\n"
+	"\t-s S1 S2 S3, --ssid=S1 S2 S3\t\tSSIDs to scan, comma or space separated\n"
+	"\t-x x, --split_scan=ST\t[split_scan] scan type\n"
+	"\t-t ST, --scan_type=ST\t[background:0/forcedbackground:1/foreground:2] scan type\n"
+	"\t-n N, --nprobes=N\tnumber of probes per scanned channel, per SSID\n"
+	"\t-c L, --channels=L\tcomma or space separated list of channels to scan"},
+#endif
+	{ "passive", wl_int, WLC_GET_PASSIVE_SCAN, WLC_SET_PASSIVE_SCAN,
+	"Puts scan engine into passive mode" },
+	{ "scansuppress", wl_int, WLC_GET_SCANSUPPRESS, WLC_SET_SCANSUPPRESS,
+	"Suppress all scans for testing.\n"
+	"\t0 - allow scans\n"
+	"\t1 - suppress scans" },
+	{ "scan_channel_time", wl_int, WLC_GET_SCAN_CHANNEL_TIME, WLC_SET_SCAN_CHANNEL_TIME,
+	"Get/Set scan channel time"},
+	{ "scan_unassoc_time", wl_int, WLC_GET_SCAN_UNASSOC_TIME, WLC_SET_SCAN_UNASSOC_TIME,
+	"Get/Set unassociated scan channel dwell time"},
+	{ "scan_home_time", wl_int, WLC_GET_SCAN_HOME_TIME, WLC_SET_SCAN_HOME_TIME,
+	"Get/Set scan home channel dwell time"},
+	{ "scan_passive_time", wl_int, WLC_GET_SCAN_PASSIVE_TIME, WLC_SET_SCAN_PASSIVE_TIME,
+	"Get/Set passive scan channel dwell time"},
+	{ "scan_nprobes", wl_int, WLC_GET_SCAN_NPROBES, WLC_SET_SCAN_NPROBES,
+	"Get/Set scan parameter for number of probes to use per channel scanned"},
+	{ "scan_ps", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set scan power optimization enable/disable"},
+	{ "scanmac", wl_scanmac, WLC_GET_VAR, WLC_SET_VAR,
+	"Configure scan MAC using subcommands:\n"
+	"\tscanmac enable <0|1>\n"
+	"\tscanmac bsscfg\n"
+	"\tscanmac config <mac> <random_mask> <scan_bitmap>\n"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_scan_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register scan commands */
+	wl_module_cmds_register(wl_scan_cmds);
+}
+
+#ifdef EXTENDED_SCAN
+/* wl extdscan
+ * -s --ssid=ssid1 ssid2 ssid3
+ * -b --split_scan=0 : [split_scan]
+ * -t --scan_type=0 : [background/forcedbackground/foreground]
+ * -n --nprobes=
+ * -c --channels=
+ */
+static int
+wl_extdscan(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_extdscan_params_t *params;
+	int params_size = WL_EXTDSCAN_PARAMS_FIXED_SIZE +
+		(WL_NUMCHANNELS * sizeof(chan_scandata_t));
+	int val = 0;
+	char *p, *eq, *valstr, *endptr;
+	char opt;
+	bool positional_param;
+	bool good_int;
+	bool opt_end;
+	int err = 0;
+	int keylen;
+	char key[64];
+	int i;
+	int nssid = 0;
+
+	fprintf(stderr, "params alloc size is %d\n", params_size);
+	params = (wl_extdscan_params_t *)malloc(params_size);
+	if (params == NULL) {
+		fprintf(stderr, "Error allocating %d bytes for scan params\n", params_size);
+		return BCME_NOMEM;
+	}
+	memset(params, 0, params_size);
+
+	params->scan_type = EXTDSCAN_FORCEDBACKGROUND_SCAN;
+	params->nprobes = 3;
+	params->band = WLC_BAND_2G;
+	params->split_scan = 0;
+
+	/* skip the command name */
+	argv++;
+
+	if (*argv == NULL) {
+		fprintf(stderr, "no arguments to wl_extdscan\n");
+		err = BCME_USAGE_ERROR;
+		goto exit;
+	}
+	opt_end = FALSE;
+	while ((p = *argv) != NULL) {
+		argv++;
+		positional_param = FALSE;
+		memset(key, 0, sizeof(key));
+		opt = '\0';
+		valstr = NULL;
+		good_int = FALSE;
+
+		if (opt_end) {
+			positional_param = TRUE;
+			valstr = p;
+		}
+		else if (!strcmp(p, "--")) {
+			opt_end = TRUE;
+			continue;
+		}
+		else if (!strncmp(p, "--", 2)) {
+			eq = strchr(p, '=');
+			if (eq == NULL) {
+				fprintf(stderr,
+				"wl_extdscan: missing \" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			keylen = eq - (p + 2);
+			if (keylen > 63)
+				keylen = 63;
+			memcpy(key, p + 2, keylen);
+
+			valstr = eq + 1;
+			if (*valstr == '\0') {
+				fprintf(stderr,
+				"extdscan: missing value after \" = \" in long param \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		else if (!strncmp(p, "-", 1)) {
+			opt = p[1];
+			if (strlen(p) > 2) {
+				fprintf(stderr,
+				"extdscan: only single char options, error on param \"%s\"\n", p);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			if (*argv == NULL) {
+				fprintf(stderr,
+				"extdscan: missing value parameter after \"%s\"\n", p);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+			valstr = *argv;
+			argv++;
+		} else {
+			positional_param = TRUE;
+			valstr = p;
+		}
+
+		/* parse valstr as int just in case */
+		if (valstr) {
+			val = (int)strtol(valstr, &endptr, 0);
+			if (*endptr == '\0') {
+				/* not all the value string was parsed by strtol */
+				good_int = TRUE;
+			}
+		}
+
+		if (opt == 's' || !strcmp(key, "ssid") || positional_param) {
+			nssid = wl_parse_ssid_list(valstr, params->ssid,
+			                           nssid, WLC_EXTDSCAN_MAX_SSID);
+			if (nssid < 0) {
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+		if (opt == 'b' || !strcmp(key, "band")) {
+			if (!strcmp(valstr, "5G")) {
+				params->band = WLC_BAND_5G;
+			}
+			else if (!strcmp(valstr, "2.4G")) {
+				params->band = WLC_BAND_2G;
+			}
+			else if (!strcmp(valstr, "all")) {
+				params->band = WLC_BAND_ALL;
+			} else {
+				fprintf(stderr,
+				"scan_type value should be \"5G\" "
+				"or \"2.4G\" " "or \"all\" but got \"%s\"\n", valstr);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		if (opt == 't' || !strcmp(key, "scan_type")) {
+			if (!strcmp(valstr, "background")) {
+				params->scan_type = EXTDSCAN_BACKGROUND_SCAN;
+			} else if (!strcmp(valstr, "fbackground")) {
+				params->scan_type = EXTDSCAN_FORCEDBACKGROUND_SCAN;
+			} else if (!strcmp(valstr, "foreground")) {
+				params->scan_type = EXTDSCAN_FOREGROUND_SCAN;
+			} else {
+				fprintf(stderr,
+				"scan_type value should be \"background\" "
+				"or \"fbackground\" " "or \"foreground\" but got \"%s\"\n", valstr);
+				err = BCME_USAGE_ERROR;
+				goto exit;
+			}
+		}
+		if (opt == 'n' || !strcmp(key, "nprobes")) {
+			if (!good_int) {
+				fprintf(stderr,
+				"could not parse \"%s\" as an int for value nprobes\n", valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			params->nprobes = val;
+		}
+		if (opt == 'x' || !strcmp(key, "split_scan")) {
+			if (val != 0)
+				params->split_scan = 1;
+		}
+		if (opt == 'c' || !strcmp(key, "channels")) {
+			params->channel_num = wl_parse_extdchannel_list(valstr,
+				params->channel_list, WL_NUMCHANNELS);
+			if (params->channel_num == -1) {
+				fprintf(stderr, "error parsing channel list arg\n");
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+	}
+
+	if (nssid > WLC_EXTDSCAN_MAX_SSID) {
+		fprintf(stderr, "ssid count %d exceeds max of %d\n",
+		        nssid, WLC_EXTDSCAN_MAX_SSID);
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	params_size = WL_EXTDSCAN_PARAMS_FIXED_SIZE +
+	    (params->channel_num * sizeof(chan_scandata_t));
+
+	fprintf(stderr, "ssid list is %s(%d) %s(%d) %s(%d) %s(%d) %s(%d)\n",
+		(char *)&params->ssid[0].SSID, params->ssid[0].SSID_len,
+		(char *)&params->ssid[1].SSID, params->ssid[1].SSID_len,
+		(char *)&params->ssid[2].SSID, params->ssid[2].SSID_len,
+		(char *)&params->ssid[3].SSID, params->ssid[3].SSID_len,
+		(char *)&params->ssid[4].SSID, params->ssid[4].SSID_len);
+	if (params->split_scan)
+	    fprintf(stderr, "split scan is enabled\n");
+	else
+	   fprintf(stderr, "split scan is not enabled\n");
+
+	fprintf(stderr, "scan type is %d, nprobes are %d, band is %d, channels are %d\n",
+		params->scan_type, params->nprobes, params->band, params->channel_num);
+
+	fprintf(stderr, "params size is %d\n", params_size);
+	params->scan_type = htodenum(params->scan_type);
+	for (i = 0; i < WLC_EXTDSCAN_MAX_SSID; i++) {
+		params->ssid[i].SSID_len = htod32(params->ssid[i].SSID_len);
+	}
+	for (i = 0; i < params->channel_num; i++) {
+		chanspec_t chanspec = params->channel_list[i].channel;
+		chanspec = wl_chspec_to_driver(chanspec);
+		if (chanspec == INVCHANSPEC) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		params->channel_list[i].channel = chanspec;
+		params->channel_list[i].channel_mintime =
+		        htod32(params->channel_list[i].channel_mintime);
+		params->channel_list[i].channel_maxtime =
+		        htod32(params->channel_list[i].channel_maxtime);
+	}
+	params->channel_num = htod32(params->channel_num);
+	err =  wlu_var_setbuf(wl, cmd->name, params, params_size);
+
+exit:
+	free(params);
+	return err;
+}
+
+static int
+wl_parse_extdchannel_list(char* list_str, chan_scandata_t* channel_list, int channel_num)
+{
+	int num;
+	int val;
+	char* str;
+	char* endptr;
+
+	if (list_str == NULL)
+		return -1;
+
+	str = list_str;
+	num = 0;
+	while (*str != '\0') {
+		val = (int)strtol(str, &endptr, 0);
+		if (endptr == str) {
+			fprintf(stderr,
+				"could not parse channel number starting at"
+				" substring \"%s\" in list:\n%s\n",
+				str, list_str);
+			return -1;
+		}
+		str = endptr + strspn(endptr, " ,");
+
+		if (num == channel_num) {
+			fprintf(stderr, "too many channels (more than %d) in channel list:\n%s\n",
+				channel_num, list_str);
+			return -1;
+		}
+		channel_list->channel = (uint16)val;
+		channel_list++;
+		num++;
+	}
+
+	return num;
+}
+#endif /* EXTENDED_SCAN */
+
+static int
+wl_scanmac(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	char *subcmd;
+	int subcmd_len;
+
+	/* skip iovar */
+	argv++;
+
+	/* must have subcommand */
+	subcmd = *argv++;
+	if (!subcmd) {
+		return BCME_USAGE_ERROR;
+	}
+	subcmd_len = strlen(subcmd);
+
+	if (!*argv) {
+		/* get */
+		uint8 buffer[OFFSETOF(wl_scanmac_t, data)];
+		wl_scanmac_t *sm = (wl_scanmac_t *)buffer;
+		int len = OFFSETOF(wl_scanmac_t, data);
+
+		memset(sm, 0, len);
+		if (!strncmp(subcmd, "enable", subcmd_len)) {
+			sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
+		} else if (!strncmp(subcmd, "bsscfg", subcmd_len)) {
+			sm->subcmd_id = WL_SCANMAC_SUBCMD_BSSCFG;
+		} else if (!strncmp(subcmd, "config", subcmd_len)) {
+			sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+		/* invoke GET iovar */
+		sm->subcmd_id = dtoh16(sm->subcmd_id);
+		sm->len = dtoh16(sm->len);
+		if ((err = wlu_iovar_getbuf(wl, cmd->name, sm, len, buf, WLC_IOCTL_SMLEN)) < 0) {
+			return err;
+		}
+
+		/* process and print GET results */
+		sm = (wl_scanmac_t *)buf;
+		sm->subcmd_id = dtoh16(sm->subcmd_id);
+		sm->len = dtoh16(sm->len);
+
+		switch (sm->subcmd_id) {
+		case WL_SCANMAC_SUBCMD_ENABLE:
+		{
+			wl_scanmac_enable_t *sm_enable = (wl_scanmac_enable_t *)sm->data;
+			if (sm->len >= sizeof(*sm_enable)) {
+				printf("%d\n", sm_enable->enable);
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		case WL_SCANMAC_SUBCMD_BSSCFG:
+		{
+			wl_scanmac_bsscfg_t *sm_bsscfg = (wl_scanmac_bsscfg_t *)sm->data;
+			if (sm->len >= sizeof(*sm_bsscfg)) {
+				sm_bsscfg->bsscfg = dtoh32(sm_bsscfg->bsscfg);
+				printf("%d\n", sm_bsscfg->bsscfg);
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		case WL_SCANMAC_SUBCMD_CONFIG:
+		{
+			wl_scanmac_config_t *sm_config = (wl_scanmac_config_t *)sm->data;
+			if (sm->len >= sizeof(*sm_config)) {
+				sm_config->scan_bitmap = dtoh16(sm_config->scan_bitmap);
+				printf("mac:         %s\n", wl_ether_etoa(&sm_config->mac));
+				printf("random mask: %s\n", wl_ether_etoa(&sm_config->random_mask));
+				printf("scan bitmap: 0x%02X\n", sm_config->scan_bitmap);
+				if (sm_config->scan_bitmap & WL_SCANMAC_SCAN_UNASSOC) {
+					printf("             unassoc\n");
+				}
+				if (sm_config->scan_bitmap & WL_SCANMAC_SCAN_ASSOC_ROAM) {
+					printf("             assoc roam\n");
+				}
+				if (sm_config->scan_bitmap & WL_SCANMAC_SCAN_ASSOC_PNO) {
+					printf("             assoc PNO\n");
+				}
+				if (sm_config->scan_bitmap & WL_SCANMAC_SCAN_ASSOC_HOST) {
+					printf("             assoc host\n");
+				}
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		default:
+			break;
+		}
+	}
+	else {
+		/* set */
+		uint8 buffer[OFFSETOF(wl_scanmac_t, data) +
+			MAX(sizeof(wl_scanmac_enable_t), sizeof(wl_scanmac_config_t))];
+		wl_scanmac_t *sm = (wl_scanmac_t *)buffer;
+		int len = OFFSETOF(wl_scanmac_t, data);
+
+		if (!strncmp(subcmd, "enable", subcmd_len) &&
+			(*argv[0] == '0' || *argv[0] == '1')) {
+			wl_scanmac_enable_t *sm_enable = (wl_scanmac_enable_t *)sm->data;
+			sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
+			sm->len = sizeof(*sm_enable);
+			sm_enable->enable = atoi(argv[0]);
+		} else if (!strncmp(subcmd, "config", subcmd_len) &&
+			argv[0] && argv[1] && argv[2]) {
+			wl_scanmac_config_t *sm_config = (wl_scanmac_config_t *)sm->data;
+			char *mac = argv[0];
+			char *mask = argv[1];
+			char *bitmap = argv[2];
+			sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
+			sm->len = sizeof(*sm_config);
+			if (!wl_ether_atoe(mac, &sm_config->mac) ||
+				!wl_ether_atoe(mask, &sm_config->random_mask)) {
+				return BCME_USAGE_ERROR;
+			}
+			sm_config->scan_bitmap = (uint16)strtoul(bitmap, NULL, 0);
+			sm_config->scan_bitmap = htod16(sm_config->scan_bitmap);
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+		/* invoke SET iovar */
+		len = OFFSETOF(wl_scanmac_t, data) + sm->len;
+		sm->subcmd_id = htod16(sm->subcmd_id);
+		sm->len = htod16(sm->len);
+		err = wlu_iovar_set(wl, cmd->name, sm, len);
+	}
+
+	return err;
+}
diff --git a/wl/src/wl/exe/wluc_sdio.c b/wl/src/wl/exe/wluc_sdio.c
new file mode 100644
index 0000000..9ca285a
--- /dev/null
+++ b/wl/src/wl/exe/wluc_sdio.c
@@ -0,0 +1,16 @@
+/*
+ * wl sdio command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_sdio.c 458728 2014-02-27 18:15:25Z $
+ */
diff --git a/wl/src/wl/exe/wluc_seq_cmds.c b/wl/src/wl/exe/wluc_seq_cmds.c
new file mode 100644
index 0000000..54976b5
--- /dev/null
+++ b/wl/src/wl/exe/wluc_seq_cmds.c
@@ -0,0 +1,72 @@
+/*
+ * wl seq_cmds command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_seq_cmds.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_t wl_seq_cmds[] = {
+	{ "seq_start", wl_seq_start, -1, WLC_SET_VAR,
+	"Initiates command batching sequence. Subsequent IOCTLs will be queued until\n"
+	"seq_stop is received."},
+	{ "seq_stop", wl_seq_stop, -1, WLC_SET_VAR,
+	"Defines the end of command batching sequence. Queued IOCTLs will be executed."},
+	{ "seq_delay", wl_varint, -1, WLC_SET_VAR,
+	"Driver should spin for the indicated amount of time.\n"
+	"It is only valid within the context of batched commands."},
+	{ "seq_error_index", wl_varint, WLC_GET_VAR, -1,
+	"Used to retrieve the index (starting at 1) of the command that failed within a batch"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_seq_cmds_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register seq_cmds commands */
+	wl_module_cmds_register(wl_seq_cmds);
+}
diff --git a/wl/src/wl/exe/wluc_stf.c b/wl/src/wl/exe/wluc_stf.c
new file mode 100644
index 0000000..a04353e
--- /dev/null
+++ b/wl/src/wl/exe/wluc_stf.c
@@ -0,0 +1,1327 @@
+/*
+ * wl stf command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_stf.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#include "wlu_rates_matrix.h"
+
+#define WL_MIMO_PS_MAX_PARAMS			4
+#define WL_MIMO_PS_LEARNING_MAX_PARAMS		3
+
+static void wl_txppr_print(ppr_t *ppr, int cck, uint flags);
+static void wl_txppr_print_bw(ppr_t *ppr, int cck, uint flags, wl_tx_bw_t bw);
+static cmd_func_t wl_get_current_txppr;
+static cmd_func_t wl_txcore;
+static cmd_func_t wl_txcore_pwr_offset;
+static int wl_mimo_stf(void *wl, cmd_t *cmd, char **argv);
+static cmd_func_t wl_spatial_policy, wl_ratetbl_ppr;
+static cmd_func_t wl_mimo_ps_cfg;
+static cmd_func_t wl_mimo_ps_learning_cfg;
+static int wl_mimo_ps_learning_cfg_get_status(void *wl, const char *iovar);
+static cmd_func_t wl_mimo_ps_status;
+static int wl_mimo_ps_status_dump(wl_mimo_ps_status_t *status);
+static int wl_mimo_ps_status_assoc_status_dump(uint8 assoc_status);
+static void wl_mimo_ps_status_hw_state_dump(uint16 hw_state);
+static cmd_func_t wl_temp_throttle_control;
+static cmd_func_t wl_ocl_status;
+static void wl_ocl_status_fw_dump(uint16 fw_state);
+static void wl_ocl_status_hw_dump(uint8 hw_state);
+
+static cmd_t wl_stf_cmds[] = {
+	{ "curppr", wl_get_current_txppr, WLC_GET_VAR, -1,
+	"Return current tx power per rate offset."},
+	{ "txcore", wl_txcore, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: wl txcore -k <CCK core mask> -o <OFDM core mask> -s <1..4> -c <core bitmap>\n"
+	"\t-k CCK core mask\n"
+	"\t-o OFDM core mask\n"
+	"\t-s # of space-time-streams\n"
+	"\t-c active core (bitmask) to be used when transmitting frames"
+	},
+	{ "txcore_override", wl_txcore, WLC_GET_VAR, -1,
+	"Usage: wl txcore_override\n"
+	"\tget the user override of txcore"
+	},
+	{ "txchain_pwr_offset", wl_txcore_pwr_offset, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: wl txchain_pwr_offset [qdBm offsets]\n"
+	"\tGet/Set the current offsets for each core in qdBm (quarter dBm)"
+	},
+	{ "mimo_ss_stf", wl_mimo_stf, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set SS STF mode.\n"
+	"\tUsage: wl mimo_ss_stf <value> <-b a | b>\n"
+	"\tvalue: 0 - SISO; 1 - CDD\n"
+	"\t-b(band): a - 5G; b - 2.4G"},
+	{ "spatial_policy", wl_spatial_policy, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get spatial_policy\n"
+	"\tUsage: wl spatial_policy <-1: auto / 0: turn off / 1: turn on>\n"
+	"\t       to control individual band/sub-band use\n"
+	"\t       wl spatial_policy a b c d e\n"
+	"\t       where a is 2.4G band setting\n"
+	"\t       where b is 5G lower band setting\n"
+	"\t       where c is 5G middle band setting\n"
+	"\t       where d is 5G high band setting\n"
+	"\t       where e is 5G upper band setting"},
+	{ "ratetbl_ppr", wl_ratetbl_ppr, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: For get: wl ratetbl_ppr\n"
+	"\t     For set: wl ratetbl_ppr <rate> <ppr>" },
+	{ "mrc_rssi_threshold", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set mrc_rssi_threshold for mimo power save,\n "
+	"\twhen RSSI is below RSSI level specified by mrc_rssi_threshold then \n"
+	"\tall rx chains will be made active for all rx frames to benefit "
+	"from Maximal ratio combining (MRC) "
+	},
+	{ "mimo_ps_cfg_change_wait_time", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set mimo_ps_guard_interval for mimo power save,\n "
+	"\tspecifies the time STA will wait before receiving packets"
+	"when moving from higher configuration to lower configuration\n"
+	},
+	{ "mimo_ps_cfg", wl_mimo_ps_cfg, WLC_GET_VAR, WLC_SET_VAR,
+	"Description: Configure MIMO Power save configuration.\n"
+	"\twhere active_chains: 0 for all, 1 for 1 chain. Only 0 and 1 are supported for now.\n"
+	"\tIn future more than 1 can be supported to enable more than 1 but less than max chains.\n"
+	"\tmode = static (0) or dynamic (1) or disabled(3)."
+	"Mode applies only when active_chains is 0.\n"
+	"\tbandwidth = Full (0), 20M (1), 40M (2), 80M (3).\n"
+	"\tApply changes after learning donot appy(0) apply(1).\n"
+	},
+	{ "mimo_ps_status", wl_mimo_ps_status, WLC_GET_VAR, -1,
+	"usage: mimo_ps_status\n"
+	"Displays MIMO PS related state/information"
+	},
+	{ "mimo_ps_learning_config", wl_mimo_ps_learning_cfg, WLC_GET_VAR, WLC_SET_VAR,
+	"Description: Configure mimo ps learning related parameters\n"
+	"\tusage: wl mimo_ps_learning_config <flag> <no_of_packets> \n"
+	"\tFlag :\n\t0 - Get status of current learning\n"
+	"\t1 - ABORT current learning. \n"
+	"\t2 - used to configure only no of packets\n"
+	},
+	{ "temp_throttle_control", wl_temp_throttle_control, WLC_GET_VAR, WLC_SET_VAR,
+	"Usage: temp_throttle_control <enable/disable> <value>\n"
+	},
+	{ "ocl_status", wl_ocl_status, WLC_GET_VAR, -1,
+	"usage: ocl_status\n"
+	"Displays ocl fw/hw state/information"
+	},
+	{ "ocl_rssi_threshold", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set ocl_rssi_threshold such that,\n "
+	"\twhen RSSI is below the specified ocl_rssi_threshold then \n"
+	"\tocl is disabled.\n"
+	},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_stf_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register stf commands */
+	wl_module_cmds_register(wl_stf_cmds);
+}
+
+static void
+wl_txppr_print(ppr_t *ppr, int cck, uint flags)
+{
+
+	switch (ppr_get_ch_bw(ppr)) {
+	case WL_TX_BW_20:
+		printf("\n20MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_20);
+		break;
+	case WL_TX_BW_40:
+		printf("\n20 in 40MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_20IN40);
+		printf("\n40MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_40);
+		break;
+	case WL_TX_BW_80:
+		printf("\n20 in 80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_20IN80);
+		printf("\n40 in 80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_40IN80);
+		printf("\n80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_80);
+		break;
+	case WL_TX_BW_160:
+		printf("\n20 in 160MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_20IN160);
+		printf("\n40 in 160MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_40IN160);
+		printf("\n80 in 160MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_80IN160);
+		printf("\n160MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_160);
+		break;
+	case WL_TX_BW_8080:
+		printf("\n20 in 80+80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_20IN8080);
+		printf("\n40 in 80+80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_40IN8080);
+		printf("\n80 in 80+80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_80IN8080);
+		printf("\nchan1 80+80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_8080);
+		printf("\nchan2 80+80MHz:\n");
+		wl_txppr_print_bw(ppr, cck, flags, WL_TX_BW_8080CHAN2);
+		break;
+	default:
+		break;
+	}
+	/* MCS32 value is obsoleted */
+	/* printf("MCS32        %2d\n", ppr->mcs32); */
+	printf("\n");
+}
+
+
+#define PRINT_PPR_RATE_LOOP(idx, len, rates)		  \
+			for (idx = 0; idx < len; idx++) { \
+				if (rates[idx] == WL_RATE_DISABLED) \
+					printf("  -"); \
+				else \
+					printf(" %2d", rates[idx]); \
+			}
+
+/* print power offset for for a given bandwidth */
+static void
+wl_txppr_print_bw(ppr_t *ppr, int cck, uint flags, wl_tx_bw_t bw)
+{
+	uint i, j, rlen;
+	uint n = WL_NUM_2x2_ELEMENTS;
+	uint offset = 0;
+	int8 *ptr, *vhtptr;
+	const char *str = "";
+	bool siso = ((flags & WL_TX_POWER_F_MIMO) == 0);
+	bool vht = ((flags & WL_TX_POWER_F_VHT) != 0);
+	ppr_ofdm_rateset_t ofdm_rate;
+	ppr_vht_mcs_rateset_t vhtrate;
+
+
+	if (!siso) {
+		offset = WL_NUM_3x3_ELEMENTS;
+		n = WL_NUM_4x4_ELEMENTS;
+	}
+
+	if (cck) {
+		ppr_dsss_rateset_t rate;
+		ppr_get_dsss(ppr, bw, WL_TX_CHAINS_1, &rate);
+		printf("CCK         ");
+		PRINT_PPR_RATE_LOOP(j, WL_RATESET_SZ_DSSS, rate.pwr);
+		if (!siso) {
+			for (i = WL_TX_CHAINS_2; i <= WL_TX_CHAINS_4; i++) {
+				ppr_get_dsss(ppr, bw, i, &rate);
+				printf("\nCCK CDD 1x%d ", i);
+				PRINT_PPR_RATE_LOOP(j, WL_RATESET_SZ_DSSS, rate.pwr);
+			}
+		}
+	}
+	ppr_get_ofdm(ppr, bw, WL_TX_MODE_NONE, WL_TX_CHAINS_1, &ofdm_rate);
+	printf("\nOFDM        ");
+	PRINT_PPR_RATE_LOOP(j, WL_RATESET_SZ_OFDM, ofdm_rate.pwr);
+	for (i = WL_TX_CHAINS_2; i <= WL_TX_CHAINS_4; i++) {
+		ppr_get_ofdm(ppr, bw, WL_TX_MODE_CDD, i, &ofdm_rate);
+		printf("\nOFDM-CDD 1x%d", i);
+		PRINT_PPR_RATE_LOOP(j, WL_RATESET_SZ_OFDM, ofdm_rate.pwr);
+	}
+	printf("\n");
+	for (i = 0; i < n; i++) {
+		wl_tx_nss_t nss;
+		wl_tx_mode_t mode;
+		wl_tx_chains_t chains;
+		switch (i + offset) {
+			case 0:
+				str = "MCS-SISO   ";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_1;
+				ptr = vhtrate.pwr;
+				vhtptr = NULL;
+				break;
+			case 1:
+				str = "MCS-CDD    ";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_CDD;
+				chains = WL_TX_CHAINS_2;
+				ptr = vhtrate.pwr;
+				vhtptr = NULL;
+				break;
+			case 2:
+				str = "MCS STBC   ";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_STBC;
+				chains = WL_TX_CHAINS_2;
+				ptr = vhtrate.pwr;
+				vhtptr = NULL;
+				break;
+			case 3:
+				str = "MCS 8~15   ";
+				nss = WL_TX_NSS_2;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_2;
+				ptr = vhtrate.pwr;
+				vhtptr = NULL;
+				break;
+			case 4:
+			case 5:
+				ptr = NULL;
+				vhtptr = NULL;
+				break;
+			case 6:
+				str = "1 Nsts 1 Tx";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_1;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 7:
+				str = "1 Nsts 2 Tx";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_CDD;
+				chains = WL_TX_CHAINS_2;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 8:
+				str = "1 Nsts 3 Tx";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_CDD;
+				chains = WL_TX_CHAINS_3;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 9:
+				str = "1 Nsts 4 Tx";
+				nss = WL_TX_NSS_1;
+				mode = WL_TX_MODE_CDD;
+				chains = WL_TX_CHAINS_4;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+
+			case 10:
+				str = "2 Nsts 2 Tx";
+				nss = WL_TX_NSS_2;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_2;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 11:
+				str = "2 Nsts 3 Tx";
+				nss = WL_TX_NSS_2;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_3;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 12:
+				str = "2 Nsts 4 Tx";
+				nss = WL_TX_NSS_2;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_4;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 13:
+				str = "3 Nsts 3 Tx";
+				nss = WL_TX_NSS_3;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_3;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 14:
+				str = "3 Nsts 4 Tx";
+				nss = WL_TX_NSS_3;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_4;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			case 15:
+				str = "4 Nsts 4 Tx";
+				nss = WL_TX_NSS_4;
+				mode = WL_TX_MODE_NONE;
+				chains = WL_TX_CHAINS_4;
+				ptr = vhtrate.pwr;
+				vhtptr = &vhtrate.pwr[8];
+				break;
+			default:
+				ptr = NULL;
+				vhtptr = NULL;
+				break;
+		}
+		if (ptr == NULL)
+			continue;
+		ppr_get_vht_mcs(ppr, bw, nss, mode, chains, &vhtrate);
+		printf("%s ", str);
+		if (vht && vhtptr)
+			rlen = WL_RATESET_SZ_VHT_MCS_P;
+		else
+			rlen = WL_RATESET_SZ_HT_MCS;
+		PRINT_PPR_RATE_LOOP(j, rlen, ptr);
+		printf("\n");
+	}
+}
+
+static int
+wl_get_current_txppr(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint flags;
+	chanspec_t chanspec;
+	char chanspec_str[CHANSPEC_STR_LEN];
+	uint pprsize = ppr_ser_size_by_bw(ppr_get_max_bw());
+	wl_txppr_t *wl_txppr;
+	ppr_t *pprptr = NULL;
+
+	wl_txppr = (wl_txppr_t *)malloc(sizeof(*wl_txppr) + pprsize);
+
+	if (wl_txppr == NULL) {
+		fprintf(stderr, "Error allocating memory failed for curppr");
+		return BCME_NOMEM;
+	}
+
+	memset(wl_txppr, 0, sizeof(*wl_txppr));
+	wl_txppr->buflen = pprsize;
+	if ((err = ppr_init_ser_mem_by_bw(wl_txppr->pprbuf, ppr_get_max_bw(), pprsize))
+		!= BCME_OK) {
+		free(wl_txppr);
+		return err;
+	}
+
+	if (WLC_IOCTL_MAXLEN < sizeof(wl_txppr_t) + pprsize) {
+		free(wl_txppr);
+		return BCME_ERROR;
+	}
+
+	argv++;
+	if (*argv)
+		fprintf(stderr, "Ignoring arguments for %s\n", cmd->name);
+
+	wl_txppr->ver = WL_TXPPR_VERSION;
+	wl_txppr->len = WL_TXPPR_LENGTH;
+	if ((err = wlu_iovar_getbuf(wl, "curppr", wl_txppr, sizeof(*wl_txppr) + pprsize,
+		buf, WLC_IOCTL_MAXLEN)) < 0) {
+		free(wl_txppr);
+		return err;
+	}
+
+	/* the input buffer is no longer needed, output results are in buf */
+	free(wl_txppr);
+	wl_txppr = (wl_txppr_t *)buf;
+
+	/* parse */
+	wl_txppr->flags = dtoh32(wl_txppr->flags);
+	wl_txppr->chanspec = wl_chspec_from_driver(wl_txppr->chanspec);
+	wl_txppr->local_chanspec = wl_chspec_from_driver(wl_txppr->local_chanspec);
+
+	chanspec = wl_txppr->chanspec;
+	flags = (wl_txppr->flags & WL_TX_POWER_F_VHT) |
+	       (wl_txppr->flags & WL_TX_POWER_F_HT) |
+	       (wl_txppr->flags & WL_TX_POWER_F_MIMO) |
+	       (wl_txppr->flags & WL_TX_POWER_F_SISO);
+
+	/* dump */
+	printf("Current channel:\t %s\n",
+	       wf_chspec_ntoa(wl_txppr->chanspec, chanspec_str));
+	printf("BSS channel:\t\t %s\n",
+	       wf_chspec_ntoa(wl_txppr->local_chanspec, chanspec_str));
+
+	printf("Power/Rate Dump (in %s): Channel %d\n", (wl_txppr->flags & WL_TX_POWER_F_UNIT_QDBM)?
+		"1/4dB":"1/2dB", CHSPEC_CHANNEL(chanspec));
+	if ((err = ppr_deserialize_create(NULL, wl_txppr->pprbuf, pprsize, &pprptr)) == BCME_OK) {
+		wl_txppr_print(pprptr, CHSPEC_IS2G(chanspec), flags);
+		ppr_delete(NULL, pprptr);
+	}
+	return err;
+}
+
+static int
+wl_txcore_pwr_offset(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_txchain_pwr_offsets_t offsets;
+	char *endptr;
+	int i;
+	long val;
+	int err;
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv) {
+		err = wlu_iovar_get(wl, cmd->name, &offsets, sizeof(wl_txchain_pwr_offsets_t));
+
+		if (err < 0)
+			return err;
+
+		printf("txcore offsets qdBm: %d %d %d %d\n",
+		       offsets.offset[0], offsets.offset[1],
+		       offsets.offset[2], offsets.offset[3]);
+
+		return 0;
+	}
+
+	memset(&offsets, 0, sizeof(wl_txchain_pwr_offsets_t));
+
+	for (i = 0; i < WL_NUM_TXCHAIN_MAX; i++, argv++) {
+		if (!*argv)
+			break;
+
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		if (val > 0)
+			return BCME_BADARG;
+
+		offsets.offset[i] = (int8)val;
+	}
+
+	err = wlu_iovar_set(wl, cmd->name, &offsets, sizeof(wl_txchain_pwr_offsets_t));
+
+	return err;
+}
+
+static int
+wl_txcore(void *wl, cmd_t *cmd, char **argv)
+{
+	miniopt_t to;
+	const char* fn_name = "wl_txcore";
+	int err = 0, opt_err, val;
+	uint8 streams = 0;
+	bool streams_set = FALSE;
+	uint8 core = 0;
+	bool core_set = FALSE;
+	uint8 cck_mask = 0;
+	bool cck_set = FALSE;
+	uint8 ofdm_mask = 0;
+	bool ofdm_set = FALSE;
+	uint8 mcs_mask[4] = {0, 0, 0, 0}; /* pre-initialize # of streams {core:4 | stream:4} */
+	bool mcs_set = FALSE;
+	uint8 idx;
+	uint32 coremask[2] = {0, 0};
+
+	/* toss the command name */
+	argv++;
+
+	if (!*argv) {
+		if (cmd->get < 0)
+			return -1;
+		if ((err = wlu_iovar_get(wl, cmd->name, &coremask, sizeof(uint32)*2)) < 0)
+			return err;
+
+		printf("txcore enabled bitmap (Nsts {4..1}) 0x%02x 0x%02x 0x%02x 0x%02x\n",
+			(coremask[0] >> 24) & 0xff, (coremask[0] >> 16) & 0xff,
+			(coremask[0] >> 8) & 0xff, coremask[0] & 0xff);
+		printf("txcore mask OFDM 0x%02x  CCK 0x%02x\n",
+			(coremask[1] >> 8) & 0xff, coremask[1] & 0xff);
+		return 0;
+	}
+
+	val = atoi(*argv);
+	if (val == -1)
+		goto next;
+
+	miniopt_init(&to, fn_name, "w", FALSE);
+	while ((opt_err = miniopt(&to, argv)) != -1) {
+		if (opt_err == 1) {
+			err = BCME_USAGE_ERROR;
+			goto exit;
+		}
+		argv += to.consumed;
+
+		if (to.opt == 's') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for streams\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			streams_set = TRUE;
+			streams = (to.val & 0x0f);
+			if (streams > 4)
+				fprintf(stderr, "%s: Nsts > %d\n", fn_name, to.val);
+		}
+		if (to.opt == 'c') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for stf core\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			core_set = TRUE;
+			core = (to.val & 0x0f) << 4;
+			if (core == 0) {
+				fprintf(stderr, "%s: %1d-stream core cannot be zero\n",
+					fn_name, streams);
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+		if (to.opt == 'o') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for streams\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			ofdm_set = TRUE;
+			ofdm_mask = (to.val & 0x0f);
+			if (ofdm_mask == 0) {
+				fprintf(stderr, "%s: OFDM core cannot be zero\n", fn_name);
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+		if (to.opt == 'k') {
+			if (!to.good_int) {
+				fprintf(stderr,
+					"%s: could not parse \"%s\" as an int for streams\n",
+					fn_name, to.valstr);
+				err = BCME_BADARG;
+				goto exit;
+			}
+			cck_set = TRUE;
+			cck_mask = (to.val & 0x0f);
+			if (cck_mask == 0) {
+				fprintf(stderr, "%s: CCK core cannot be zero\n", fn_name);
+				err = BCME_BADARG;
+				goto exit;
+			}
+		}
+
+		if (streams_set && core_set) {
+			streams_set = core_set = FALSE;
+			mcs_set = TRUE;
+			idx = streams - 1;
+			mcs_mask[idx] = (uint8)(core|streams);
+		}
+	}
+
+	if (streams_set != core_set) {
+		fprintf(stderr, "%s: require to set both -s x -c y\n", fn_name);
+		err = BCME_BADARG;
+		goto exit;
+	}
+
+	if (mcs_set) {
+		coremask[0] |= mcs_mask[0] << 0;
+		coremask[0] |= mcs_mask[1] << 8;
+		coremask[0] |= mcs_mask[2] << 16;
+		coremask[0] |= mcs_mask[3] << 24;
+	}
+	if (cck_set)
+		coremask[1] |= cck_mask;
+	if (ofdm_set)
+		coremask[1] |= ofdm_mask << 8;
+next:
+	err = wlu_var_setbuf(wl, cmd->name, coremask, sizeof(uint32)*2);
+exit:
+	return err;
+}
+
+static int
+wl_mimo_stf(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	int32 int_val;
+	bool get = TRUE;
+	uint32 len = 0;
+	void *ptr = NULL;
+	char *endptr;
+	int i = 0, j = 0;
+	int ret = 0;
+
+	while (argv[i])
+		i++;
+
+	if (i > 4)
+		return BCME_USAGE_ERROR;
+
+	/* toss the command name */
+	argv++;
+	j = 1;
+
+	if (i == 1) {
+		int_val = -1;
+		memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+		len += sizeof(int_val);
+	}
+	else {
+		if (isdigit((unsigned char)(**argv))) {
+			get = FALSE;
+			int_val = htod32(strtoul(*argv, &endptr, 0));
+			if ((int_val != 0) && (int_val != 1)) {
+				fprintf(stderr, "wl mimo_ss_stf: bad stf mode.\n");
+				return BCME_BADARG;
+			}
+			memcpy(var, (char *)&int_val, sizeof(int_val));
+			len += sizeof(int_val);
+			argv++;
+			j++;
+		}
+
+		 if (j == i) {
+			int_val = -1;
+			memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+			len += sizeof(int_val);
+		}
+		else if (!strncmp(*argv, "-b", 2)) {
+			argv++;
+			j++;
+			if (j == i)
+				return BCME_BADARG;
+
+			if (!strcmp(*argv, "a"))
+				int_val = 1;
+			else if (!strcmp(*argv, "b"))
+				int_val = 0;
+			else {
+				fprintf(stderr,
+					"wl mimo_ss_stf: wrong -b option, \"-b a\" or \"-b b\"\n");
+				return BCME_USAGE_ERROR;
+			}
+			j++;
+			if (j < i)
+				return BCME_BADARG;
+			memcpy(&var[len], (char *)&int_val, sizeof(int_val));
+			len += sizeof(int_val);
+		}
+	}
+
+	if (get) {
+		if ((ret = wlu_var_getbuf(wl, cmd->name, var, sizeof(var), &ptr)) < 0)
+			return ret;
+
+		printf("0x%x\n", dtoh32(*(int *)ptr));
+	}
+	else
+		ret = wlu_var_setbuf(wl, cmd->name, &var, sizeof(var));
+	return ret;
+}
+
+static int
+wl_spatial_policy(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr = NULL;
+	int err, i, *reply;
+	int mode[SPATIAL_MODE_MAX_IDX] = {-1, -1, -1, -1, -1};
+
+	/* Order is 2G, 5G-LOW, 5G-MID, 5G-HIGH, 5G-UPPER
+	 * if only one argument given, than all band or sub-band take the
+	 * same value
+	 */
+	if (!*++argv) {
+		bool all_same = TRUE;
+		if ((err = wlu_var_getbuf(wl, cmd->name, &mode, sizeof(mode), &ptr)) < 0)
+			return err;
+		reply = (int *)ptr;
+		for (i = 1; i < SPATIAL_MODE_MAX_IDX; i++) {
+			 /* check if return values for each band/sub-band is same or not */
+			 if (reply[i-1] != reply[i])
+				 all_same = FALSE;
+		}
+		if (all_same)
+			printf("%2d\n", reply[0]);
+		else {
+			printf("2.4GHz       : %2d\n", reply[SPATIAL_MODE_2G_IDX]);
+			printf("5GHz (lower) : %2d\n", reply[SPATIAL_MODE_5G_LOW_IDX]);
+			printf("5GHz (middle): %2d\n", reply[SPATIAL_MODE_5G_MID_IDX]);
+			printf("5GHz (high)  : %2d\n", reply[SPATIAL_MODE_5G_HIGH_IDX]);
+			printf("5GHz (upper) : %2d\n", reply[SPATIAL_MODE_5G_UPPER_IDX]);
+		}
+		return 0;
+	}
+	mode[0] = atoi(*argv);
+	if (!*++argv) {
+		for (i = 1; i < SPATIAL_MODE_MAX_IDX; i++)
+			mode[i] = mode[0];
+	} else {
+		for (i = 1; i < SPATIAL_MODE_MAX_IDX; i++) {
+			mode[i] = atoi(*argv);
+			if (!*++argv && i < (SPATIAL_MODE_MAX_IDX - 1)) {
+				printf("error: missing arguments\n");
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+	err = wlu_var_setbuf(wl, cmd->name, &mode, sizeof(mode));
+	return err;
+}
+
+static int
+wl_ratetbl_ppr(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr = NULL;
+	int err, i, *reply;
+	int val[12];
+
+	/* Order is 2G, 5G-LOW, 5G-MID, 5G-HIGH, 5G-UPPER
+	 * if only one argument given, than all band or sub-band take the
+	 * same value
+	 */
+	memset(&val, 0, sizeof(val));
+	if (!*++argv) {
+		if ((err = wlu_var_getbuf(wl, cmd->name, &val, sizeof(val), &ptr)) < 0)
+			return err;
+		reply = (int *)ptr;
+		for (i = 0; i < 12; i++)
+			printf("%s: %2d\n", (reply[i] & 0x80) ? "OFDM" : "CCK ", (reply[i] & 0x7f));
+		return 0;
+	}
+	val[0] = atoi(*argv++);
+	val[1] = atoi(*argv++);
+	err = wlu_var_setbuf(wl, cmd->name, &val, sizeof(val));
+	return err;
+}
+
+static int
+wl_mimo_ps_learning_cfg(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_mimops_learning_cfg_t mimo_ps_learning_cfg;
+	char *endptr;
+	int i;
+	long val;
+	int err;
+
+	/* toss the command name */
+	argv++;
+	if (!*argv) {
+		err = wl_mimo_ps_learning_cfg_get_status(wl, cmd->name);
+		return err;
+	}
+	memset(&mimo_ps_learning_cfg, 0, sizeof(wl_mimops_learning_cfg_t));
+	for (i = 0; i < WL_MIMO_PS_LEARNING_MAX_PARAMS; i++, argv++) {
+		if (!*argv) {
+			break;
+		}
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			return BCME_BADARG;
+		}
+
+		switch (i) {
+			case 0:
+				if (val == 0)
+					mimo_ps_learning_cfg.flag =
+						(uint8)WL_MIMO_PS_PS_LEARNING_CFG_STATUS;
+				else if (val == 1)
+					mimo_ps_learning_cfg.flag =
+						(uint8)WL_MIMO_PS_PS_LEARNING_CFG_ABORT;
+				else if (val == 2)
+					mimo_ps_learning_cfg.flag =
+						(uint8)WL_MIMO_PS_PS_LEARNING_CFG_CONFIG;
+				else
+					return BCME_BADARG;
+				break;
+			case 1:
+				mimo_ps_learning_cfg.no_of_packets_for_learning = (uint32)val;
+				mimo_ps_learning_cfg.learning_rssi_threshold = 0;
+				break;
+			case 2:
+				mimo_ps_learning_cfg.learning_rssi_threshold = (int8)val;
+				break;
+
+			default:
+				return BCME_BADARG;
+		}
+	}
+	/* At the end get the configuration and display */
+	mimo_ps_learning_cfg.version = WL_MIMO_PS_PS_LEARNING_CFG_V1;
+	err = wlu_iovar_set(wl, cmd->name,
+		(void*)&mimo_ps_learning_cfg, sizeof(wl_mimops_learning_cfg_t));
+	return err;
+}
+
+
+static int
+wl_mimo_ps_learning_cfg_get_status(void *wl, const char *iovar)
+{
+	wl_mimops_learning_cfg_t mimo_ps_learning_data;
+	int err;
+	err = wlu_iovar_get(wl, iovar, &mimo_ps_learning_data, sizeof(wl_mimops_learning_cfg_t));
+	if (err < 0)
+		return err;
+
+	printf("\n Current MIMO PS Learning data :-  \n");
+	printf("\t BSSID %s\n",
+		wl_ether_etoa(&mimo_ps_learning_data.mimops_learning_data.BSSID));
+	printf("\t Start time stamp %d\n",
+		mimo_ps_learning_data.mimops_learning_data.startTimeStamp);
+	printf("\t End time stamp %d\n",
+		mimo_ps_learning_data.mimops_learning_data.endTimeStamp);
+	printf("\t Total MIMO above threshold %d\n",
+		mimo_ps_learning_data.mimops_learning_data.totalMIMO_above_rssi_threshold);
+	printf("\t Total MIMO below threshold %d\n",
+		mimo_ps_learning_data.mimops_learning_data.totalMIMO_below_rssi_threshold);
+	printf("\t Total SISO above threshold %d\n",
+		mimo_ps_learning_data.mimops_learning_data.totalSISO_above_rssi_threshold);
+	printf("\t Total SISO below threshold %d\n",
+		mimo_ps_learning_data.mimops_learning_data.totalSISO_below_rssi_threshold);
+	if (mimo_ps_learning_data.version == WL_MIMO_PS_PS_LEARNING_CFG_V1) {
+		printf("\t mimo_ps learning version %d\n",
+				mimo_ps_learning_data.version);
+		printf("\t mimo_ps learning rssi threshold value %d\n",
+				mimo_ps_learning_data.learning_rssi_threshold);
+	}
+	printf("\t mimo_ps no of packets to wait for  %d\n",
+		mimo_ps_learning_data.no_of_packets_for_learning);
+	if (mimo_ps_learning_data.mimops_learning_data.reason ==
+		WL_MIMO_PS_PS_LEARNING_ABORTED)
+			printf("\t REASON : MIMO PS LEARNING ABORTED\n");
+	else if (mimo_ps_learning_data.mimops_learning_data.reason ==
+		WL_MIMO_PS_PS_LEARNING_COMPLETED)
+			printf("\t REASON :  MIMO PS LEARNING COMPLETED\n");
+	else if (mimo_ps_learning_data.mimops_learning_data.reason ==
+		WL_MIMO_PS_PS_LEARNING_ONGOING)
+			printf("\t REASON :  MIMO PS LEARNING IN PRPGRESS\n");
+	else
+		printf("\t REASON :  UNKNOWN \n");
+	return err;
+}
+
+static int
+wl_mimo_ps_cfg(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_mimops_cfg_t mimo_ps_cfg;
+	char *endptr;
+	int i;
+	long val;
+	int err;
+
+	/* toss the command name */
+	argv++;
+	if (!*argv) {
+		err = wlu_iovar_get(wl, cmd->name, &mimo_ps_cfg, sizeof(wl_mimops_cfg_t));
+
+		if (err < 0)
+			return err;
+		printf("\n Current MIMO PS CFG :-  \n"
+		"\t active chains = %d\n \t mode = %d \n\t bandwidth = %d "
+		"\t apply changes after learning = %d\n",
+		mimo_ps_cfg.active_chains, mimo_ps_cfg.mode, mimo_ps_cfg.bandwidth,
+		mimo_ps_cfg.applychangesafterlearning);
+		return 0;
+	}
+	memset(&mimo_ps_cfg, 0, sizeof(wl_mimops_cfg_t));
+	for (i = 0; i < WL_MIMO_PS_MAX_PARAMS; i++, argv++) {
+		if (!*argv) {
+			break;
+		}
+		val = strtol(*argv, &endptr, 0);
+		if (*endptr != '\0') {
+			return BCME_BADARG;
+		}
+
+		switch (i) {
+			case 0:
+				mimo_ps_cfg.active_chains = (int8)val;
+				break;
+			case 1:
+				mimo_ps_cfg.mode = (int8)val;
+				break;
+			case 2:
+				mimo_ps_cfg.bandwidth = (int8)val;
+				break;
+			case 3:
+				mimo_ps_cfg.applychangesafterlearning = (int8) val;
+				break;
+			default:
+				return BCME_BADARG;
+		}
+	}
+	mimo_ps_cfg.version = WL_MIMO_PS_CFG_VERSION_1;
+	err = wlu_iovar_set(wl, cmd->name, (void*)&mimo_ps_cfg, sizeof(wl_mimops_cfg_t));
+	return err;
+}
+
+static int
+wl_mimo_ps_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_mimo_ps_status_t mimo_ps_status;
+
+	/* toss the command name */
+	argv++;
+
+	err = wlu_iovar_get(wl, cmd->name, &mimo_ps_status, sizeof(wl_mimo_ps_status_t));
+	if (err < 0)
+		return err;
+	/* Check version */
+	if ((mimo_ps_status.version != WL_MIMO_PS_STATUS_VERSION_1) &&
+	    (mimo_ps_status.version != WL_MIMO_PS_STATUS_VERSION_2) &&
+	    (mimo_ps_status.version != WL_MIMO_PS_STATUS_VERSION_3)) {
+		printf("Unexpected version: %u\n", mimo_ps_status.version);
+		return BCME_VERSION;
+	}
+	/* dump */
+	err = wl_mimo_ps_status_dump(&mimo_ps_status);
+	return err;
+}
+
+static const char *mimo_ps_status_state_str_tbl[] = {
+	"STATE_NONE",
+	"INFORM_AP_IN_PROGRESS",
+	"INFORM_AP_DONE",
+	"LEARNING",
+	"HW_CONFIGURE",
+	"INFORM_AP_PENDING"
+};
+
+static const char *mimo_ps_status_bw_str_tbl[] = {
+	"FULL",
+	"20MHz",
+	"40MHz",
+	"80MHz",
+	"160MHz",
+	"8080MHz"
+};
+
+static const char *mimo_ps_status_hw_state_str_tbl[] = {
+	"NONE",
+	"LTE_COEX",
+	"MIMOPS_BSS",
+	"AWDL_BSS",
+	"SCAN",
+	"TXPPR",
+	"PWRTHOTTLE",
+	"TEMPSENSE",
+	"IOVAR",
+	"AP_BSS"
+};
+
+static const char *mimo_ps_status_mhf_flag[] = {
+	"Disabled",
+	"Enabled",
+	"Core Down",
+	"Unsupported"
+};
+
+static int
+wl_mimo_ps_status_dump(wl_mimo_ps_status_t *status)
+{
+	int err = BCME_OK;
+	uint8 ap_cap_bw;
+
+	if (status == NULL)
+		return BCME_ERROR;
+
+	ap_cap_bw = WL_MIMO_PS_STATUS_AP_CAP_BW(status->ap_cap);
+
+	/* AP capability (MIMO,SISO)/BW */
+	printf("AP capability: ");
+	err = wl_mimo_ps_status_assoc_status_dump(WL_MIMO_PS_STATUS_AP_CAP(status->ap_cap));
+	if (ap_cap_bw > (ARRAYSIZE(mimo_ps_status_bw_str_tbl)-1)) {
+		printf("/Invalid BW value=%d\n", ap_cap_bw);
+		err = BCME_BADARG;
+	} else {
+		if (WL_MIMO_PS_STATUS_AP_CAP(status->ap_cap) != WL_MIMO_PS_STATUS_ASSOC_NONE)
+			printf("/%s", mimo_ps_status_bw_str_tbl[ap_cap_bw]);
+		printf("\n");
+	}
+
+	/* Association */
+	printf("Association: ");
+	err = wl_mimo_ps_status_assoc_status_dump(status->association_status &
+		WL_MIMO_PS_STATUS_ASSOC_STATUS_MASK);
+	if (status->association_status & WL_MIMO_PS_STATUS_ASSOC_STATUS_VHT_WITHOUT_OMN)
+		printf("\t(AP without OMN)");
+	printf("\n");
+
+	/* mimo_ps_cfg state */
+	printf("MIMO PS state: ");
+	if (status->mimo_ps_state > (ARRAYSIZE(mimo_ps_status_state_str_tbl)-1)) {
+		printf("\tInvalid MIMO PS state=%d\n", status->mimo_ps_state);
+		err = BCME_BADARG;
+	} else {
+		printf("\t%s\n", mimo_ps_status_state_str_tbl[status->mimo_ps_state]);
+	}
+
+	/* mrc_state */
+	printf("MRC state: ");
+	if (status->mrc_state == WL_MIMO_PS_STATUS_MRC_NONE)
+		printf("\tNot active\n");
+	else if (status->mrc_state == WL_MIMO_PS_STATUS_MRC_ACTIVE)
+		printf("\tACTIVE\n");
+	else {
+		printf("\tInvalid MRC state\n");
+		err = BCME_BADARG;
+	}
+	/* bss information */
+	printf("bss_rxchain:\t0x%02x\n", status->bss_rxchain);
+	printf("bss_txchain:\t0x%02x\n", status->bss_txchain);
+	printf("bss_bw: ");
+	if (status->bss_bw > (ARRAYSIZE(mimo_ps_status_bw_str_tbl)-1)) {
+		printf("\tInvalid bandwidth value=%d\n", status->bss_bw);
+		err = BCME_BADARG;
+	} else
+		printf("\t%s\n", mimo_ps_status_bw_str_tbl[status->bss_bw]);
+
+	/* hw_state */
+	wl_mimo_ps_status_hw_state_dump(status->hw_state);
+
+	/* hw information */
+	printf("hw_rxchain:\t0x%02x\n", status->hw_rxchain);
+	printf("hw_txchain:\t0x%02x\n", status->hw_txchain);
+	printf("hw_bw: ");
+	if (status->hw_bw > (ARRAYSIZE(mimo_ps_status_bw_str_tbl)-1)) {
+		printf("\tInvalid bandwidth value=%d\n", status->hw_bw);
+		err = BCME_BADARG;
+	} else
+		printf("\t\t%s\n", mimo_ps_status_bw_str_tbl[status->hw_bw]);
+
+	if (status->version == WL_MIMO_PS_STATUS_VERSION_1)
+		return err;
+
+	printf("PM_BCNRX state: ");
+	if (status->pm_bcnrx_state > (ARRAYSIZE(mimo_ps_status_mhf_flag) - 1)) {
+		printf("\tInvalid value %d\n", status->pm_bcnrx_state);
+	} else {
+		printf("\t%s\n", mimo_ps_status_mhf_flag[status->pm_bcnrx_state]);
+	}
+
+	printf("SISO_BCMC_RX state: ");
+	if (status->siso_bcmc_rx_state > (ARRAYSIZE(mimo_ps_status_mhf_flag) - 1)) {
+		printf("\tInvalid value %d\n", status->siso_bcmc_rx_state);
+	} else {
+		char *astr = "";
+		if (status->siso_bcmc_rx_state == WL_MIMO_PS_STATUS_MHF_FLAG_ACTIVE) {
+			if ((status->pm_bcnrx_state == WL_MIMO_PS_STATUS_MHF_FLAG_NONE) ||
+			    (status->pm_bcnrx_state == WL_MIMO_PS_STATUS_MHF_FLAG_INVALID))
+				astr = " (Inactive)";
+			else if (status->pm_bcnrx_state == WL_MIMO_PS_STATUS_MHF_FLAG_ACTIVE)
+				astr = " (Active)";
+		}
+		printf("\t%s%s\n", mimo_ps_status_mhf_flag[status->siso_bcmc_rx_state], astr);
+	}
+
+	printf("BSSBasicRateSet: %s\n", (status->basic_rates_present ? "Yes" : "No"));
+
+	return err;
+}
+
+static void
+wl_mimo_ps_status_hw_state_dump(uint16 hw_state)
+{
+	uint i, n;
+
+	printf("HW state: \t0x%04x\n", hw_state);
+	if (hw_state == 0) {
+		printf("\t\t%s\n", mimo_ps_status_hw_state_str_tbl[hw_state]);
+		return;
+	}
+	n = MIN(ARRAYSIZE(mimo_ps_status_hw_state_str_tbl), NBITS(hw_state));
+	for (i = 0; i < n; i++) {
+		if (hw_state & (0x1 << (i-1))) {
+			printf("\t\t%s\n", mimo_ps_status_hw_state_str_tbl[i]);
+		}
+	}
+}
+
+static int
+wl_mimo_ps_status_assoc_status_dump(uint8 assoc_status)
+{
+	switch (assoc_status) {
+	case WL_MIMO_PS_STATUS_ASSOC_NONE:
+		printf("\tNot associated");
+		break;
+	case WL_MIMO_PS_STATUS_ASSOC_SISO:
+		printf("\tSISO");
+		break;
+	case WL_MIMO_PS_STATUS_ASSOC_MIMO:
+		printf("\tMIMO");
+		break;
+	case WL_MIMO_PS_STATUS_ASSOC_LEGACY:
+		printf("\tLEGACY");
+		break;
+	default:
+		printf("Invalid AP cap/association status\n");
+		break;
+	}
+	return BCME_OK;
+}
+
+static int
+wl_temp_throttle_control(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_temp_control_t temp_control;
+	char *endptr;
+	long val;
+	int err;
+
+	memset(&temp_control, 0, sizeof(wl_temp_control_t));
+
+	if (!*++argv) {
+		/* Get */
+		err = wlu_iovar_get(wl, cmd->name, &temp_control, sizeof(wl_temp_control_t));
+
+		if (err < 0) {
+			return err;
+		}
+
+		if (temp_control.enable == 0) {
+			printf("Temp control is off\n");
+			return BCME_OK;
+		}
+
+		printf("Current mode : 0x%x\n", temp_control.control_bit);
+		return BCME_OK;
+	} else {
+		/* Enable / Disable */
+		val = atoi(*argv);
+		temp_control.enable = val;
+		argv++;
+
+		if (temp_control.enable == 1) {
+			if (!*argv) {
+				return BCME_ERROR;
+			}
+
+			val = strtol(*argv, &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+			if (val > 0xFF) {
+				printf("Out of range\n");
+				return BCME_OUTOFRANGECHAN;
+			}
+
+			temp_control.control_bit = val;
+		}
+
+		err = wlu_iovar_set(wl, cmd->name, &temp_control, sizeof(wl_temp_control_t));
+
+		return err;
+	}
+}
+static int
+wl_ocl_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = BCME_OK;
+	ocl_status_info_t ocl_status;
+
+	/* toss the command name */
+	argv++;
+
+	err = wlu_iovar_get(wl, cmd->name, &ocl_status, sizeof(ocl_status));
+	if (err < 0)
+		return err;
+	/* Check version */
+	if (ocl_status.version != WL_OCL_STATUS_VERSION) {
+		printf("Unexpected version: %u\n", ocl_status.version);
+		return BCME_VERSION;
+	}
+	/* validate length */
+	if (ocl_status.len < (uint8) sizeof(ocl_status)) {
+		fprintf(stderr, "OCL Status: short len %d < %d\n",
+		        ocl_status.len, (int)sizeof(ocl_status));
+		return BCME_ERROR;
+	}
+	/* dump fw/hw state */
+	wl_ocl_status_fw_dump(ocl_status.fw_status);
+	wl_ocl_status_hw_dump(ocl_status.hw_status);
+	printf("OCL Coremask      : 0x%02x   (Core-%d)\n",
+			ocl_status.coremask, ocl_status.coremask-1);
+
+	return err;
+}
+
+static const char *ocl_status_fw_state_str_tbl[] = {
+	"HOST",
+	"RSSI",
+	"LTEC",
+	"SISO",
+	"CAL",
+	"CHAN",
+	"ASPND"
+};
+static const char *ocl_status_hw_state_str_tbl[] = {
+	"OCL",
+	"MIMO",
+	"", "", "", "", "",
+	"Core Down"
+};
+
+static void
+wl_ocl_status_fw_dump(uint16 fw_state)
+{
+	uint i, n;
+	bool first = TRUE;
+
+	printf("FW Disable Reason : 0x%04x (", fw_state);
+	if (fw_state == 0) {
+		printf("%s)\n", "NONE");
+		return;
+	}
+	n = MIN(ARRAYSIZE(ocl_status_fw_state_str_tbl), NBITS(fw_state));
+	for (i = 0; i < n; i++) {
+		if (fw_state & (0x1 << (i))) {
+			printf("%s%s", first ? "": ", ", ocl_status_fw_state_str_tbl[i]);
+			first = FALSE;
+		}
+	}
+	printf(")\n");
+}
+
+static void
+wl_ocl_status_hw_dump(uint8 hw_state)
+{
+	uint i, n;
+	bool first = TRUE;
+
+	printf("HW Status Bits    : 0x%02x   ", hw_state);
+	n = MIN(ARRAYSIZE(ocl_status_hw_state_str_tbl), NBITS(hw_state));
+	for (i = 0; i < n; i++) {
+		if (hw_state & (0x1 << (i))) {
+			printf("%s%s", first ? "(": ", ", ocl_status_hw_state_str_tbl[i]);
+			first = FALSE;
+		}
+	}
+	printf("%s\n", hw_state ? ")" : "");
+}
diff --git a/wl/src/wl/exe/wluc_tbow.c b/wl/src/wl/exe/wluc_tbow.c
new file mode 100644
index 0000000..fc41684
--- /dev/null
+++ b/wl/src/wl/exe/wluc_tbow.c
@@ -0,0 +1,164 @@
+/*
+ * wl tbow command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_tbow.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+#ifdef LINUX
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* LINUX */
+
+static cmd_func_t wl_tbow_doho;
+
+static cmd_t wl_tbow_cmds[] = {
+	{ "tbow_doho", wl_tbow_doho, -1, WLC_SET_VAR,
+	"Trigger the BT-WiFi handover/handback"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_tbow_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register tbow commands */
+	wl_module_cmds_register(wl_tbow_cmds);
+}
+
+static int
+wl_tbow_doho(void *wl, cmd_t *cmd, char **argv)
+{
+	tbow_setup_netinfo_t netinfo;
+	char ssid_buf[TBOW_MAX_SSID_LEN + 1];
+	char passph[TBOW_MAX_PASSPHRASE_LEN + 1];
+
+	if (!*++argv) {
+		printf("wl tbow_doho <opmode> <chanspec> <ssid> <passphrase> <go_ifaddr>\n");
+		return -1;
+	}
+
+	netinfo.version = WL_TBOW_SETUPINFO_T_VERSION;
+	netinfo.opmode = atoi(*argv++);
+	switch (netinfo.opmode) {
+	case TBOW_HO_MODE_START_GO: /* Start GO */
+	case TBOW_HO_MODE_START_STA: /* Start STA */
+	case TBOW_HO_MODE_START_GC: /* Start GC */
+		netinfo.chanspec = wf_chspec_aton(*argv++);
+		printf("Chanspec: 0x%x\n", netinfo.chanspec);
+
+		if (!*argv) {
+			printf("SSID is not given\n");
+			return -1;
+		}
+		netinfo.ssid_len = strlen(*argv);
+		if (netinfo.ssid_len > TBOW_MAX_SSID_LEN) {
+			printf("Too long SSID: %d bytes\n", netinfo.ssid_len);
+			return -1;
+		}
+		memcpy(netinfo.ssid, *argv, netinfo.ssid_len);
+		memcpy(ssid_buf, *argv, netinfo.ssid_len);
+		ssid_buf[netinfo.ssid_len] = 0;
+		printf("SSID: %s\n", ssid_buf);
+
+		++argv;
+		if (!*argv) {
+			printf("Passphrase is not given\n");
+			return -1;
+		}
+		netinfo.passphrase_len = strlen(*argv);
+		if (netinfo.passphrase_len > TBOW_MAX_PASSPHRASE_LEN) {
+			printf("Too long passphrase: %d bytes\n", netinfo.passphrase_len);
+			return -1;
+		}
+		memcpy(netinfo.passphrase, *argv, netinfo.passphrase_len);
+		memcpy(passph, *argv, netinfo.passphrase_len);
+		passph[netinfo.passphrase_len] = 0;
+		printf("PASSPHRASE: %s\n", passph);
+
+		/* Start GO */
+		if (netinfo.opmode == TBOW_HO_MODE_START_GO ||
+		    netinfo.opmode == TBOW_HO_MODE_START_GC) {
+			++argv;
+			if (!*argv) {
+				printf("MAC address is not given for GO/GC\n");
+				return -1;
+			}
+			if (!wl_ether_atoe(*argv, (struct ether_addr *)&netinfo.macaddr)) {
+				printf(" ERROR: no valid ether addr provided\n");
+				return -1;
+			}
+			if (netinfo.opmode == TBOW_HO_MODE_START_GO)
+				printf("Own MAC ADDRESS: %s\n",
+				        wl_ether_etoa((struct ether_addr *)&netinfo.macaddr));
+			else
+				printf("GO BSSID: %s\n",
+				        wl_ether_etoa((struct ether_addr *)&netinfo.macaddr));
+		}
+		break;
+
+	case TBOW_HO_MODE_STOP_GO:
+	case TBOW_HO_MODE_STOP_GC:
+	case TBOW_HO_MODE_STOP_STA:
+	case TBOW_HO_MODE_TEST_GO:
+	case TBOW_HO_MODE_TEARDOWN:
+		break;
+
+	default:
+		printf("Invalid opmode: %d\n", netinfo.opmode);
+		return -1;
+	}
+
+	return wlu_iovar_set(wl, cmd->name, &netinfo, sizeof(netinfo));
+}
diff --git a/wl/src/wl/exe/wluc_tdls.c b/wl/src/wl/exe/wluc_tdls.c
new file mode 100644
index 0000000..00e1720
--- /dev/null
+++ b/wl/src/wl/exe/wluc_tdls.c
@@ -0,0 +1,600 @@
+/*
+ * wl tdls command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_tdls.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_tdls_endpoint;
+static cmd_func_t wl_tdls_wfd_ie;
+
+static cmd_t wl_tdls_cmds[] = {
+	{ "tdls_endpoint", wl_tdls_endpoint, WLC_GET_VAR, WLC_SET_VAR,
+	"Available TDLS operations to each TDLS peer.\n"
+	"\tusage: wl tdls_endpoint <disc, create, delete, PM, wake, cw> <ea> [chanspec]\n"
+	"\t       [chanspec] only applies to 'cw' operaton.\n\n"
+	"\t       addendum:\n"
+	"\t       wl tdls_endpoint wfd_disc <ea> sends a WFD tunneled Probe Request"},
+	{ "tdls_wfd_ie", wl_tdls_wfd_ie, WLC_GET_VAR, -1,
+	"To set, get and clear additional WFD IE in setup_req and setup_resp\n"
+	"\tTo set2, get2 and clear2 additional WFD IE in tunneled probe_req and probe_resp\n"
+	"\tusage: wl tdls_wfd_ie get  <own|peer_eth_addr#> [ip] [port]\n"
+	"\t       wl tdls_wfd_ie get2 <own|peer_eth_addr#> [alt_mac] [port] [PC_bit]\n"
+	"\t\t       peer_eth_addr#: HH:HH:HH:HH:HH:HH\n"
+	"\t\t       and peer must be TDLS connected (only in case of setup)\n\n"
+	"\t       wl tdls_wfd_ie <clr|clr2> own\n\n"
+	"\t       wl tdls_wfd_ie set  own wfd_ie_hexa_string [ip# [port# [type# [bssid#]]]]\n"
+	"\t       wl tdls_wfd_ie set2 own wfd_ie_hexa_string [alt_mac# [port# [type#]]]\n"
+	"\t\t       wfd_ie_hexa_string: should start with the full WFD IE header\n"
+	"\t\t                           e.g. 0xDDXX506F9A0A...\n"
+	"\t\t       ip#:      XXX.XXX.XXX.XXX\n"
+	"\t\t       alt_mac#: HH:HH:HH:HH:HH:HH\n"
+	"\t\t       port#:    0-65535\n"
+	"\t\t       type#:    0 for source, 1 for primary sink\n"
+	"\t\t       bssid#:   HH:HH:HH:HH:HH:HH"},
+	{ "tdls_sta_info", wl_sta_info, WLC_GET_VAR, -1,
+	"wl tdls_sta_info <xx:xx:xx:xx:xx:xx>"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_tdls_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register tdls commands */
+	wl_module_cmds_register(wl_tdls_cmds);
+}
+
+static int
+wl_tdls_endpoint(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname_tdls = "tdls_endpoint";
+	tdls_iovar_t info;
+	chanspec_t chanspec;
+
+	if (strcmp(cmd->name, cmdname_tdls)) {
+		printf("error: invalid command name.\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	memset(&info, 0, sizeof(tdls_iovar_t));
+
+	if (!strcmp("create", *argv))
+		info.mode = TDLS_MANUAL_EP_CREATE;
+	else if (!strcmp("modify", *argv))
+		info.mode = TDLS_MANUAL_EP_MODIFY;
+	else if (!strcmp("delete", *argv))
+		info.mode = TDLS_MANUAL_EP_DELETE;
+	else if (!strcmp("PM", *argv))
+		info.mode = TDLS_MANUAL_EP_PM;
+	else if (!strcmp("wake", *argv))
+		info.mode = TDLS_MANUAL_EP_WAKE;
+	else if (!strcmp("disc", *argv))
+		info.mode = TDLS_MANUAL_EP_DISCOVERY;
+	else if (!strcmp("cw", *argv)) {
+		info.mode = TDLS_MANUAL_EP_CHSW;
+	}
+	else if (!strcmp("wfd_disc", *argv))
+		info.mode = TDLS_MANUAL_EP_WFD_TPQ;
+	else {
+		printf("error: invalid mode string\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	argv++;
+	if (!*argv) {
+		printf("error: missing ea\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!wl_ether_atoe(*argv, &info.ea)) {
+		printf("error: could not parse MAC address %s\n", *argv);
+		return BCME_USAGE_ERROR;
+	}
+
+	if (info.mode == TDLS_MANUAL_EP_CHSW) {
+		argv++;
+		if (!*argv) {
+			printf("error: missing target channel number\n");
+			return BCME_USAGE_ERROR;
+		}
+		if (atoi(*argv) != 0) {
+			chanspec = wf_chspec_aton(*argv);
+			if (chanspec == 0) {
+				printf("error: bad chanspec \"%s\".\n", *argv);
+				return BCME_USAGE_ERROR;
+			}
+			chanspec = wl_chspec_to_driver(chanspec);
+			if (chanspec == INVCHANSPEC) {
+				return BCME_USAGE_ERROR;
+			}
+			info.chanspec = chanspec;
+		}
+	}
+
+	return wlu_var_setbuf(wl, cmd->name, &info, sizeof(info));
+}
+
+
+#define WFD_DEV			0
+#define WFD_DEV_LEN		6
+#define WFD_IP				8
+#define WFD_IP_LEN		5
+#define WFD_ALT_MAC		10
+#define WFD_ALT_MAC_LEN	6
+
+static int
+wl_tdls_wfd_ie(void *wl, cmd_t *cmd, char **argv)
+{
+	const char *cmdname_tdls = "tdls_wfd_ie";
+	tdls_wfd_ie_iovar_t info;
+	tdls_wfd_ie_iovar_t* buf_info = (tdls_wfd_ie_iovar_t*) buf;
+	int ret;
+	uint8* ptr;
+	uint8 element, subelement = 0;
+	uint16 offset;
+	uint8 buffer[TDLS_WFD_IE_SIZE - (WFA_OUI_LEN + 3)];
+	uint16 length, element_length, current_length;
+	bcm_tlv_t * ie;
+	unsigned long value;
+	struct ether_addr ea;
+	struct ipv4_addr ipa_set;
+
+	if (strcmp(cmd->name, cmdname_tdls)) {
+		printf("error: invalid command name.\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	if (!strcmp(*argv, "clr")) {
+		memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			info.mode = TDLS_WFD_IE_TX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		return wlu_var_setbuf(wl, cmd->name, &info, sizeof(info));
+
+	} else if (!strcmp(*argv, "get")) {
+		memset(buf_info, 0, sizeof(*buf_info));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			buf_info->mode = TDLS_WFD_IE_TX;
+		else if (wl_ether_atoe(*argv, &buf_info->ea))
+			buf_info->mode = TDLS_WFD_IE_RX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, buf_info,
+			sizeof(*buf_info), buf, WLC_IOCTL_MAXLEN)) < 0) {
+			return ret;
+		}
+
+		/* empty */
+		if (!buf_info->length)
+			return ret;
+
+		if (!*++argv)
+			wl_hexdump((uchar *)buf_info->data, buf_info->length);
+		else {
+			if (!strcmp("ip", *argv)) {
+				element = WFD_IP;
+				element_length = WFD_IP_LEN;
+			} else if (!strcmp("port", *argv)) {
+				element = WFD_DEV;
+				element_length = WFD_DEV_LEN;
+			} else {
+				printf("error: unknown element\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			/* Reassemble the WFD IE (without header) */
+
+			ptr = buf_info->data;
+			length = buf_info->length;
+			offset = 0;
+			current_length = 0;
+
+			while (length - offset > WFA_OUI_LEN + 3) {
+				if ((ie = bcm_parse_tlvs(ptr + offset,
+					length - offset, DOT11_MNG_VS_ID)) != NULL) {
+					if (ie->len > WFA_OUI_LEN + 1) {
+						if ((!memcmp(ie->data, WFA_OUI, WFA_OUI_LEN)) &&
+						    (*(ie->data + WFA_OUI_LEN) ==
+						    WFA_OUI_TYPE_WFD)) {
+							/* WFD */
+							memcpy(buffer + current_length,
+								ie->data + WFA_OUI_LEN + 1,
+								ie->len - WFA_OUI_LEN - 1);
+							current_length += ie->len - WFA_OUI_LEN - 1;
+						}
+					}
+					offset = (uint16)((uint8*)ie - ptr + ie->len + 2);
+				}
+				else
+					break;
+			}
+
+			/* Find the elements */
+
+			ptr = buffer;
+			length = current_length;
+
+			while (length > 3) {
+				current_length = (ptr[1] << 8) + ptr[2];
+				if ((ptr[0] == element) && (current_length == element_length) &&
+				(current_length <= length - 3)) {
+
+					switch (element) {
+						case WFD_IP:
+	/* we do not care about the IP version i.e. ptr[3] */
+	printf("%u.%u.%u.%u\n", ptr[4], ptr[5], ptr[6], ptr[7]);
+						break;
+
+						case WFD_DEV:
+	/* just get the RTSP TCP valid port */
+	printf("%u\n", (ptr[5] << 8) + ptr[6]);
+						break;
+					}
+					break;
+
+				} else {
+					if (current_length + 3 < length) {
+						length -= current_length + 3;
+						ptr += current_length + 3;
+					} else
+						break;
+				}
+			}
+		}
+
+		return ret;
+
+	} else if (!strcmp(*argv, "set")) {
+		memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			info.mode = TDLS_WFD_IE_TX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		argv++;
+		if (!*argv) {
+			printf("error: missing IE string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if (strlen((char*)*argv) - 2 > sizeof(info.data) * 2) {
+			printf("error: IE string too long; max is %u bytes\n",
+			    (unsigned int)sizeof(info.data));
+			return BCME_BADARG;
+		}
+
+		ret = wl_pattern_atoh(*argv, (char*)info.data);
+
+		if (ret <= 0) {
+			printf("error: could not parse IE string address %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		info.length = ret;
+
+		if (*++argv) {
+		/* IP specified */
+
+			/* watchdog */
+			if (info.length != 32) {
+				printf(
+				"if one or several set fields are used, "
+				"the following the IE string must be\n"
+				"exactly 32 bytes and must have the following order:\n"
+				"\t6-byte header (0xDD1E506F9A0A)\n"
+				"\t9-byte subelement 0 (WFD device information)\n"
+				"\t9-byte subelement 1 (BSSID)\n"
+				"\t8-byte subelement 8 (IP address)\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			if (!wl_atoip(*argv, &ipa_set))
+			return BCME_USAGE_ERROR;
+
+			memcpy(&info.data[28], (uint8*) &ipa_set, sizeof(ipa_set));
+
+			if (*++argv) {
+			/* port specified */
+
+				value = strtoul(*argv, NULL, 0);
+				info.data[11] = (uint8) (0xFF & (value >> 8));
+				info.data[12] = (uint8) (0xFF & value);
+
+				if (*++argv) {
+					/* WFD type (Source or Primary Sink) specified */
+
+					element = (uint8) (0x01 & strtoul(*argv, NULL, 0));
+					if (element)
+						info.data[10] |= 0x01;
+					else
+						info.data[10] &= ~0x01;
+
+					if (*++argv) {
+					/* BSSID specified */
+
+						if (!wl_ether_atoe(*argv, &ea))
+							return BCME_USAGE_ERROR;
+
+						memcpy(&info.data[18], (uint8*) &ea, sizeof(ea));
+					}
+				}
+			}
+		}
+
+		return wlu_var_setbuf(wl, cmd->name, &info, sizeof(info));
+
+	} else if (!strcmp(*argv, "clr2")) {
+		memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			info.mode = TDLS_WFD_PROBE_IE_TX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		return wlu_var_setbuf(wl, cmd->name, &info, sizeof(info));
+
+	} else if (!strcmp(*argv, "get2")) {
+		memset(buf_info, 0, sizeof(*buf_info));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			buf_info->mode = TDLS_WFD_PROBE_IE_TX;
+		else if (wl_ether_atoe(*argv, &buf_info->ea))
+			buf_info->mode = TDLS_WFD_PROBE_IE_RX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if ((ret = wlu_iovar_getbuf(wl, cmd->name, buf_info,
+			sizeof(*buf_info), buf, WLC_IOCTL_MAXLEN)) < 0) {
+			return ret;
+		}
+
+		/* empty */
+		if (!buf_info->length)
+			return ret;
+
+		if (!*++argv)
+			wl_hexdump((uchar *)buf_info->data, buf_info->length);
+
+		else {
+			if (!strcmp("alt_mac", *argv)) {
+				element = WFD_ALT_MAC;
+				element_length = WFD_ALT_MAC_LEN;
+			} else if (!strcmp("port", *argv)) {
+				element = WFD_DEV;
+				element_length = WFD_DEV_LEN;
+				subelement = 1;
+			} else if (!strcmp("PC_bit", *argv)) {
+				element = WFD_DEV;
+				element_length = WFD_DEV_LEN;
+				subelement = 0;
+			} else {
+				printf("error: unknown element\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			/* Reassemble the WFD IE (without header) */
+
+			ptr = buf_info->data;
+			length = buf_info->length;
+			offset = 0;
+			current_length = 0;
+
+			while (length - offset > WFA_OUI_LEN + 3) {
+				if ((ie = bcm_parse_tlvs(ptr + offset,
+					length - offset, DOT11_MNG_VS_ID)) != NULL) {
+					if (ie->len > WFA_OUI_LEN + 1) {
+						if ((!memcmp(ie->data, WFA_OUI, WFA_OUI_LEN)) &&
+							(*(ie->data + WFA_OUI_LEN) ==
+							WFA_OUI_TYPE_WFD)) {
+							/* WFD */
+							memcpy(buffer + current_length,
+								ie->data + WFA_OUI_LEN + 1,
+								ie->len - WFA_OUI_LEN - 1);
+							current_length += ie->len - WFA_OUI_LEN - 1;
+						}
+					}
+					offset = (uint16)((uint8*)ie - ptr + ie->len + 2);
+				}
+				else
+					break;
+			}
+
+			/* Find the elements */
+
+			ptr = buffer;
+			length = current_length;
+
+			while (length > 3) {
+				current_length = (ptr[1] << 8) + ptr[2];
+				if ((ptr[0] == element) && (current_length == element_length) &&
+					(current_length <= length - 3)) {
+
+					switch (element) {
+	case WFD_ALT_MAC:
+		printf("%02X:%02X:%02X:%02X:%02X:%02X\n",
+			ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8]);
+		break;
+	case WFD_DEV:
+			if (subelement)
+				/* just get the RTSP TCP valid port */
+				printf("%u\n", (ptr[5] << 8) + ptr[6]);
+			else
+				/* just get the Preferred Connection bit */
+				printf("%u\n", ptr[4] >> 7);
+		break;
+					}
+					break;
+
+				} else {
+					if (current_length + 3 < length) {
+						length -= current_length + 3;
+						ptr += current_length + 3;
+					} else
+						break;
+				}
+			}
+		}
+
+		return ret;
+
+	} else if (!strcmp(*argv, "set2")) {
+		memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
+
+		if (!*++argv)
+			return BCME_USAGE_ERROR;
+
+		if (!strcmp("own", *argv))
+			info.mode = TDLS_WFD_PROBE_IE_TX;
+		else {
+			printf("error: invalid mode string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		argv++;
+		if (!*argv) {
+			printf("error: missing IE string\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if (strlen((char*)*argv) - 2 > sizeof(info.data) * 2) {
+			printf("error: IE string too long; max is %u bytes\n",
+				(unsigned int)sizeof(info.data));
+			return BCME_USAGE_ERROR;
+		}
+
+		ret = wl_pattern_atoh(*argv, (char*)info.data);
+
+		if (ret <= 0) {
+			printf("error: could not parse IE string address %s\n", *argv);
+			return BCME_USAGE_ERROR;
+		}
+
+		info.length = ret;
+
+		if (*++argv) {
+		/* alt MAC specified */
+
+			/* watchdog */
+			if (info.length != 24) {
+				printf(
+				"if one or several set2 fields are used, "
+				"the following the IE string must be\n"
+				"exactly 24 bytes and must have the following order:\n"
+				"\t6-byte header (0xDD16506F9A0A)\n"
+				"\t9-byte subelement 0  (WFD device information)\n"
+				"\t9-byte subelement 10 (alternate MAC address)\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			if (!wl_ether_atoe(*argv, &ea))
+				return BCME_USAGE_ERROR;
+			memcpy(&info.data[18], (uint8*) &ea, sizeof(ea));
+
+			if (*++argv) {
+			/* port specified */
+
+				value = strtoul(*argv, NULL, 0);
+				info.data[11] = (uint8) (0xFF & (value >> 8));
+				info.data[12] = (uint8) (0xFF & value);
+
+				if (*++argv) {
+					/* WFD type (Source or Primary Sink) specified */
+
+					element = (uint8) (0x01 & strtoul(*argv, NULL, 0));
+					if (element)
+						info.data[10] |= 0x01;
+					else
+						info.data[10] &= ~0x01;
+				}
+			}
+		}
+
+		return wlu_var_setbuf(wl, cmd->name, &info, sizeof(info));
+
+	} else {
+		printf("error: unknown operation\n");
+		return BCME_USAGE_ERROR;
+	}
+}
diff --git a/wl/src/wl/exe/wluc_tko.c b/wl/src/wl/exe/wluc_tko.c
new file mode 100644
index 0000000..b8de37b
--- /dev/null
+++ b/wl/src/wl/exe/wluc_tko.c
@@ -0,0 +1,908 @@
+/*
+ * wl tko command module - TCP Keepalive Offload
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id:$
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#if defined(linux)
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <linux/if_packet.h>
+#endif /* linux */
+
+#include <wlioctl.h>
+
+#if defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+#include <sys/stat.h>
+#include <errno.h>
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include <proto/802.3.h>
+#include <proto/bcmip.h>
+#include <proto/bcmipv6.h>
+#include <proto/bcmtcp.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_tko;
+#if defined(linux)
+static cmd_func_t wl_tko_auto_config;
+static cmd_func_t wl_tko_event_check;
+#endif	/* linux */
+
+static cmd_t wl_tko_cmds[] = {
+	{ "tko", wl_tko, WLC_GET_VAR, WLC_SET_VAR,
+	"TCP keepalive offload subcommands:\n"
+	"\ttko max_tcp\n"
+	"\ttko param <interval> <retry interval> <retry count>\n"
+	"\ttko connect <index> [<ip_addr_type> <src MAC> <dst MAC>\n"
+		"<src IP> <dst IP> <src port> <dst port>\n"
+		"<seq num> <ack num> <TCP window>]\n"
+	"\ttko enable <0|1>\n"
+	"\ttko status\n"},
+#if defined(linux)
+	{ "tko_auto_config", wl_tko_auto_config, -1, WLC_SET_VAR,
+	"Listens for TCP and automatically configures TKO.\n"},
+	{ "tko_event_check", wl_tko_event_check, -1, WLC_SET_VAR,
+	"Listens for TKO event.\n"},
+#endif	/* linux */
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_tko_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register tko commands */
+	wl_module_cmds_register(wl_tko_cmds);
+}
+
+/* encode IPv6 TCP keepalive packet
+ * input 'buf' size = (ETHER_HDR_LEN + sizeof(struct ipv6_hdr) +
+ * 	sizeof(struct bcmtcp_hdr))
+ * returns the size of the encoded packet
+ */
+static int
+wl_ipv6_tcp_keepalive_pkt(uint8 *buf,
+	struct ether_addr *daddr, struct ether_addr *saddr,
+	struct ipv6_addr *dipv6addr, struct ipv6_addr *sipv6addr,
+	uint16 sport, uint16 dport, uint32 seq, uint32 ack, uint16 tcpwin)
+{
+	struct ether_header *eth;
+	struct ipv6_hdr *ipv6;
+	struct bcmtcp_hdr *tcp;
+
+	if (buf == NULL) {
+		return 0;
+	}
+
+	/* encode ethernet header */
+	eth = (struct ether_header *)buf;
+	memcpy(eth->ether_dhost, daddr, ETHER_ADDR_LEN);
+	memcpy(eth->ether_shost, saddr, ETHER_ADDR_LEN);
+	eth->ether_type = hton16(ETHER_TYPE_IPV6);
+
+	/* encode IPv6 header */
+	ipv6 = (struct ipv6_hdr *)(buf + sizeof(struct ether_header));
+	memset(ipv6, 0, sizeof(*ipv6));
+	ipv6->version = IPV6_VERSION;
+	ipv6->payload_len = hton16(sizeof(struct bcmtcp_hdr));
+	ipv6->nexthdr = IP_PROT_TCP;
+	ipv6->hop_limit = IPV6_HOP_LIMIT;
+	memcpy(&ipv6->daddr, dipv6addr, sizeof(ipv6->daddr));
+	memcpy(&ipv6->saddr, sipv6addr, sizeof(ipv6->saddr));
+
+	/* encode TCP header */
+	tcp = (struct bcmtcp_hdr *)(buf + sizeof(struct ether_header) + sizeof(struct ipv6_hdr));
+	memset(tcp, 0, sizeof(*tcp));
+	tcp->src_port = hton16(sport);
+	tcp->dst_port = hton16(dport);
+	tcp->seq_num = hton32(seq);
+	tcp->ack_num = hton32(ack);
+	tcp->tcpwin = hton16(tcpwin);
+	tcp->chksum = 0;
+	tcp->urg_ptr = 0;
+	tcp->hdrlen_rsvd_flags = (TCP_FLAG_ACK << 8) |
+	    ((sizeof(struct bcmtcp_hdr) >> 2) << TCP_HDRLEN_SHIFT);
+
+	/* calculate checksum */
+	tcp->chksum = ipv6_tcp_hdr_cksum((uint8 *)ipv6, (uint8 *)tcp, sizeof(*tcp));
+
+	return (sizeof(struct ether_header) + sizeof(struct ipv6_hdr) +
+		sizeof(struct bcmtcp_hdr));
+}
+
+/* encode TCP keepalive packet
+ * input 'buf' size = (ETHER_HDR_LEN + sizeof(struct ipv4_hdr) +
+ * 	sizeof(struct bcmtcp_hdr))
+ * returns the size of the encoded packet
+ */
+static int
+wl_tcp_keepalive_pkt(uint8 *buf,
+	struct ether_addr *daddr, struct ether_addr *saddr,
+	struct ipv4_addr *dipaddr, struct ipv4_addr *sipaddr,
+	uint16 sport, uint16 dport, uint32 seq, uint32 ack, uint16 tcpwin)
+{
+	struct ether_header *eth;
+	struct ipv4_hdr *ip;
+	struct bcmtcp_hdr *tcp;
+
+	if (buf == NULL) {
+		return 0;
+	}
+	eth = (struct ether_header *)buf;
+	memcpy(eth->ether_dhost, daddr, ETHER_ADDR_LEN);
+	memcpy(eth->ether_shost, saddr, ETHER_ADDR_LEN);
+	eth->ether_type = hton16(ETHER_TYPE_IP);
+	ip = (struct ipv4_hdr *)(buf + sizeof(struct ether_header));
+	memcpy(ip->dst_ip, dipaddr, IPV4_ADDR_LEN);
+	memcpy(ip->src_ip, sipaddr, IPV4_ADDR_LEN);
+	ip->version_ihl = (IP_VER_4 << IPV4_VER_SHIFT) | (IPV4_MIN_HEADER_LEN / 4);
+	ip->tos = 0;
+	ip->tot_len = hton16(sizeof(struct ipv4_hdr) + sizeof(struct bcmtcp_hdr));
+	ip->id = hton16(0);
+	ip->frag = 0;
+	ip->ttl = 32;
+	ip->prot = IP_PROT_TCP;
+	ip->hdr_chksum = 0;
+	ip->hdr_chksum = ipv4_hdr_cksum((uint8 *)ip, IPV4_HLEN(ip));
+	tcp = (struct bcmtcp_hdr *)(buf + sizeof(struct ether_header) +
+	    sizeof(struct ipv4_hdr));
+	tcp->src_port = hton16(sport);
+	tcp->dst_port = hton16(dport);
+	tcp->seq_num = hton32(seq);
+	tcp->ack_num = hton32(ack);
+	tcp->tcpwin = hton16(tcpwin);
+	tcp->chksum = 0;
+	tcp->urg_ptr = 0;
+	tcp->hdrlen_rsvd_flags = (TCP_FLAG_ACK << 8) |
+	    ((sizeof(struct bcmtcp_hdr) >> 2) << TCP_HDRLEN_SHIFT);
+
+	/* calculate TCP header checksum */
+	tcp->chksum = ipv4_tcp_hdr_cksum((uint8 *)ip, (uint8 *)tcp, sizeof(*tcp));
+
+	return (sizeof(struct ether_header) + sizeof(struct ipv4_hdr) +
+		sizeof(struct bcmtcp_hdr));
+}
+
+/* intialize TKO connect struct and returns the length of connect struct */
+static int
+wl_tko_connect_init(wl_tko_connect_t *connect, uint8 index, uint8 ip_addr_type,
+	struct ether_addr *saddr, struct ether_addr *daddr, void *sipaddr, void *dipaddr,
+	uint16 local_port, uint16 remote_port, uint32 local_seq, uint32 remote_seq, uint16 tcpwin)
+{
+	int data_len = 0;
+
+	connect->index = index;
+	connect->ip_addr_type = ip_addr_type;
+	connect->local_port = htod16(local_port);
+	connect->remote_port = htod16(remote_port);
+	connect->local_seq = htod32(local_seq);
+	connect->remote_seq = htod32(remote_seq);
+
+	if (ip_addr_type) {
+		/* IPv6 */
+		struct ipv6_addr *sipv6addr = sipaddr;
+		struct ipv6_addr *dipv6addr = dipaddr;
+
+		memcpy(&connect->data[data_len], sipv6addr, sizeof(*sipv6addr));
+		data_len += sizeof(*sipv6addr);
+		memcpy(&connect->data[data_len], dipv6addr, sizeof(*dipv6addr));
+		data_len += sizeof(*dipv6addr);
+		/* IPv6 TCP keepalive request */
+		connect->request_len = wl_ipv6_tcp_keepalive_pkt(
+			&connect->data[data_len], daddr, saddr,
+			dipv6addr, sipv6addr, local_port, remote_port,
+			local_seq - 1, remote_seq, tcpwin);
+		data_len += connect->request_len;
+		/* IPv6 TCP keepalive response */
+		connect->response_len = wl_ipv6_tcp_keepalive_pkt(
+			&connect->data[data_len], daddr, saddr,
+			dipv6addr, sipv6addr, local_port, remote_port,
+			local_seq, remote_seq, tcpwin);
+			data_len += connect->response_len;
+	} else {
+		/* IPv4 */
+		struct ipv4_addr *sipv4addr = sipaddr;
+		struct ipv4_addr *dipv4addr = dipaddr;
+
+		memcpy(&connect->data[data_len], sipv4addr, sizeof(*sipv4addr));
+		data_len += sizeof(*sipv4addr);
+		memcpy(&connect->data[data_len], dipv4addr, sizeof(*dipv4addr));
+		data_len += sizeof(*dipv4addr);
+		/* TCP keepalive request */
+		connect->request_len = wl_tcp_keepalive_pkt(
+			&connect->data[data_len], daddr, saddr,
+			dipv4addr, sipv4addr, local_port, remote_port,
+			local_seq - 1, remote_seq, tcpwin);
+		data_len += connect->request_len;
+		/* TCP keepalive response */
+		connect->response_len = wl_tcp_keepalive_pkt(
+			&connect->data[data_len], daddr, saddr,
+			dipv4addr, sipv4addr, local_port, remote_port,
+			local_seq, remote_seq, tcpwin);
+		data_len += connect->response_len;
+	}
+
+	return (OFFSETOF(wl_tko_connect_t, data) + data_len);
+}
+
+static int
+wl_tko(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	char *subcmd;
+	int subcmd_len;
+
+	/* skip iovar */
+	argv++;
+
+	/* must have subcommand */
+	subcmd = *argv++;
+	if (!subcmd) {
+		return BCME_USAGE_ERROR;
+	}
+	subcmd_len = strlen(subcmd);
+
+	/* GET for "connect" has 1 parameter */
+	if ((!*argv && strncmp(subcmd, "connect", subcmd_len)) ||
+		(!strncmp(subcmd, "connect", subcmd_len) && argv[0] && !argv[1])) {
+		/* get */
+		uint8 buffer[OFFSETOF(wl_tko_t, data) +	sizeof(wl_tko_get_connect_t)];
+		wl_tko_t *tko = (wl_tko_t *)buffer;
+		int len = OFFSETOF(wl_tko_t, data);
+
+		memset(tko, 0, len);
+		if (!strncmp(subcmd, "max_tcp", subcmd_len)) {
+			tko->subcmd_id = WL_TKO_SUBCMD_MAX_TCP;
+		} else if (!strncmp(subcmd, "param", subcmd_len)) {
+			tko->subcmd_id = WL_TKO_SUBCMD_PARAM;
+		} else if (!strncmp(subcmd, "connect", subcmd_len)) {
+			wl_tko_get_connect_t *get_connect = (wl_tko_get_connect_t *)tko->data;
+			tko->subcmd_id = WL_TKO_SUBCMD_CONNECT;
+			tko->len = sizeof(*get_connect);
+			get_connect->index = atoi(argv[0]);
+		} else if (!strncmp(subcmd, "enable", subcmd_len)) {
+			tko->subcmd_id = WL_TKO_SUBCMD_ENABLE;
+		} else if (!strncmp(subcmd, "status", subcmd_len)) {
+			tko->subcmd_id = WL_TKO_SUBCMD_STATUS;
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+		len += tko->len;
+
+		/* invoke GET iovar */
+		tko->subcmd_id = htod16(tko->subcmd_id);
+		tko->len = htod16(tko->len);
+		if ((err = wlu_iovar_getbuf(wl, cmd->name, tko, len, buf, WLC_IOCTL_MEDLEN)) < 0) {
+			return err;
+		}
+
+		/* process and print GET results */
+		tko = (wl_tko_t *)buf;
+		tko->subcmd_id = dtoh16(tko->subcmd_id);
+		tko->len = dtoh16(tko->len);
+
+		switch (tko->subcmd_id) {
+		case WL_TKO_SUBCMD_MAX_TCP:
+		{
+			wl_tko_max_tcp_t *max_tcp =
+				(wl_tko_max_tcp_t *)tko->data;
+			if (tko->len >= sizeof(*max_tcp)) {
+				printf("max TCP: %d\n", max_tcp->max);
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+
+		}
+		case WL_TKO_SUBCMD_PARAM:
+		{
+			wl_tko_param_t *param =	(wl_tko_param_t *)tko->data;
+			if (tko->len >= sizeof(*param)) {
+				param->interval = dtoh16(param->interval);
+				param->retry_interval = dtoh16(param->retry_interval);
+				param->retry_count = dtoh16(param->retry_count);
+				printf("interval: %d\n", param->interval);
+				printf("retry interval: %d\n", param->retry_interval);
+				printf("retry count: %d\n", param->retry_count);
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		case WL_TKO_SUBCMD_CONNECT:
+		{
+			wl_tko_connect_t *connect = (wl_tko_connect_t *)tko->data;
+			if (tko->len >= sizeof(*connect)) {
+				connect->local_port = dtoh16(connect->local_port);
+				connect->remote_port = dtoh16(connect->remote_port);
+				connect->local_seq = dtoh32(connect->local_seq);
+				connect->remote_seq = dtoh32(connect->remote_seq);
+				printf("index:        %d\n", connect->index);
+				printf("IP addr type: %d\n", connect->ip_addr_type);
+				printf("local port:   %u\n", connect->local_port);
+				printf("remote port:  %u\n", connect->remote_port);
+				printf("local seq:    %u\n", connect->local_seq);
+				printf("remote seq:   %u\n", connect->remote_seq);
+				if (connect->ip_addr_type) {
+					/* IPv6 */
+					printf("src IPv6:     %s\n",
+						wl_ipv6toa((struct ipv6_addr *)&connect->data[0]));
+					printf("dst IPv6:     %s\n",
+						wl_ipv6toa((struct ipv6_addr *)
+						&connect->data[IPV6_ADDR_LEN]));
+					printf("IPv6 TCP keepalive request\n");
+					wl_hexdump(&connect->data[2 * IPV6_ADDR_LEN],
+						connect->request_len);
+					printf("IPv6 TCP keepalive response\n");
+					wl_hexdump(&connect->data[2 * IPV6_ADDR_LEN +
+						connect->request_len], connect->response_len);
+				} else {
+					/* IPv4 */
+					printf("src IP:       %s\n",
+						wl_iptoa((struct ipv4_addr *)&connect->data[0]));
+					printf("dst IP:       %s\n",
+						wl_iptoa((struct ipv4_addr *)
+						&connect->data[IPV4_ADDR_LEN]));
+					printf("TCP keepalive request\n");
+					wl_hexdump(&connect->data[2 * IPV4_ADDR_LEN],
+						connect->request_len);
+					printf("TCP keepalive response\n");
+					wl_hexdump(&connect->data[2 * IPV4_ADDR_LEN +
+						connect->request_len], connect->response_len);
+				}
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		case WL_TKO_SUBCMD_ENABLE:
+		{
+			wl_tko_enable_t *tko_enable = (wl_tko_enable_t *)tko->data;
+			if (tko->len >= sizeof(*tko_enable)) {
+				printf("%d\n", tko_enable->enable);
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		case WL_TKO_SUBCMD_STATUS:
+		{
+			wl_tko_status_t *tko_status = (wl_tko_status_t *)tko->data;
+			if (tko->len >= sizeof(*tko_status)) {
+				int i;
+				for (i = 0; i < tko_status->count; i++) {
+					uint8 status = tko_status->status[i];
+					printf("%d: %s\n", i,
+					status == TKO_STATUS_NORMAL ? "normal" :
+					status == TKO_STATUS_NO_RESPONSE ? "no response" :
+					status == TKO_STATUS_NO_TCP_ACK_FLAG ? "no TCP ACK flag" :
+					status == TKO_STATUS_UNEXPECT_TCP_FLAG ?
+						"unexpected TCP flag" :
+					status == TKO_STATUS_SEQ_NUM_INVALID ? "seq num invalid" :
+					status == TKO_STATUS_REMOTE_SEQ_NUM_INVALID ?
+						"remote seq num invalid" :
+					status == TKO_STATUS_TCP_DATA ? "TCP data" :
+					status == TKO_STATUS_UNAVAILABLE ? "unavailable" :
+					"unknown");
+				}
+			} else {
+				err = BCME_BADLEN;
+			}
+			break;
+		}
+		default:
+			break;
+		}
+	}
+	else {
+		/* set */
+		wl_tko_t *tko = (wl_tko_t *)buf;
+		int len;
+
+		if (!strncmp(subcmd, "param", subcmd_len) &&
+			argv[0] && argv[1] && argv[2]) {
+			wl_tko_param_t *param =
+				(wl_tko_param_t *)tko->data;
+			tko->subcmd_id = WL_TKO_SUBCMD_PARAM;
+			tko->len = sizeof(*param);
+			param->interval = htod16(atoi(argv[0]));
+			param->retry_interval = htod16(atoi(argv[1]));
+			param->retry_count = htod16(atoi(argv[2]));
+		} else if (!strncmp(subcmd, "connect", subcmd_len) &&
+			argv[0] && argv[1] && argv[2] && argv[3] && argv[4] &&
+			argv[5] && argv[6] && argv[7] && argv[8] && argv[9] && argv[10]) {
+			wl_tko_connect_t *connect = (wl_tko_connect_t *)tko->data;
+			uint8 index;
+			uint8 ip_addr_type;
+			struct ether_addr saddr;
+			struct ether_addr daddr;
+			struct ipv4_addr sipaddr;
+			struct ipv4_addr dipaddr;
+			struct ipv6_addr sipv6addr;
+			struct ipv6_addr dipv6addr;
+			uint16 local_port;
+			uint16 remote_port;
+			uint32 local_seq;
+			uint32 remote_seq;
+			uint16 tcpwin;
+
+			index = atoi(argv[0]);
+			ip_addr_type = atoi(argv[1]);
+			if (!wl_ether_atoe(argv[2], &saddr)) {
+				return BCME_USAGE_ERROR;
+			}
+			if (!wl_ether_atoe(argv[3], &daddr)) {
+				return BCME_USAGE_ERROR;
+			}
+			if (ip_addr_type) {
+				/* IPv6 */
+				if (!wl_atoipv6(argv[4], &sipv6addr)) {
+					return BCME_USAGE_ERROR;
+				}
+				if (!wl_atoipv6(argv[5], &dipv6addr)) {
+					return BCME_USAGE_ERROR;
+				}
+			} else {
+				/* IPv4 */
+				if (!wl_atoip(argv[4], &sipaddr)) {
+					return BCME_USAGE_ERROR;
+				}
+				if (!wl_atoip(argv[5], &dipaddr)) {
+					return BCME_USAGE_ERROR;
+				}
+			}
+			local_port = atoi(argv[6]);
+			remote_port = atoi(argv[7]);
+			local_seq = bcm_strtoul(argv[8], NULL, 0);
+			remote_seq = bcm_strtoul(argv[9], NULL, 0);
+			tcpwin = atoi(argv[10]);
+
+			tko->subcmd_id = WL_TKO_SUBCMD_CONNECT;
+			tko->len = wl_tko_connect_init(connect, index, ip_addr_type,
+				&saddr, &daddr,
+				ip_addr_type ? (void *)&sipv6addr : (void *)&sipaddr,
+				ip_addr_type ? (void *)&dipv6addr : (void *)&dipaddr,
+				local_port, remote_port, local_seq, remote_seq, tcpwin);
+
+		} else if (!strncmp(subcmd, "enable", subcmd_len) &&
+			(!strcmp(argv[0], "0") || !strcmp(argv[0], "1"))) {
+			wl_tko_enable_t *tko_enable = (wl_tko_enable_t *)tko->data;
+			tko->subcmd_id = WL_TKO_SUBCMD_ENABLE;
+			tko->len = sizeof(*tko_enable);
+			tko_enable->enable = atoi(argv[0]);
+
+		} else {
+			return BCME_USAGE_ERROR;
+		}
+
+		/* invoke SET iovar */
+		len = OFFSETOF(wl_tko_t, data) + tko->len;
+		tko->subcmd_id = htod16(tko->subcmd_id);
+		tko->len = htod16(tko->len);
+		err = wlu_iovar_set(wl, cmd->name, tko, len);
+	}
+
+	return err;
+}
+
+#if defined(linux)
+
+#define ETH_P_ALL		0x0003
+#define TKO_BUFFER_SIZE		2048
+#define TKO_TCP_WINDOW_SIZE	400
+
+/* automatically configures TKO by monitoring TCP connections */
+static int
+wl_tko_auto_config(void *wl, cmd_t *cmd, char **argv)
+{
+	/* 802.3 llc/snap header */
+	static const uint8 llc_snap_hdr[SNAP_HDR_LEN] =
+		{0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
+	bool is_checksum = TRUE;
+	int err;
+	int fd = -1;
+	int i;
+	wl_tko_t *tko;
+	wl_tko_max_tcp_t *tko_max;
+	uint8 cur_tcp = 0;
+	uint8 max_tcp = 0;
+	uint8 **tko_buf = NULL;
+	uint8 *frame = NULL;
+	struct ether_addr ea;
+	struct sockaddr_ll sll;
+	struct ifreq ifr;
+	char ifnames[IFNAMSIZ] = {"eth1"};
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+	if (*argv) {
+		if (!stricmp(*argv, "-nochecksum")) {
+			/* note: ssh on FC15 has TCP checksum failures on packets read
+			 * from socket but checksum correct over-the-air
+			 */
+			printf("no checksum check\n");
+			is_checksum = FALSE;
+		}
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	if (wl) {
+		strncpy(ifr.ifr_name, ((struct ifreq *)wl)->ifr_name, (IFNAMSIZ - 1));
+	} else {
+		strncpy(ifr.ifr_name, ifnames, (IFNAMSIZ - 1));
+	}
+
+	if ((err = wlu_iovar_get(wl, "cur_etheraddr", &ea, ETHER_ADDR_LEN)) < 0) {
+		printf("Failed to get current ether address\n");
+		goto exit;
+	}
+
+	fd = socket(PF_PACKET, SOCK_RAW, hton16(ETH_P_ALL));
+	if (fd < 0) {
+		printf("Cannot create socket %d\n", fd);
+		err = -1;
+		goto exit;
+	}
+
+	err = ioctl(fd, SIOCGIFINDEX, &ifr);
+	if (err < 0) {
+		printf("Cannot get index %d\n", err);
+		goto exit;
+	}
+
+	/* bind the socket first before starting so we won't miss any event */
+	memset(&sll, 0, sizeof(sll));
+	sll.sll_family = AF_PACKET;
+	sll.sll_protocol = hton16(ETH_P_ALL);
+	sll.sll_ifindex = ifr.ifr_ifindex;
+	err = bind(fd, (struct sockaddr *)&sll, sizeof(sll));
+	if (err < 0) {
+		printf("Cannot bind %d\n", err);
+		goto exit;
+	}
+
+	/* get the max TCP connections supported */
+	tko = (wl_tko_t *)buf;
+	memset(tko, 0, sizeof(*tko));
+	tko->subcmd_id = htod16(WL_TKO_SUBCMD_MAX_TCP);
+	tko->len = htod16(tko->len);
+	if ((err = wlu_iovar_getbuf(wl, "tko", tko, sizeof(*tko), buf, WLC_IOCTL_SMLEN)) < 0) {
+		goto exit;
+	}
+	tko = (wl_tko_t *)buf;
+	tko_max = (wl_tko_max_tcp_t *)tko->data;
+	max_tcp = tko_max->max;
+
+	/* allocate TKO buffers */
+	tko_buf = (uint8 **)malloc(sizeof(uint8 *) * max_tcp);
+	if (tko_buf == NULL) {
+		printf("Cannot not allocate %d bytes for TKO buffer\n",
+			(int)(sizeof(uint8 *) * max_tcp));
+		err = BCME_NOMEM;
+		goto exit;
+	}
+	for (i = 0; i < max_tcp; i++) {
+		int size = OFFSETOF(wl_tko_t, data) + OFFSETOF(wl_tko_connect_t, data) + 1024;
+		tko_buf[i] = malloc(size);
+		if (tko_buf[i] == NULL) {
+			printf("Cannot not allocate %d bytes for TKO buffer\n",	size);
+			err = BCME_NOMEM;
+			goto exit;
+		}
+		memset(tko_buf[i], 0, size);
+	}
+
+	/* frame buffer */
+	frame = (uint8 *)malloc(TKO_BUFFER_SIZE);
+	if (frame == NULL) {
+		printf("Cannot not allocate %d bytes for receive buffer\n",
+			TKO_BUFFER_SIZE);
+		err = BCME_NOMEM;
+		goto exit;
+	}
+
+	/* receive result */
+	while (1) {
+		int length;
+		uint8 *end, *pt;
+		uint16 ethertype;
+		struct bcmtcp_hdr *tcp_hdr = NULL;
+		uint16 tcp_len = 0;
+		uint8 ip_addr_type = 0;
+		uint8 *src_ip = NULL;
+		uint8 *dst_ip = NULL;
+
+		length = recv(fd, frame, TKO_BUFFER_SIZE, 0);
+		end = frame + length;
+
+		if (length < ETHER_HDR_LEN) {
+			continue;
+		}
+
+		/* process only tx'ed packets */
+		if (memcmp(ea.octet, &frame[ETHER_SRC_OFFSET], sizeof(ea)) != 0) {
+			continue;
+		}
+
+		/* process Ethernet II or SNAP-encapsulated 802.3 frames */
+		if (ntoh16_ua((const void *)(frame + ETHER_TYPE_OFFSET)) >= ETHER_TYPE_MIN) {
+			/* Frame is Ethernet II */
+			pt = frame + ETHER_TYPE_OFFSET;
+		} else if (length >= ETHER_HDR_LEN + SNAP_HDR_LEN + ETHER_TYPE_LEN &&
+			!memcmp(llc_snap_hdr, frame + ETHER_HDR_LEN, SNAP_HDR_LEN)) {
+			pt = frame + ETHER_HDR_LEN + SNAP_HDR_LEN;
+		} else {
+			continue;
+		}
+
+		ethertype = ntoh16_ua((const void *)pt);
+		pt += ETHER_TYPE_LEN;
+
+		/* check ethertype */
+		if ((ethertype != ETHER_TYPE_IP) && (ethertype != ETHER_TYPE_IPV6)) {
+			continue;
+		}
+
+		if (ethertype == ETHER_TYPE_IP) {
+			struct ipv4_hdr *ipv4_hdr;
+			uint16 iphdr_len;
+			uint16 cksum;
+
+			ipv4_hdr = (struct ipv4_hdr *)pt;
+			iphdr_len = IPV4_HLEN(ipv4_hdr);
+			if (pt + iphdr_len > end) {
+				continue;
+			}
+			pt += iphdr_len;
+
+			if (ipv4_hdr->prot != IP_PROT_TCP) {
+				continue;
+			}
+
+			if (ntoh16(ipv4_hdr->frag) & IPV4_FRAG_OFFSET_MASK) {
+				continue;
+			}
+
+			if (ntoh16(ipv4_hdr->frag) & IPV4_FRAG_MORE) {
+				continue;
+			}
+
+			tcp_len = ntoh16(ipv4_hdr->tot_len) - iphdr_len;
+			if (pt + tcp_len > end) {
+				continue;
+			}
+			tcp_hdr = (struct bcmtcp_hdr *)pt;
+
+			/* verify IP header checksum */
+			cksum = ipv4_hdr_cksum((uint8 *)ipv4_hdr, iphdr_len);
+			if (cksum != ipv4_hdr->hdr_chksum) {
+				continue;
+			}
+
+			/* verify TCP header checksum */
+			if (is_checksum) {
+				cksum = ipv4_tcp_hdr_cksum((uint8 *)ipv4_hdr,
+					(uint8 *)tcp_hdr, tcp_len);
+				if (cksum != tcp_hdr->chksum) {
+					printf("TCP checksum failed: 0x%04x 0x%04x\n",
+						ntoh16(cksum), ntoh16(tcp_hdr->chksum));
+					continue;
+				}
+			}
+
+			ip_addr_type = 0;
+			src_ip = ipv4_hdr->src_ip;
+			dst_ip = ipv4_hdr->dst_ip;
+
+		} else if (ethertype == ETHER_TYPE_IPV6) {
+			struct ipv6_hdr *ipv6_hdr;
+			uint16 cksum;
+
+			if (pt + sizeof(struct ipv6_hdr) > end) {
+				continue;
+			}
+			ipv6_hdr = (struct ipv6_hdr *)pt;
+			pt += sizeof(struct ipv6_hdr);
+
+			if (ipv6_hdr->nexthdr != IP_PROT_TCP) {
+				continue;
+			}
+
+			tcp_len = ntoh16(ipv6_hdr->payload_len);
+			if (pt + tcp_len > end) {
+				continue;
+			}
+			tcp_hdr = (struct bcmtcp_hdr *)pt;
+
+			/* verify TCP checksum */
+			if (is_checksum) {
+				cksum = ipv6_tcp_hdr_cksum((uint8 *)ipv6_hdr,
+					(uint8 *)tcp_hdr, tcp_len);
+				if (cksum != tcp_hdr->chksum) {
+					printf("IPv6 TCP checksum failed: 0x%04x 0x%04x\n",
+						ntoh16(cksum), ntoh16(tcp_hdr->chksum));
+					continue;
+				}
+			}
+
+			ip_addr_type = 1;
+			src_ip = ipv6_hdr->saddr.addr;
+			dst_ip = ipv6_hdr->daddr.addr;
+		}
+
+		if (src_ip != NULL && dst_ip != NULL && tcp_hdr != NULL) {
+			uint16 src_port = ntoh16(tcp_hdr->src_port);
+			uint16 dst_port = ntoh16(tcp_hdr->dst_port);
+			uint32 seq_num = ntoh32(tcp_hdr->seq_num);
+			uint32 ack_num = ntoh32(tcp_hdr->ack_num);
+			uint8 tcp_flags[2];
+			uint16 tcp_data_len;
+			wl_tko_connect_t *connect;
+			uint8 index;
+			int len;
+
+			/* find existing TCP connection */
+			for (i = 0; i < cur_tcp; i++) {
+				int ip_addr_size = ip_addr_type ? sizeof(struct ipv6_addr) :
+					sizeof(struct ipv4_addr);
+
+				tko = (wl_tko_t *)tko_buf[i];
+				connect = (wl_tko_connect_t *)tko->data;
+
+				/* existing TCP connection if src/dst IP and ports match */
+				if (connect->ip_addr_type == ip_addr_type &&
+					memcmp(src_ip, &connect->data[0], ip_addr_size) == 0 &&
+					memcmp(dst_ip, &connect->data[ip_addr_size],
+						ip_addr_size) == 0 &&
+					connect->local_port == src_port &&
+					connect->remote_port == dst_port) {
+					/* found existing TCP connection */
+					index = connect->index;
+					break;
+				}
+			}
+			/* TCP connection not found */
+			if (i == cur_tcp) {
+				if (cur_tcp < max_tcp) {
+					/* new TCP connection */
+					index = cur_tcp;
+					cur_tcp++;
+				} else {
+					/* no more */
+					printf("max TCP connections supported %d\n", max_tcp);
+					continue;
+				}
+			}
+
+			/* TCP data length */
+			memcpy(tcp_flags, &tcp_hdr->hdrlen_rsvd_flags, sizeof(tcp_flags));
+			tcp_data_len = tcp_len - (TCP_HDRLEN(tcp_flags[0]) << 2);
+			if (tcp_data_len != 0) {
+				printf("TCP data len=%d\n", tcp_data_len);
+			}
+
+			/* adjust the sequence num with the TCP data length */
+			seq_num += tcp_data_len;
+
+			printf("index:        %d\n", index);
+			if (ip_addr_type) {
+				/* IPv6 */
+				printf("src IPv6:     %s\n",
+					wl_ipv6toa((struct ipv6_addr *)src_ip));
+				printf("dst IPv6:     %s\n",
+					wl_ipv6toa((struct ipv6_addr *)dst_ip));
+			} else {
+				/* IPv4 */
+				printf("src IP:       %s\n",
+					wl_iptoa((struct ipv4_addr *)src_ip));
+				printf("dst IP:       %s\n",
+					wl_iptoa((struct ipv4_addr *)dst_ip));
+			}
+			printf("local port:   %u\n", src_port);
+			printf("remote port:  %u\n", dst_port);
+			printf("local seq:    %u\n", seq_num);
+			printf("remote seq:   %u\n", ack_num);
+
+			tko = (wl_tko_t *)tko_buf[index];
+			connect = (wl_tko_connect_t *)tko->data;
+
+			tko->len = wl_tko_connect_init(connect, index, ip_addr_type,
+				(struct ether_addr *)&frame[ETHER_SRC_OFFSET],
+				(struct ether_addr *)&frame[ETHER_DEST_OFFSET],
+				src_ip, dst_ip, src_port, dst_port, seq_num,
+				ack_num, TKO_TCP_WINDOW_SIZE);
+
+			/* invoke SET iovar */
+			tko->subcmd_id = WL_TKO_SUBCMD_CONNECT;
+			len = OFFSETOF(wl_tko_t, data) + tko->len;
+			tko->subcmd_id = htod16(tko->subcmd_id);
+			tko->len = htod16(tko->len);
+			err = wlu_iovar_set(wl, "tko", tko, len);
+			if (err < 0) {
+				printf("TKO connect failed\n");
+				break;
+			}
+		}
+	}
+
+exit:
+	if (tko_buf != NULL) {
+		for (i = 0; i < max_tcp; i++) {
+			if (tko_buf[i] != NULL) {
+				free(tko_buf[i]);
+			}
+		}
+		free(tko_buf);
+	}
+	if (frame != NULL) {
+		free(frame);
+	}
+	if (fd >= 0) {
+		close(fd);
+	}
+	return err;
+}
+
+static void
+wl_tko_event_cb(int event_type, bcm_event_t *bcm_event)
+{
+	wl_event_tko_t *data = (wl_event_tko_t *) (bcm_event + 1);
+
+	if (event_type == WLC_E_TKO) {
+		printf("WLC_E_TKO(%d): status=%d index=%d\n",
+			WLC_E_TKO, ntoh32(bcm_event->event.status), data->index);
+	}
+}
+
+static int
+wl_tko_event_check(void *wl, cmd_t *cmd, char **argv)
+{
+	if (argv[1] && argv[1][0] == '-') {
+		wl_cmd_usage(stderr, cmd);
+		return -1;
+	}
+	return wl_wait_for_event(wl, argv, WLC_E_TKO, 256, wl_tko_event_cb);
+}
+
+#endif	/* linux */
diff --git a/wl/src/wl/exe/wluc_toe.c b/wl/src/wl/exe/wluc_toe.c
new file mode 100644
index 0000000..ffa3f11
--- /dev/null
+++ b/wl/src/wl/exe/wluc_toe.c
@@ -0,0 +1,106 @@
+/*
+ * wl toe command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_toe.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_toe_stats;
+
+static cmd_t wl_toe_cmds[] = {
+	{ "toe_ol", wl_offload_cmpnt, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set tcpip offload components"},
+	{ "toe_stats", wl_toe_stats, WLC_GET_VAR, -1,
+	"Display checksum offload statistics"},
+	{ "toe_stats_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear checksum offload statistics"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_toe_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register toe commands */
+	wl_module_cmds_register(wl_toe_cmds);
+}
+
+static int
+wl_toe_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	struct toe_ol_stats_t *toestats;
+
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+		toestats = (struct toe_ol_stats_t *)ptr;
+		printf("tx_summed = %d\n", dtoh32(toestats->tx_summed));
+		printf("tx_iph_fill = %d\n", dtoh32(toestats->tx_iph_fill));
+		printf("tx_tcp_fill = %d\n", dtoh32(toestats->tx_tcp_fill));
+		printf("tx_udp_fill = %d\n", dtoh32(toestats->tx_udp_fill));
+		printf("tx_icmp_fill = %d\n", dtoh32(toestats->tx_icmp_fill));
+		printf("rx_iph_good = %d\n", dtoh32(toestats->rx_iph_good));
+		printf("rx_iph_bad = %d\n", dtoh32(toestats->rx_iph_bad));
+		printf("rx_tcp_good = %d\n", dtoh32(toestats->rx_tcp_good));
+		printf("rx_tcp_bad = %d\n", dtoh32(toestats->rx_tcp_bad));
+		printf("rx_udp_good = %d\n", dtoh32(toestats->rx_udp_good));
+		printf("rx_udp_bad = %d\n", dtoh32(toestats->rx_udp_bad));
+		printf("rx_icmp_good = %d\n", dtoh32(toestats->rx_icmp_good));
+		printf("rx_icmp_bad = %d\n", dtoh32(toestats->rx_icmp_bad));
+		printf("tx_tcp_errinj = %d\n", dtoh32(toestats->tx_tcp_errinj));
+		printf("tx_udp_errinj = %d\n", dtoh32(toestats->tx_udp_errinj));
+		printf("tx_icmp_errinj = %d\n", dtoh32(toestats->tx_icmp_errinj));
+		printf("rx_tcp_errinj = %d\n", dtoh32(toestats->rx_tcp_errinj));
+		printf("rx_udp_errinj = %d\n", dtoh32(toestats->rx_udp_errinj));
+		printf("rx_icmp_errinj = %d\n", dtoh32(toestats->rx_icmp_errinj));
+	} else
+		printf("Cannot set toe stats, use 'wl toe_stats_clear' to clear the counters\n");
+
+	return 0;
+}
diff --git a/wl/src/wl/exe/wluc_tpc.c b/wl/src/wl/exe/wluc_tpc.c
new file mode 100644
index 0000000..70db77b
--- /dev/null
+++ b/wl/src/wl/exe/wluc_tpc.c
@@ -0,0 +1,93 @@
+/*
+ * wl tpc command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_tpc.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_tpc_lm;
+
+static cmd_t wl_tpc_cmds[] = {
+	{ "tpc_mode", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/disable AP TPC.\n"
+	"Usage: wl tpc_mode <mode> \n"
+	"\t0 - disable, 1 - BSS power control, 2 - AP power control, 3 - Both (1) and (2)"},
+	{ "tpc_period", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set AP TPC periodicity in secs.\n"
+	"Usage: wl tpc_period <secs> "},
+	{ "tpc_lm", wl_tpc_lm, WLC_GET_VAR, -1,
+	"Get current link margins."},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_tpc_module_init(void)
+{
+	(void)g_swap;
+
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register tpc commands */
+	wl_module_cmds_register(wl_tpc_cmds);
+}
+
+static int
+wl_tpc_lm(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	uint16 val;
+	int8 aplm, stalm;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_iovar_getint(wl, cmd->name, (int *)(uintptr)&val)) < 0)
+		return ret;
+
+	stalm = val & 0xff;
+	aplm = (val >> 8) & 0xff;
+
+	printf("TPC: APs link margin:%d\t STAs link margin:%d\n", aplm, stalm);
+
+	return 0;
+}
diff --git a/wl/src/wl/exe/wluc_traffic_mgmt.c b/wl/src/wl/exe/wluc_traffic_mgmt.c
new file mode 100644
index 0000000..af0c78d
--- /dev/null
+++ b/wl/src/wl/exe/wluc_traffic_mgmt.c
@@ -0,0 +1,1011 @@
+/*
+ * wl traffic_mgmt command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_traffic_mgmt.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_trf_mgmt_config;
+static cmd_func_t wl_trf_mgmt_filters_add;
+static cmd_func_t wl_trf_mgmt_filters_addex;
+static cmd_func_t wl_trf_mgmt_filters_remove;
+static cmd_func_t wl_trf_mgmt_filters_removeex;
+static cmd_func_t wl_trf_mgmt_filters_list;
+static cmd_func_t wl_trf_mgmt_filters_clear;
+static cmd_func_t wl_trf_mgmt_bandwidth;
+static cmd_func_t wl_trf_mgmt_flags;
+static cmd_func_t wl_trf_mgmt_stats;
+static cmd_func_t wl_trf_mgmt_stats_clear;
+static cmd_func_t wl_trf_mgmt_shaping_info;
+
+static cmd_t wl_trf_mgmt_cmds[] = {
+	{"trf_mgmt_config", wl_trf_mgmt_config, WLC_GET_VAR, WLC_SET_VAR,
+	"Sets/gets traffic management configuration.\n"
+	"\tUsage: wl trf_mgmt_config [<enable> \n"
+	"\t                          [<host IP address> <host IP subnet mask> \n"
+	"\t                           <downlink kbps> <uplink kbps> [<flags>]]] \n"
+	"\tenable: 0 - Disable traffic management\n"
+	"\t        1 - Enables traffic management (host IP arguments required)\n"
+	"\tFlag values are the following:\n"
+	"\t0x0001 : Add DSCP values to tx packets\n"
+	"\t0x0002 : Disable traffic shaping...just do priority classification\n"
+	"\nIf no arguments are entered, the current traffic management configuration \n"
+	"is displayed.\n"
+	"\ne.g. Configure traffic management and specify local ip addr. and bandwidth data:\n"
+	"\nwl trf_mgmt_config 1 12.0.0.1 255.0.0.0 5000 650"},
+
+	{"trf_mgmt_filters_add", wl_trf_mgmt_filters_add, -1, WLC_SET_VAR,
+	"Adds a traffic management filter.\n"
+	"\tUsage: wl trf_mgmt_filter_add [dst_port src_port prot priority]\n"
+	"\tdst_port    : Destination TCP or UDP port \n"
+	"\tsrc_port    : Source TCP or UDP port (0 - wildcard for any source port)\n"
+	"\tprot        : L4 protocol (6 - TCP, 17 - UDP)\n"
+	"\tpriority    : Priority value (see trf_mgmt_priority_values enum) \n"
+	"\ne.g. Add a tcp wildcard filter:\n"
+	"\nwl trf_mgmt_filters_add 80 0 6 2"},
+
+	{"trf_mgmt_filters_addex", wl_trf_mgmt_filters_addex, -1, WLC_SET_VAR,
+	"Adds a traffic management filter.\n"
+	"\tUsage: wl trf_mgmt_filter_add flag [dst_port src_port prot priority]\n"
+	"\tUsage: wl trf_mgmt_filter_add flag [dst_mac priority] \n"
+	"\tFlag values are the following:\n"
+	"\t0x0000 : filter on tcp/udp src/dst port\n"
+	"\t0x0001 : filter on destination MAC address\n"
+	"\t0x0010 : do not update the packet priority \n"
+	"\t0x0020 : Tag packets as Favored\n"
+	"\tdst_mac    : Destination MAC address \n"
+	"\tdst_port    : Destination TCP or UDP port \n"
+	"\tsrc_port    : Source TCP or UDP port (0 - wildcard for any source port)\n"
+	"\tprot        : L4 protocol (6 - TCP, 17 - UDP)\n"
+	"\tpriority    : Priority value (see trf_mgmt_priority_values enum) \n"
+	"\ne.g. Add a tcp wildcard filter for all src/dst ports:\n"
+	"\nwl trf_mgmt_filters_addex 0 0 0 6 2\n"
+	"\ne.g. Add a dst mac address filter\n"
+	"\nwl trf_mgmt_filters_addex 0x31 aa:bb:cc:dd:ee:ff 2"},
+
+	{"trf_mgmt_filters_remove", wl_trf_mgmt_filters_remove, -1, WLC_SET_VAR,
+	"Removes a traffic management filter.\n"
+	"\tUsage: wl trf_mgmt_filter_remove [dst_port src_port prot]\n"
+	"\tdst_port    : Destination TCP or UDP port \n"
+	"\tsrc_port    : Source TCP or UDP port (0 - wildcard for any source port)\n"
+	"\tprot        : L4 protocol (6 - TCP, 17 - UDP)\n"
+	"\ne.g. Remove a tcp wildcard filter:\n"
+	"\nwl trf_mgmt_filters_remove 80 0 6"},
+
+	{"trf_mgmt_filters_removeex", wl_trf_mgmt_filters_removeex, -1, WLC_SET_VAR,
+	"Removes a traffic management filter.\n"
+	"\tUsage: wl trf_mgmt_filter_remove flag [dst_port src_port prot]\n"
+	"\tUsage: wl trf_mgmt_filter_remove flag [dst_mac]\n"
+	"\tFlag values are the following:\n"
+	"\t0x0000 : filter on tcp/udp src/dst port\n"
+	"\t0x0001 : filter on destination MAC address\n"
+	"\t0x0010 : do not update the packet priority \n"
+	"\t0x0020 : Tag packets as Favored\n"
+	"\tdst_mac    : Destination MAC address \n"
+	"\tdst_port    : Destination TCP or UDP port \n"
+	"\tsrc_port    : Source TCP or UDP port (0 - wildcard for any source port)\n"
+	"\tprot        : L4 protocol (6 - TCP, 17 - UDP)\n"
+	"\ne.g. Remove a tcp wildcard filter:\n"
+	"\nwl trf_mgmt_filters_removeex 0 80 0 6\n"
+	"\nwl trf_mgmt_filters_removeex 0x31 00:90:4c:52:a8:83"},
+
+	{"trf_mgmt_filters_list", wl_trf_mgmt_filters_list, WLC_GET_VAR, -1,
+	"Lists all traffic management filters.\n"
+	"\tUsage: wl trf_mgmt_filter_list"},
+
+	{"trf_mgmt_filters_clear", wl_trf_mgmt_filters_clear, -1, WLC_SET_VAR,
+	"Clears all traffic management filters.\n"
+	"\tUsage: wl trf_mgmt_filters_clear"},
+
+	{"trf_mgmt_bandwidth", wl_trf_mgmt_bandwidth, WLC_GET_VAR, WLC_SET_VAR,
+	"Sets/gets traffic management bandwidth configuration.\n"
+	"\tUsage: wl trf_mgmt_bandwidth \n"
+	"\t          [downlink uplink min_tx_bk min_tx_be min_tx_vi\n"
+	"\t                          [min_rx_b min_rx_be min_rx_vi]]\n"
+	"\tdownlink   : downlink bandwidth (kbps)\n"
+	"\tuplink     : uplink bandwidth (kbps)\n"
+	"\tmin_tx_bk  : min. guaranteed tx bandwidth percentage for BK (kbps)\n"
+	"\tmin_tx_be  : min. guaranteed tx bandwidth percentage for BE (kbps)\n"
+	"\tmin_tx_vi  : min. guaranteed tx bandwidth percentage for VI (kbps)\n"
+	"\n(min_tx_bo + min_tx_be + min_tx_vi) must equal 100.\n"
+	"\tmin_rx_bk  : min. guaranteed rx bandwidth percentage for BK (kbps)\n"
+	"\tmin_rx_be  : min. guaranteed rx bandwidth percentage for BE (kbps)\n"
+	"\tmin_rx_vi  : min. guaranteed rx bandwidth percentage for VI (kbps)\n"
+	"\n(min_rx_bk + min_rx_be + min_rx_vi) must equal 100."
+	"\nIf no rx gandwidth arguments are entered, tx bandwidth is used for rx."
+	"\nIf no arguments are entered, the current bandwidth configuration is displayed."},
+
+	{"trf_mgmt_flags", wl_trf_mgmt_flags, WLC_GET_VAR, WLC_SET_VAR,
+	"Sets/gets traffic management operational flags.\n"
+	"\tUsage: wl trf_mgmt_flags [flags]\n\n"
+	"\tFlag values are the following:\n"
+	"\t0x0001 : Add DSCP values to tx packets\n"
+	"\t0x0002 : Disable traffic shaping...just do priority classification\n"
+	"\nIf no arguments are entered, the current operational flags are displayed."},
+
+	{"trf_mgmt_stats", wl_trf_mgmt_stats, WLC_GET_VAR, -1,
+	"Gets traffic management statistics.\n"
+	"\tUsage: wl trf_mgmt_stats [index]\n"
+	"\tindex : Queue index"},
+
+	{"trf_mgmt_stats_clear", wl_trf_mgmt_stats_clear, -1, WLC_SET_VAR,
+	"Clears traffic management statistics.\n"
+	"\tUsage: wl trf_mgmt_stats_clear"},
+
+	{"trf_mgmt_shaping_info", wl_trf_mgmt_shaping_info, WLC_GET_VAR, -1,
+	"Gets traffic management shaping parameters.\n"
+	"\tUsage: wl trf_mgmt_shaping_info [index]\n"
+	"\tindex : Queue index"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_trf_mgmt_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register trf_mgmt commands */
+	wl_module_cmds_register(wl_trf_mgmt_cmds);
+}
+
+/* Get/set traffic management configuration. */
+static int
+wl_trf_mgmt_config(void *wl, cmd_t *cmd, char **argv)
+{
+	uint		    argc = 0;
+	uint32		    i;
+	trf_mgmt_config_t   *ptrf_mgmt_config;
+	uint8		    buf[sizeof(trf_mgmt_config_t)];
+	int		    buf_len;
+	char		    *endptr = NULL;
+	int		    rc = -1;
+	void		    *ptr = NULL;
+
+	if (!*++argv) {
+	   /*
+	    * Get current traffic management configuration.
+	    */
+	    if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return rc;
+
+	    ptrf_mgmt_config = (trf_mgmt_config_t *)ptr;
+
+	    printf("Enabled                   : %d\n",
+	        dtoh32(ptrf_mgmt_config->trf_mgmt_enabled));
+	    printf("Host IP Address           : %s\n",
+	        wl_iptoa((void *)&ptrf_mgmt_config->host_ip_addr));
+	    printf("Host IP Subnet Mask       : %s\n",
+	        wl_iptoa((void *)&ptrf_mgmt_config->host_subnet_mask));
+	    printf("Downlink Bandwidth        : %d\n",
+	        dtoh32(ptrf_mgmt_config->downlink_bandwidth));
+	    printf("Uplink Bandwidth          : %d\n",
+	        dtoh32(ptrf_mgmt_config->uplink_bandwidth));
+	    printf("\n");
+
+	    printf("Minimum Tx Bandwidth[BK]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[0]));
+	    printf("Minimum Tx Bandwidth[BE]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[1]));
+	    printf("Minimum Tx Bandwidth[VI]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[2]));
+	    printf("\n");
+
+	    printf("Minimum Rx Bandwidth[BK]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_rx_bandwidth[0]));
+	    printf("Minimum Rx Bandwidth[BE]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_rx_bandwidth[1]));
+	    printf("Minimum Rx Bandwidth[VI]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_rx_bandwidth[2]));
+	    printf("\n");
+
+	    printf("Flags                     : 0x%04X\n",
+	        dtoh32(ptrf_mgmt_config->flags));
+	}
+	else {
+	    /* arg count */
+	    while (argv[argc])
+		argc++;
+
+	    /* required	arguments */
+	    if ((argc != 1) && (argc != 5) && (argc != 6)) {
+		fprintf(stderr,	"Too few/many arguments	(require 1 or 5 or 6 , got %d)\n", argc);
+		return BCME_USAGE_ERROR;
+	    }
+
+	    ptrf_mgmt_config = (trf_mgmt_config_t *)buf;
+	    buf_len	     = sizeof(trf_mgmt_config_t);
+	    memset((uint8 *)buf, 0, buf_len);
+
+	    ptrf_mgmt_config->trf_mgmt_enabled = htod32((int32)strtol(*argv++, &endptr,	0));
+	    if (*endptr	!= '\0') {
+		return BCME_USAGE_ERROR;
+	    }
+
+	    if (argc > 1) {
+		if (ptrf_mgmt_config->trf_mgmt_enabled)	{
+		    if (!wl_atoip(*argv++, (void *)&ptrf_mgmt_config->host_ip_addr)) {
+			return BCME_USAGE_ERROR;
+		    }
+		    if (!wl_atoip(*argv++, (void *)&ptrf_mgmt_config->host_subnet_mask)) {
+			return BCME_USAGE_ERROR;
+		    }
+		    ptrf_mgmt_config->downlink_bandwidth =
+		        htod32((int32)strtol(*argv++, &endptr, 0));
+		    ptrf_mgmt_config->uplink_bandwidth =
+		        htod32((int32)strtol(*argv++, &endptr, 0));
+
+		    /*
+		     * Zero-fill min bandwidth based. This will	cause the driver to use
+		     * defult settings
+		     */
+		    for	(i = 0;	i < TRF_MGMT_MAX_PRIORITIES; i++) {
+			ptrf_mgmt_config->min_tx_bandwidth[i] =	0;
+			ptrf_mgmt_config->min_rx_bandwidth[i] =	0;
+		    }
+
+		    if (argc ==	6) {
+			ptrf_mgmt_config->flags	= htod32((int32)strtol(*argv++,	&endptr, 0));
+		    }
+		} else {
+		    return BCME_BADARG;
+		}
+	    }
+
+	    rc = wlu_var_setbuf(wl, cmd->name, ptrf_mgmt_config, buf_len);
+	}
+	return rc;
+}
+
+/* Sets a traffic management filter. */
+static int
+wl_trf_mgmt_filters_add(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                    argc = 0;
+	trf_mgmt_filter_list_t  *ptrf_mgmt_filter_list;
+	trf_mgmt_filter_t       *ptrf_mgmt_filter;
+	uint8                   buf[sizeof(trf_mgmt_filter_list_t)];
+	int                     buf_len;
+	char                    *param;
+	char                    *endptr = NULL;
+	int                     rc = -1;
+
+	(void)param;
+	/* arg count */
+	param = *++argv;
+	while (argv[argc])
+	    argc++;
+
+	/* required arguments */
+	if (argc != 4) {
+	    fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 4, argc);
+	    return BCME_USAGE_ERROR;
+	}
+
+	ptrf_mgmt_filter_list = (trf_mgmt_filter_list_t *)buf;
+	buf_len               = sizeof(trf_mgmt_filter_list_t);
+	memset((uint8 *)buf, 0, buf_len);
+
+	ptrf_mgmt_filter_list->num_filters = 1;
+	ptrf_mgmt_filter                   = &ptrf_mgmt_filter_list->filter[0];
+
+	ptrf_mgmt_filter->dst_port = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+
+	ptrf_mgmt_filter->src_port = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+
+	ptrf_mgmt_filter->prot = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+
+	ptrf_mgmt_filter->priority = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+
+	rc = wlu_var_setbuf(wl, cmd->name, ptrf_mgmt_filter_list, buf_len);
+
+	return rc;
+}
+/* Sets a traffic management filter L2/L3/L4 */
+static int
+wl_trf_mgmt_filters_addex(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                    argc = 0;
+	trf_mgmt_filter_list_t  *ptrf_mgmt_filter_list;
+	trf_mgmt_filter_t       *ptrf_mgmt_filter;
+	uint8                   buf[sizeof(trf_mgmt_filter_list_t)];
+	int                     buf_len;
+	char                    *param;
+	char                    *endptr = NULL;
+	int                     rc = -1;
+
+	(void)param;
+	(void)cmd;
+	/* arg count */
+	param = *++argv;
+	while (argv[argc])
+	    argc++;
+
+	/* required arguments */
+	if (argc < 3) {
+		fprintf(stderr, "Too few arguments (require > 3  got %d)\n", argc);
+		return BCME_USAGE_ERROR;
+	}
+
+	ptrf_mgmt_filter_list = (trf_mgmt_filter_list_t *)buf;
+	buf_len               = sizeof(trf_mgmt_filter_list_t);
+	memset((uint8 *)buf, 0, buf_len);
+
+	ptrf_mgmt_filter_list->num_filters = 1;
+	ptrf_mgmt_filter                   = &ptrf_mgmt_filter_list->filter[0];
+
+	ptrf_mgmt_filter->flags = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+
+	if (ptrf_mgmt_filter->flags & TRF_FILTER_MAC_ADDR) {
+
+		if (argc != 3) {
+			fprintf(stderr, "Too many arguments (require 3 got %d)\n", argc);
+			return BCME_USAGE_ERROR;
+		}
+
+		if (!wl_ether_atoe(*argv++, &ptrf_mgmt_filter->dst_ether_addr))
+			return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->priority = htod16((int16)strtol(*argv++, &endptr, 0));
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+	} else {
+		/* required arguments */
+		if (argc != 5) {
+			fprintf(stderr, "Too few/many arguments (require 5 got %d)\n", argc);
+			return BCME_USAGE_ERROR;
+		}
+
+		ptrf_mgmt_filter->dst_port = htod16((int16)strtol(*argv++, &endptr, 0));
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->src_port = htod16((int16)strtol(*argv++, &endptr, 0));
+			if (*endptr != '\0')
+			    return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->prot = htod16((int16)strtol(*argv++, &endptr, 0));
+			if (*endptr != '\0')
+			    return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->priority = htod16((int16)strtol(*argv++, &endptr, 0));
+			if (*endptr != '\0')
+			    return BCME_USAGE_ERROR;
+	}
+
+	rc = wlu_var_setbuf(wl, "trf_mgmt_filters_add", ptrf_mgmt_filter_list, buf_len);
+
+	return rc;
+}
+
+/* Removes a traffic management filter. */
+static int
+wl_trf_mgmt_filters_remove(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                    argc = 0;
+	trf_mgmt_filter_list_t  *ptrf_mgmt_filter_list;
+	trf_mgmt_filter_t       *ptrf_mgmt_filter;
+	uint8                   buf[sizeof(trf_mgmt_filter_list_t)];
+	int                     buf_len;
+	char                    *endptr = NULL;
+	char                    *param;
+	int                     rc = -1;
+
+	(void)param;
+	/* arg count */
+	param = *++argv;
+	while (argv[argc])
+	    argc++;
+
+	/* required arguments */
+	if (argc != 3) {
+	    fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 3, argc);
+	    return BCME_USAGE_ERROR;
+	}
+
+	ptrf_mgmt_filter_list = (trf_mgmt_filter_list_t *)buf;
+	buf_len               = sizeof(trf_mgmt_filter_list_t);
+
+	memset((uint8 *)buf, 0, buf_len);
+
+	ptrf_mgmt_filter_list->num_filters = 1;
+	ptrf_mgmt_filter                   = &ptrf_mgmt_filter_list->filter[0];
+
+	ptrf_mgmt_filter->dst_port = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+	ptrf_mgmt_filter->src_port = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+	ptrf_mgmt_filter->prot = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0')
+	    return BCME_USAGE_ERROR;
+	rc = wlu_var_setbuf(wl, cmd->name, ptrf_mgmt_filter_list, buf_len);
+
+	return rc;
+}
+
+/* Removes a traffic management filter for L2/L3/L4 */
+static int
+wl_trf_mgmt_filters_removeex(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                    argc = 0;
+	trf_mgmt_filter_list_t  *ptrf_mgmt_filter_list;
+	trf_mgmt_filter_t       *ptrf_mgmt_filter;
+	uint8                   buf[sizeof(trf_mgmt_filter_list_t)];
+	int                     buf_len;
+	char                    *endptr = NULL;
+	char                    *param;
+	int                     rc = -1;
+
+	(void)param;
+	(void)cmd;
+	/* arg count */
+	param = *++argv;
+	while (argv[argc])
+	    argc++;
+
+	/* required arguments */
+	if (argc < 2) {
+	    fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 2, argc);
+	    return BCME_USAGE_ERROR;
+	}
+
+	ptrf_mgmt_filter_list = (trf_mgmt_filter_list_t *)buf;
+	buf_len               = sizeof(trf_mgmt_filter_list_t);
+
+	memset((uint8 *)buf, 0, buf_len);
+
+	ptrf_mgmt_filter_list->num_filters = 1;
+	ptrf_mgmt_filter                   = &ptrf_mgmt_filter_list->filter[0];
+
+	ptrf_mgmt_filter->flags = htod16((int16)strtol(*argv++, &endptr, 0));
+	if (*endptr != '\0') {
+		return BCME_USAGE_ERROR;
+	}
+	if (ptrf_mgmt_filter->flags & TRF_FILTER_MAC_ADDR) {
+
+		if (argc != 2) {
+			fprintf(stderr, "Too many arguments (require 2 got %d)\n", argc);
+			return BCME_USAGE_ERROR;
+		}
+
+		if (!wl_ether_atoe(*argv++, &ptrf_mgmt_filter->dst_ether_addr)) {
+			return BCME_USAGE_ERROR;
+		}
+
+	} else {
+		if (argc < 4) {
+			fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 4, argc);
+			return BCME_USAGE_ERROR;
+		}
+		ptrf_mgmt_filter->dst_port = htod16((int16)strtol(*argv++, &endptr, 0));
+		if (*endptr != '\0')
+		    return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->src_port = htod16((int16)strtol(*argv++, &endptr, 0));
+		if (*endptr != '\0')
+		    return BCME_USAGE_ERROR;
+
+		ptrf_mgmt_filter->prot = htod16((int16)strtol(*argv++, &endptr, 0));
+		if (*endptr != '\0')
+		    return BCME_USAGE_ERROR;
+	}
+
+	rc = wlu_var_setbuf(wl, "trf_mgmt_filters_remove", ptrf_mgmt_filter_list, buf_len);
+
+	return rc;
+}
+
+/* lists the current traffic management filters. */
+static int
+wl_trf_mgmt_filters_list(void *wl, cmd_t *cmd, char **argv)
+{
+	trf_mgmt_filter_list_t  *ptrf_mgmt_filter_list;
+	trf_mgmt_filter_t       *ptrf_mgmt_filter;
+	uint                    i;
+	int                     rc = -1;
+	void                    *ptr = NULL;
+
+	UNUSED_PARAMETER(argv);
+
+	/*
+	 * Get current traffic management filters.
+	 */
+	if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+	    return rc;
+
+	ptrf_mgmt_filter_list = (trf_mgmt_filter_list_t *)ptr;
+
+	printf("Number of filters : %d\n", dtoh32(ptrf_mgmt_filter_list->num_filters));
+
+	for (i = 0; i < ptrf_mgmt_filter_list->num_filters; i++) {
+	    ptrf_mgmt_filter = &ptrf_mgmt_filter_list->filter[i];
+
+		if (ptrf_mgmt_filter->flags & TRF_FILTER_MAC_ADDR) {
+			printf("\n");
+			printf("Filter #%d\n", i);
+			printf("Flags    : 0x%02x\n", dtoh32(ptrf_mgmt_filter->flags));
+			printf("Dst EtherAddr    : %s\n",
+				wl_ether_etoa(&ptrf_mgmt_filter->dst_ether_addr));
+			printf("Priority : %d\n", dtoh32(ptrf_mgmt_filter->priority));
+		} else {
+			printf("\n");
+			printf("Filter #%d\n", i);
+			printf("Dst Port : %d\n", dtoh32(ptrf_mgmt_filter->dst_port));
+			printf("Src Port : %d\n", dtoh32(ptrf_mgmt_filter->src_port));
+			printf("Protocol : %d\n", dtoh32(ptrf_mgmt_filter->prot));
+			printf("Flags    : 0x%02x\n", dtoh32(ptrf_mgmt_filter->flags));
+			printf("Priority : %d\n", dtoh32(ptrf_mgmt_filter->priority));
+		}
+	}
+
+	return rc;
+}
+
+/* Clears the traffic management filters. */
+static int
+wl_trf_mgmt_filters_clear(void *wl, cmd_t *cmd, char **argv)
+{
+	int rc = -1;
+
+	UNUSED_PARAMETER(argv);
+
+	rc = wlu_var_setbuf(wl, cmd->name, NULL, 0);
+
+	return rc;
+}
+
+/*
+ * Get/set traffic management bandwidth configuration. We support the ability to get/set just the
+ * bandwidth parameters in the global trf_mgmt_config_t structure.
+ */
+static int
+wl_trf_mgmt_bandwidth(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                argc = 0;
+	trf_mgmt_config_t   *ptrf_mgmt_config;
+	uint8               buf[sizeof(trf_mgmt_config_t)];
+	int                 buf_len;
+	char                *endptr = NULL;
+	int                 i, total_bandwidth;
+	int                 rc = -1;
+	void                *ptr = NULL;
+
+	if (!*++argv) {
+	   /*
+	    * Get current traffic management bandwidth settings.
+	    */
+	    if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return rc;
+
+	    ptrf_mgmt_config = (trf_mgmt_config_t *)ptr;
+
+	    printf("Downlink Bandwidth        : %d\n",
+	        dtoh32(ptrf_mgmt_config->downlink_bandwidth));
+	    printf("Uplink Bandwidth          : %d\n",
+	        dtoh32(ptrf_mgmt_config->uplink_bandwidth));
+	    printf("\n");
+
+	    printf("Minimum Tx Bandwidth[BK]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[0]));
+	    printf("Minimum Tx Bandwidth[BE]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[1]));
+	    printf("Minimum Tx Bandwidth[VI]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[2]));
+	    printf("\n");
+
+	    printf("Minimum Rx Bandwidth[BK]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[0]));
+	    printf("Minimum Rx Bandwidth[BE]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[1]));
+	    printf("Minimum Rx Bandwidth[VI]  : %d\n",
+	        dtoh32(ptrf_mgmt_config->min_tx_bandwidth[2]));
+	}
+	else {
+	    /* arg count */
+	    while (argv[argc])
+		argc++;
+
+	    /* required arguments */
+	    if (argc < 5) {
+		fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 5, argc);
+		return BCME_USAGE_ERROR;
+	    }
+
+	    if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return rc;
+
+	    ptrf_mgmt_config = (trf_mgmt_config_t *)buf;
+	    buf_len          = sizeof(trf_mgmt_config_t);
+
+	    memcpy(buf, ptr, buf_len);
+
+	    ptrf_mgmt_config->downlink_bandwidth = htod32((int32)strtol(*argv++, &endptr, 0));
+	    if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	    ptrf_mgmt_config->uplink_bandwidth = htod32((int32)strtol(*argv++, &endptr, 0));
+	    if (*endptr != '\0')
+		return BCME_USAGE_ERROR;
+	    for (i = 0, total_bandwidth = 0; i < TRF_MGMT_MAX_PRIORITIES; i++) {
+		ptrf_mgmt_config->min_tx_bandwidth[i] =
+		    htod32((int32)strtol(*argv++, &endptr, 0));
+
+		if (*endptr != '\0')
+		   return BCME_USAGE_ERROR;
+		total_bandwidth += ptrf_mgmt_config->min_tx_bandwidth[i];
+	    }
+
+	    if (total_bandwidth != 100) {
+		fprintf(stderr,
+		    "Sum of gauranteed bandwidth levels must equal 100 (got %d)\n",
+		    total_bandwidth);
+		return BCME_BADARG;
+	    }
+
+	    if (argc > 5) {
+		for (i = 0, total_bandwidth = 0; i < TRF_MGMT_MAX_PRIORITIES; i++) {
+		    ptrf_mgmt_config->min_rx_bandwidth[i] =
+		        htod32((int32)strtol(*argv++, &endptr, 0));
+
+		    if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+		    total_bandwidth += ptrf_mgmt_config->min_rx_bandwidth[i];
+		}
+
+		if (total_bandwidth != 100) {
+		    fprintf(stderr,
+		        "Sum of gauranteed rx bandwidth levels must equal 100 (got %d)\n",
+		        total_bandwidth);
+		    return BCME_BADARG;
+		}
+	    } else {
+		for (i = 0, total_bandwidth = 0; i < TRF_MGMT_MAX_PRIORITIES; i++) {
+		    ptrf_mgmt_config->min_rx_bandwidth[i] = ptrf_mgmt_config->min_tx_bandwidth[i];
+		}
+	    }
+
+	    rc = wlu_var_setbuf(wl, cmd->name, ptrf_mgmt_config, buf_len);
+	}
+
+	return rc;
+}
+
+/*
+ * Get/set traffic management operational flags. We use this to change flags that
+ * can't be set by GUI. This allows us to configure certain options that we may want to
+ * enable/disable in the shipping product.
+ */
+static int
+wl_trf_mgmt_flags(void *wl, cmd_t *cmd, char **argv)
+{
+	uint                argc = 0;
+	uint32              flags;
+	char                *endptr = NULL;
+	int                 rc = -1;
+	void                *ptr = NULL;
+
+	if (!*++argv) {
+	   /*
+	    * Get current traffic management bandwidth settings.
+	    */
+	    if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+		return rc;
+
+	    flags = *(uint32 *)ptr;
+
+	    printf("Flags : 0x%04X\n", flags);
+	}
+	else {
+	    /* arg count */
+	    while (argv[argc])
+		argc++;
+
+	    /* required arguments */
+	    if (argc != 1) {
+		fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 1, argc);
+		return BCME_USAGE_ERROR;
+	    }
+
+	    flags = htod32((int32)strtol(*argv++, &endptr, 0));
+	    if (*endptr != '\0') {
+		return BCME_USAGE_ERROR;
+	    }
+	    rc = wlu_var_setbuf(wl, cmd->name, &flags, sizeof(uint32));
+	}
+
+	return rc;
+}
+
+/* Print traffic management statistics. */
+static void
+wl_trf_mgmt_print_stats(void *ptr, uint index)
+{
+	trf_mgmt_stats_array_t  *ptrf_mgmt_statistics_array;
+	trf_mgmt_stats_t        *ptrf_mgmt_statistics;
+
+	ptrf_mgmt_statistics_array = (trf_mgmt_stats_array_t *)ptr;
+
+	ptrf_mgmt_statistics = &ptrf_mgmt_statistics_array->tx_queue_stats[index];
+
+	printf("Statistics for Tx Queue[%d]\n", index);
+	printf("\n");
+	printf("Num. packets processed : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_processed_packets));
+	printf("Num. bytes processed   : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_processed_bytes));
+	printf("Num. packets discarded : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_discarded_packets));
+
+	ptrf_mgmt_statistics = &ptrf_mgmt_statistics_array->rx_queue_stats[index];
+
+	printf("\n");
+	printf("Statistics for Rx Queue[%d]\n", index);
+	printf("\n");
+	printf("Num. packets processed : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_processed_packets));
+	printf("Num. bytes processed   : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_processed_bytes));
+	printf("Num. packets discarded : %d\n",
+	       dtoh32(ptrf_mgmt_statistics->num_discarded_packets));
+
+	printf("\n");
+}
+
+/* Get traffic management statistics. */
+static int
+wl_trf_mgmt_stats(void *wl, cmd_t *cmd, char **argv)
+{
+	uint    argc = 0;
+	uint    i;
+	int     rc = -1;
+	char    *endptr = NULL;
+	void    *ptr = NULL;
+
+	/*
+	 * Get current traffic management statistics.
+	 */
+	if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+	    return rc;
+
+	if (!*++argv) {
+	    /*
+	     * Print all of the current traffic management statistics.
+	     */
+	    for (i = 0; i < TRF_MGMT_MAX_PRIORITIES; i++) {
+		wl_trf_mgmt_print_stats(ptr, i);
+	    }
+	}
+	else {
+	    /* arg count */
+	    while (argv[argc])
+		argc++;
+
+	    /* required arguments */
+	    if (argc != 1) {
+		fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 1, argc);
+		return BCME_USAGE_ERROR;
+	    }
+
+	    i = htod16((int16)strtol(*argv, &endptr, 0));
+	    if (i >= TRF_MGMT_MAX_PRIORITIES) {
+		fprintf(stderr, "Index must be < %d)\n", TRF_MGMT_MAX_PRIORITIES);
+		return BCME_BADARG;
+	    }
+
+	    /* Print the current traffic management statistics for the specified queue index. */
+	    wl_trf_mgmt_print_stats(ptr, i);
+	}
+
+
+	return rc;
+}
+
+/* Clears the traffic management statistics. */
+static int
+wl_trf_mgmt_stats_clear(void *wl, cmd_t *cmd, char **argv)
+{
+	int rc = -1;
+
+	UNUSED_PARAMETER(argv);
+
+	rc = wlu_var_setbuf(wl, cmd->name, NULL, 0);
+
+	return rc;
+}
+
+/* Print traffic management shaping info. */
+static void
+wl_trf_mgmt_print_global_shaping_info(void *ptr)
+{
+	trf_mgmt_shaping_info_array_t   *ptrf_mgmt_shaping_info_array;
+	trf_mgmt_global_info_t          *ptrf_mgmt_global_info;
+
+	ptrf_mgmt_shaping_info_array = (trf_mgmt_shaping_info_array_t *)ptr;
+
+	ptrf_mgmt_global_info = &ptrf_mgmt_shaping_info_array->tx_global_shaping_info;
+
+	printf("Global shaping info. for Tx Queues\n");
+	printf("\n");
+	printf("Maximum bytes/second                      : %d\n",
+	    ptrf_mgmt_global_info->maximum_bytes_per_second);
+	printf("Maximum bytes/sampling period             : %d\n",
+	    ptrf_mgmt_global_info->maximum_bytes_per_sampling_period);
+	printf("Total bytes consumed per second           : %d\n",
+	    ptrf_mgmt_global_info->total_bytes_consumed_per_second);
+	printf("Total bytes consumed per sampling period  : %d\n",
+	    ptrf_mgmt_global_info->total_bytes_consumed_per_sampling_period);
+	printf("Unused bytes for current sampling period  : %d\n",
+	    ptrf_mgmt_global_info->total_unused_bytes_per_sampling_period);
+
+	printf("\n");
+
+	ptrf_mgmt_global_info = &ptrf_mgmt_shaping_info_array->rx_global_shaping_info;
+
+	printf("Global shaping info. for Rx Queues\n");
+	printf("\n");
+	printf("Maximum bytes/second                      : %d\n",
+	    ptrf_mgmt_global_info->maximum_bytes_per_second);
+	printf("Maximum bytes/sampling period             : %d\n",
+	    ptrf_mgmt_global_info->maximum_bytes_per_sampling_period);
+	printf("Total bytes consumed per second           : %d\n",
+	    ptrf_mgmt_global_info->total_bytes_consumed_per_second);
+	printf("Total bytes consumed per sampling period  : %d\n",
+	    ptrf_mgmt_global_info->total_bytes_consumed_per_sampling_period);
+	printf("Unused bytes for current sampling period  : %d\n",
+	    ptrf_mgmt_global_info->total_unused_bytes_per_sampling_period);
+
+	printf("\n");
+}
+
+static void
+wl_trf_mgmt_print_shaping_info(void *ptr, uint index)
+{
+	trf_mgmt_shaping_info_array_t   *ptrf_mgmt_shaping_info_array;
+	trf_mgmt_shaping_info_t         *ptrf_mgmt_shaping_info;
+
+	ptrf_mgmt_shaping_info_array = (trf_mgmt_shaping_info_array_t *)ptr;
+
+	ptrf_mgmt_shaping_info = &ptrf_mgmt_shaping_info_array->tx_queue_shaping_info[index];
+
+	printf("Shaping info. for Tx Queue[%d]\n", index);
+	printf("\n");
+	printf("Gauranteed bandwidth percentage  : %d%%\n",
+	    dtoh32(ptrf_mgmt_shaping_info->gauranteed_bandwidth_percentage));
+	printf("Guaranteed bytes/second          : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->guaranteed_bytes_per_second));
+	printf("Guaranteed bytes/sampling period : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->guaranteed_bytes_per_sampling_period));
+	printf("Num. bytes produced per second   : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_bytes_produced_per_second));
+	printf("Num. bytes consumed per second   : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_bytes_consumed_per_second));
+	printf("Num. packets pending             : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_queued_packets));
+	printf("Num. bytes pending               : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_queued_bytes));
+
+	ptrf_mgmt_shaping_info = &ptrf_mgmt_shaping_info_array->rx_queue_shaping_info[index];
+
+	printf("\n");
+	printf("Shaping info. for Rx Queue[%d]\n", index);
+	printf("\n");
+	printf("Gauranteed bandwidth percentage  : %d%%\n",
+	    dtoh32(ptrf_mgmt_shaping_info->gauranteed_bandwidth_percentage));
+	printf("Guaranteed bytes/second          : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->guaranteed_bytes_per_second));
+	printf("Guaranteed bytes/sampling period : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->guaranteed_bytes_per_sampling_period));
+	printf("Num. bytes produced per second   : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_bytes_produced_per_second));
+	printf("Num. bytes consumed per second   : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_bytes_consumed_per_second));
+	printf("Num. packets pending             : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_queued_packets));
+	printf("Num. bytes pending               : %d\n",
+	    dtoh32(ptrf_mgmt_shaping_info->num_queued_bytes));
+
+	printf("\n");
+}
+
+/* Get traffic management shaping info. */
+static int
+wl_trf_mgmt_shaping_info(void *wl, cmd_t *cmd, char **argv)
+{
+	uint    argc = 0;
+	uint    i;
+	int     rc = -1;
+	char    *endptr = NULL;
+	void    *ptr = NULL;
+
+	/*
+	 * Get current traffic management shaping info.
+	 */
+	if ((rc = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+	    return rc;
+
+	if (!*++argv) {
+	    /*
+	     * Print all of the current traffic management shaping info.
+	     */
+	    wl_trf_mgmt_print_global_shaping_info(ptr);
+
+	    for (i = 0; i < TRF_MGMT_MAX_PRIORITIES; i++) {
+		wl_trf_mgmt_print_shaping_info(ptr, i);
+	    }
+	}
+	else {
+	    /* arg count */
+	    while (argv[argc])
+		argc++;
+
+	    /* required arguments */
+	    if (argc != 1) {
+		fprintf(stderr, "Too few/many arguments (require %d, got %d)\n", 1, argc);
+		return BCME_USAGE_ERROR;
+	    }
+
+	    i = htod16((int16)strtol(*argv, &endptr, 0));
+	    if (i >= TRF_MGMT_MAX_PRIORITIES) {
+		fprintf(stderr, "Index must be < %d)\n", TRF_MGMT_MAX_PRIORITIES);
+		return BCME_BADARG;
+	    }
+
+	    /* Print the current traffic management shaping info for the specified queue index. */
+	    wl_trf_mgmt_print_global_shaping_info(ptr);
+	    wl_trf_mgmt_print_shaping_info(ptr, i);
+	}
+
+
+	return rc;
+}
diff --git a/wl/src/wl/exe/wluc_wds.c b/wl/src/wl/exe/wluc_wds.c
new file mode 100644
index 0000000..2fdc4b8
--- /dev/null
+++ b/wl/src/wl/exe/wluc_wds.c
@@ -0,0 +1,206 @@
+/*
+ * wl wds command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_wds.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_wds_wpa_role_old, wl_wds_wpa_role;
+#if defined(DWDS)
+static cmd_func_t wl_dwds_config;
+#endif
+
+#define WDS_TYPE_USAGE	\
+"\tUsage: wl wds_type -i <ifname>\n" \
+"\tifname is the name of the interface to query the type.\n" \
+"\tReturn values:\n" \
+"\t\t0:The interface type is neither WDS nor DWDS.\n" \
+"\t\t1:The interface is WDS type.\n" \
+"\t\t2:The interface is DWDS type.\n"
+
+static cmd_t wl_wds_cmds[] = {
+	{ "wds", wl_maclist, WLC_GET_WDSLIST, WLC_SET_WDSLIST,
+	"Set or get the list of WDS member MAC addresses.\n"
+	"\tSet using a space separated list of MAC addresses.\n"
+	"\twl wds xx:xx:xx:xx:xx:xx [xx:xx:xx:xx:xx:xx ...]" },
+	{ "lazywds", wl_int, WLC_GET_LAZYWDS, WLC_SET_LAZYWDS,
+	"Set or get \"lazy\" WDS mode (dynamically grant WDS membership to anyone)."},
+	{ "wds_remote_mac", wl_macaddr, WLC_WDS_GET_REMOTE_HWADDR, -1,
+	"Get WDS link remote endpoint's MAC address"},
+	{ "wds_wpa_role_old", wl_wds_wpa_role_old, WLC_WDS_GET_WPA_SUP, -1,
+	"Get WDS link local endpoint's WPA role (old)"},
+	{ "wds_wpa_role", wl_wds_wpa_role, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set WDS link local endpoint's WPA role"},
+#if defined(DWDS)
+	{ "dwds_config", wl_dwds_config, -1, WLC_SET_VAR,
+	"wl dwds_config <enable/disable> <sta/ap> <xx:xx:xx:xx:xx:xx>"},
+#endif
+	{ "wds_type", wl_varint, WLC_GET_VAR, -1,
+	"Indicate whether the interface to which this IOVAR is sent is of WDS or DWDS type.\n\n"
+	WDS_TYPE_USAGE},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_wds_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register wds commands */
+	wl_module_cmds_register(wl_wds_cmds);
+}
+
+static int
+wl_wds_wpa_role_old(void *wl, cmd_t *cmd, char **argv)
+{
+	uint remote[2];
+	uint *sup = remote;
+	int ret = 0;
+
+	UNUSED_PARAMETER(argv);
+
+	if ((ret = wlu_get(wl, WLC_WDS_GET_REMOTE_HWADDR, remote, sizeof(remote))) < 0) {
+		printf("Unable to get remote endpoint's hwaddr\n");
+		return ret;
+	}
+	if ((ret = wlu_get(wl, cmd->get, remote, sizeof(remote))) < 0) {
+		printf("Unable to get local endpoint's WPA role\n");
+		return ret;
+	}
+	printf("Local endpoing's WPA role: %s\n", dtoh32(*sup) ? "supplicant" : "authenticator");
+	return 0;
+}
+
+static int
+wl_wds_wpa_role(void *wl, cmd_t *cmd, char **argv)
+{
+	char var[256];
+	char *mac;
+	char *sup;
+	int len;
+	int ret;
+	if (strlen("wds_wpa_role") + 1 + ETHER_ADDR_LEN + 1 > sizeof(var))
+		return -1;
+	/* build var required by WLC_GET|SET_VAR */
+	len = sprintf(var, "%s", "wds_wpa_role") + 1;
+	mac = var + len;
+	if ((ret = wlu_get(wl, WLC_WDS_GET_REMOTE_HWADDR, mac, ETHER_ADDR_LEN)) < 0) {
+		printf("Unable to get remote endpoint's hwaddr\n");
+		return ret;
+	}
+	len += ETHER_ADDR_LEN + 1;
+	if (argv[1]) {
+		sup = mac + ETHER_ADDR_LEN;
+		switch ((uchar)(*sup = atoi(argv[1]))) {
+		case WL_WDS_WPA_ROLE_AUTH:
+		case WL_WDS_WPA_ROLE_SUP:
+		case WL_WDS_WPA_ROLE_AUTO:
+			if ((ret = wlu_set(wl, cmd->set, var, len)) < 0)
+				printf("Unable to set local endpoint's WPA role\n");
+			break;
+		default:
+			printf("Invalid WPA role %s. %u:authenticator, %u:supplicant, %u:auto\n",
+				argv[1], WL_WDS_WPA_ROLE_AUTH,
+				WL_WDS_WPA_ROLE_SUP, WL_WDS_WPA_ROLE_AUTO);
+			break;
+		}
+	}
+	else if ((ret = wlu_get(wl, cmd->get, var, len)) < 0) {
+		printf("Unable to get local endpoint's WPA role\n");
+		return ret;
+	}
+	else {
+		sup = var;
+		printf("Local endpoint's WPA role: %s\n", *sup ? "supplicant" : "authenticator");
+	}
+	return ret;
+}
+
+#if defined(DWDS)
+static int
+wl_dwds_config(void *wl, cmd_t *cmd, char **argv)
+{
+	wlc_dwds_config_t dwds;
+	int err;
+
+	memset(&dwds, 0, sizeof(wlc_dwds_config_t));
+
+	if (!*++argv) {
+		printf("error: missing arguments\n");
+		return -1;
+	}
+
+	if (!stricmp(*argv, "enable"))
+		dwds.enable = 1;
+	else if (!stricmp(*argv, "disable"))
+		dwds.enable = 0;
+	else {
+		printf("error: unknown mode option %s\n", *argv);
+		return -1;
+	}
+	argv++;
+	/* look for sta/dwds */
+	if (!stricmp(*argv, "sta"))
+		dwds.mode = 1;
+	else if (!stricmp(*argv, "ap"))
+		dwds.mode = 0;
+	else {
+		printf("error: unknown mode option %s\n", *argv);
+		return -1;
+	}
+
+	argv++;
+	/* convert the ea string into an ea struct */
+	if (!*argv || !wl_ether_atoe(*argv, &dwds.ea)) {
+		printf(" ERROR: no valid ether addr provided\n");
+		return -1;
+	}
+
+	if ((err = wlu_iovar_set(wl, cmd->name, &dwds, sizeof(wlc_dwds_config_t))) < 0)
+		return err;
+
+	return (0);
+
+}
+#endif /* DWDS */
diff --git a/wl/src/wl/exe/wluc_wnm.c b/wl/src/wl/exe/wluc_wnm.c
new file mode 100644
index 0000000..8480b80
--- /dev/null
+++ b/wl/src/wl/exe/wluc_wnm.c
@@ -0,0 +1,1711 @@
+/*
+ * wl wnm command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_wnm.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_wnm_bsstrans_roamthrottle;
+static cmd_func_t wl_wnm_bsstrans_rssi_rate_map;
+static cmd_func_t wl_wnm_bss_select_table;
+static cmd_func_t wl_wnm_bss_select_weight;
+static cmd_func_t wl_wnm;
+static cmd_func_t wl_wnm_bsstq;
+static cmd_func_t wl_tclas_add;
+static cmd_func_t wl_tclas_del;
+static cmd_func_t wl_tclas_list;
+static cmd_func_t wl_wnm_tfsreq_add;
+static cmd_func_t wl_wnm_dms_set;
+static cmd_func_t wl_wnm_dms_status;
+static cmd_func_t wl_wnm_dms_term;
+static cmd_func_t wl_wnm_service_term;
+static cmd_func_t wl_wnm_timbc_offset;
+static cmd_func_t wl_wnm_timbc_set;
+static cmd_func_t wl_wnm_timbc_status;
+static cmd_func_t wl_wnm_maxidle;
+static cmd_func_t wl_wnm_bsstrans_req;
+static cmd_func_t wl_wnm_keepalives_max_idle;
+static cmd_func_t wl_wnm_url;
+
+static cmd_t wl_wnm_cmds[] = {
+	{ "wnm", wl_wnm, WLC_GET_VAR, WLC_SET_VAR,
+	"set driver wnm feature mask\n"
+	"\ttype \'wl msglevel ?\' for values" },
+	{ "wnm_bsstq", wl_wnm_bsstq, -1, WLC_SET_VAR,
+	"send 11v BSS transition management query\n"
+	"\tUsage: wl wnm_bsstq [ssid]"},
+	{ "tclas_add", wl_tclas_add, -1, WLC_SET_VAR,
+	"add tclas frame classifier type entry\n"
+	"\tUsage: wl tclas_add <user priority> <type> <mask> <...>\n"
+	"\ttype 0 eth2:     <src mac> <dst mac> <ether type>\n"
+	"\ttype 1/4 ipv4:   <ver> <src> <dst> <s_port> <d_port> <dscp> <prot>\n"
+	"\ttype 2 802.1Q:   <vlan tag>\n"
+	"\ttype 3 filter:   <offset> <value> <mask>\n"
+	"\ttype 4 ipv6:     <ver> <src> <dst> <s_port> <d_port> <dscp> <nxt_hdr> <flw_lbl>\n"
+	"\ttype 5 802.1D/Q: <802.1Q PCP> <802.1Q CFI> <802.1Q VID>"
+	},
+	{ "tclas_del", wl_tclas_del, -1, WLC_SET_VAR,
+	"delete tclas frame classifier type entry\n"
+	"\tUsage: wl tclas_del [<idx> [<len>]]"
+	},
+	{ "tclas_list", wl_tclas_list, WLC_GET_VAR, -1,
+	"list the added tclas frame classifier type entry\n"
+	"\tUsage: wl tclas_list"
+	},
+	{ "wnm_tfsreq_add", wl_wnm_tfsreq_add, -1, WLC_SET_VAR,
+	"add one tfs request element and send tfs request frame\n"
+	"\tUsage: wl wnm_tfsreq_add <tfs_id> <tfs_action_code> <tfs_subelem_id> <send>\n"
+	"\ttfs_id: a non-zero value (1 ~ 255)\n"
+	"\ttfs_action_code bitfield: 1: delete after match, 2: notify\n"
+	"\ttfs_subelem_id: TFS subelement (0 for none or 1 for previous tclas_add)\n"
+	"\tsend: 0: store element, 1: send all stored elements"
+	},
+	{ "wnm_dms_set", wl_wnm_dms_set, -1, WLC_SET_VAR,
+	"Optionally add pending DMS desc (after tclas_add) and optionally register all desc\n"
+	"on AP side to enable the service (with send=1)"
+	"\tUsage: wl wnm_dms_set <send> [<user_id> [<tc_pro>]]\n"
+	"\t\tsend: 0: store descriptor, 1: send all stored descs/enable DMS on AP\n"
+	"\t\tuser_id: new ID to assign to the created desc (if TCLAS added)\n"
+	"\t\t         or existing ID to enable on AP (if no TCLAS added), 0 for all desc\n"
+	"\t\ttc_pro: TCLAS processing element (if several TCLAS added)"
+	},
+	{ "wnm_dms_status", wl_wnm_dms_status, WLC_GET_VAR, -1,
+	"list all DMS descriptors and provide their internal and AP status\n"
+	"\tUsage: wl wl_wnm_dms_status"
+	},
+	{ "wnm_dms_term", wl_wnm_dms_term, -1, WLC_SET_VAR,
+	"Disable registered DMS des on AP side and optionally discard them\n"
+	"\tUsage: wl wnm_dms_term <del> [<user_id>]\n"
+	"\t\tdel: Discard desc after disabling the service on AP side\n"
+	"\t\tuser_id: desc to disable/delete, 0 for all desc"
+	},
+	{ "wnm_service_term", wl_wnm_service_term, -1, WLC_SET_VAR,
+	"Disable service. Check specific wnm_XXX_term for more info\n"
+	"\tUsage: wl wnm_service_term <srv> <service realted params>\n"
+	"\t\tsrv: 1 for DMS, 2 for FMS, 3 for TFS"
+	},
+	{ "wnm_timbc_offset", wl_wnm_timbc_offset, WLC_GET_VAR, WLC_SET_VAR,
+	"get/set TIM broadcast offset by -32768 period > offset(us) > 32768\n"
+	"CAUTION!! Due to resource limitation, one radio can have only one set of TIMBC offset\n"
+	"setting.  MBSS need to share the same setting\n"
+	"\tUsage: wl wnm_timbc_offset <offset> [<tsf_present> [<fix_interval> [<rate_ovreride>]]]\n"
+	"\t\toffset: in unit of us.  Transmit TIM frame in specific TBTT transmit time time\n"
+	"\t\ttsf_present: can be omitted.  If set to 1, timestamp field will present in TIM frame."
+	"If omitted, default setup to 1\n"
+	"\t\tfix_interval: can be omitted.  If set with non-zero value, override STA request "
+	"interval in TIM Broadcast request.  If omitted, default setup to 0\n"
+	"\t\trate_override: can be omitted.  In unit of 500k, max setup to 108.  If set, override"
+	"override high rate used to transmit TIM broadcast high rate frame"
+	},
+	{ "wnm_timbc_set", wl_wnm_timbc_set, -1, WLC_SET_VAR,
+	"Enable/disable TIM Broadcast. Station will send appropriate request if AP suport TIMBC\n"
+	"\tUsage: wl wnm_timbc_set <interval> [<flags> [<min_rate> [<max_rate>]]]\n"
+	"\t\tinterval: Beacon interval requested for TIM frames, 0 to disable TIM BC\n"
+	"\t\tflags: Bitfield with minimal requirements to keep the service enabled (check doc)\n"
+	"\t\tmin_rate: Minimal rate requirement, in Mbps, for TIM high or low rate frames\n"
+	"\t\tmax_rate: Maximal rate requirement"
+	},
+	{ "wnm_timbc_status", wl_wnm_timbc_status, WLC_GET_VAR, -1,
+	"Retrieve TIM Broadcast configuration set with current AP"
+	},
+	{ "wnm_maxidle", wl_wnm_maxidle, WLC_GET_VAR, WLC_SET_VAR,
+	"setup WNM BSS Max Idle Period interval and option\n"
+	"\tUsage: wl wnm_maxidle <Idle Period> <Option>\n"
+	"\tIdle Period: in unit of 1000TU(1.024s)\n"
+	"\tOption: protected keep alive required(0 ~ 1)"
+	},
+	{ "wnm_bsstrans_query", wl_wnm_bsstq, -1, WLC_SET_VAR,
+	"send 11v BSS transition management query\n"
+	"\tUsage: wl wnm_bsstrans_query [ssid]"},
+	{ "wnm_bsstrans_req", wl_wnm_bsstrans_req, -1, WLC_SET_VAR,
+	"send BSS transition management request frame with BSS termination included bit set\n"
+	"\tUsage: wl wnm_bsstrans_req <reqmode> <tbtt> <dur> [unicast]\n"
+	"\treqmode: request mode of BSS transition request\n"
+	"\ttbtt: time of BSS to end of life, in unit of TBTT, max to 65535\n"
+	"\tdur: time of BSS to keep off, in unit of minute, max to 65535\n"
+	"\tunicast: [1|0] unicast or broadcast to notify STA in BSS.  Default in unicast."
+	},
+	{ "wnm_keepalives_max_idle", wl_wnm_keepalives_max_idle, -1, -1,
+	"\tUsage: wl wnm_keepalives_max_idle <keepalives_per_bss_max_idle> <mkeepalive_index>"
+	" [<max_interval>]\n"
+	"set/get the number of keepalives, mkeep-alive index and max_interval configured"
+	" per BSS-Idle period."},
+	{ "wnm_url", wl_wnm_url, WLC_GET_VAR, WLC_SET_VAR,
+	"set/get wnm session information url\n"
+	"Usage for set: wl wnm_url length urlstring\n"
+	"Usage for get: wl wnm_url" },
+	{ "wnm_bsstrans_roamthrottle", wl_wnm_bsstrans_roamthrottle, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set number of roam scans allowed in throttle period\n"
+	"\tUsage: wl wnm_bsstrans_roamthrottle [throttle_period] [scans_allowed]"
+	},
+	{ "wnm_bsstrans_rssi_rate_map", wl_wnm_bsstrans_rssi_rate_map, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set rssi to rate map\n"
+	"\tUsage: wl wnm_bsstrans_rssi_rate_map mode data\n"
+	"\tData is interpeted based on mode\n"
+	"\tFor mode=0: data = rssi0, rssi1, rssi2.... as per wl_bsstrans_rssi_rate_map_t\n"
+	"\tFor mode=1: data = phy-type band streams rssi0, rssi1...\n"
+	"\t\twhere, phy-type = cck, ofdm, 11n, 11ac\n"
+	"\t\tband = 2g or 5g for ofdm, 11n and 11ac. Only 2g for cck\n"
+	"\t\tstreams = Only 1 for cck and ofdm. 1 to 4 for 11n and 11ac\n"
+	"\t\trssiX = monotonically non-decreasing rssi values for the combination of phy-type,\n"
+	"\t\tband and streams. Max rssi values for 11ac: 10, 11n: 8, ofdm: 8, cck: 4"
+	},
+	{ "wnm_bss_select_table", wl_wnm_bss_select_table, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set RSSI or Channel usage factor table in AP Selection\n"
+	"\tGet: wnm_bss_select_table [rssi|cu] [a|b]\n"
+	"\tSet: wnm_bss_select_table [rssi|cu] <tuple> [a|b|all]"
+	},
+	{ "wnm_bss_select_weight", wl_wnm_bss_select_weight, WLC_GET_VAR, WLC_SET_VAR,
+	"Get/Set RSSI or Channel usage weightage in AP selection\n"
+	"\tGet: wnm_bss_select_weight [rssi|cu] [a|b]\n"
+	"\tSet: wnm_bss_select_weight [rssi|cu] <integer> [a|b|all]"
+	},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_wnm_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register wnm commands */
+	wl_module_cmds_register(wl_wnm_cmds);
+}
+
+static int
+wl_wnm_bsstrans_roamthrottle(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_bsstrans_roamthrottle_t *throttle;
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	if (*++(argv) == NULL) {
+		buf[buflen] = '\0';
+		err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+		if (err < 0)
+			return err;
+
+		throttle = (wl_bsstrans_roamthrottle_t *)buf;
+		printf("period %u\n", throttle->period);
+		printf("scans allowed per period %u\n", throttle->scans_allowed);
+		return 0;
+
+	} else {
+		throttle = (wl_bsstrans_roamthrottle_t *) (buf + buflen);
+		buflen += sizeof(*throttle);
+		throttle->ver = WL_BSSTRANS_ROAMTHROTTLE_VERSION;
+		throttle->period = (uint32) strtoul(*argv, NULL, 0);
+
+		if (*++(argv) == NULL) {
+			printf("Incorrect number of arguments\n");
+			return BCME_ERROR;
+		}
+		throttle->scans_allowed = (uint16) strtoul(*argv, NULL, 0);
+
+		if (*++(argv)) {
+			printf("extra arguments\n");
+			return BCME_ERROR;
+		}
+		err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+		return err;
+	}
+	return 0;
+}
+#define RSSI_RATE_MAP_PHY_TYPE_CCK 0
+#define RSSI_RATE_MAP_PHY_TYPE_OFDM 1
+#define RSSI_RATE_MAP_PHY_TYPE_N 2
+#define RSSI_RATE_MAP_PHY_TYPE_AC 3
+
+static int
+wl_wnm_bsstrans_rssi_rate_map(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_bsstrans_rssi_rate_map_t *map;
+	int i;
+	uint32 mode;
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	if (*++(argv) == NULL) {
+		printf("Mode is required \n");
+		return BCME_ERROR;
+	}
+	mode = (uint32)atoi(*argv);
+	if (mode > 1) {
+		printf("Mode can only be 0 or 1\n");
+		return BCME_ERROR;
+	}
+
+	if (mode == 0) {
+		/* Get */
+		if (*++(argv) == NULL) {
+			buf[buflen] = '\0';
+			err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+			if (err < 0)
+				return err;
+
+			map = (wl_bsstrans_rssi_rate_map_t *)buf;
+
+			printf("cck rssi-2g:\n");
+			for (i = 0; i < WL_NUM_RATES_CCK; i++) {
+				printf("%d, ", map->cck[i].rssi_2g);
+			}
+			printf("\n");
+
+			printf("cck rssi-5g:\n");
+			for (i = 0; i < WL_NUM_RATES_CCK; i++) {
+				printf("%d, ", map->cck[i].rssi_5g);
+			}
+			printf("\n");
+
+			printf("ofdm rssi-2g:\n");
+			for (i = 0; i < WL_NUM_RATES_OFDM; i++) {
+				printf("%d, ", map->ofdm[i].rssi_2g);
+			}
+			printf("\n");
+
+			printf("ofdm rssi-5g:\n");
+			for (i = 0; i < WL_NUM_RATES_OFDM; i++) {
+				printf("%d, ", map->ofdm[i].rssi_5g);
+			}
+			printf("\n");
+
+			printf("phy_n 1x1 rssi-2g:\n");
+			for (i = 0; i < WL_NUM_RATES_MCS_1STREAM; i++) {
+				printf("%d, ", map->phy_n[0][i].rssi_2g);
+			}
+			printf("\n");
+
+			printf("phy_n 1x1 rssi-5g:\n");
+			for (i = 0; i < WL_NUM_RATES_MCS_1STREAM; i++) {
+				printf("%d, ", map->phy_n[0][i].rssi_5g);
+			}
+			printf("\n");
+
+			printf("phy_n 2x2 rssi-2g:\n");
+			for (i = 0; i < WL_NUM_RATES_MCS_1STREAM; i++) {
+				printf("%d, ", map->phy_n[1][i].rssi_2g);
+			}
+			printf("\n");
+
+			printf("phy_n 2x2 rssi-5g:\n");
+			for (i = 0; i < WL_NUM_RATES_MCS_1STREAM; i++) {
+				printf("%d, ", map->phy_n[1][i].rssi_5g);
+			}
+			printf("\n");
+
+			printf("phy_ac 1x1 rssi-2g:\n");
+			for (i = 0; i < WL_NUM_RATES_VHT; i++) {
+				printf("%d, ", map->phy_ac[0][i].rssi_2g);
+			}
+			printf("\n");
+
+			printf("phy_ac 1x1 rssi-5g:\n");
+			for (i = 0; i < WL_NUM_RATES_VHT; i++) {
+				printf("%d, ", map->phy_ac[0][i].rssi_5g);
+			}
+			printf("\n");
+
+			printf("phy_ac 2x2 rssi-2g:\n");
+			for (i = 0; i < WL_NUM_RATES_VHT; i++) {
+				printf("%d, ", map->phy_ac[1][i].rssi_2g);
+			}
+			printf("\n");
+
+			printf("phy_ac 2x2 rssi-5g:\n");
+			for (i = 0; i < WL_NUM_RATES_VHT; i++) {
+				printf("%d, ", map->phy_ac[1][i].rssi_5g);
+			}
+			printf("\n");
+
+			return 0;
+		} else { /* Set */
+			int8 *rssi;
+			uint32 len = 0;
+			map = (wl_bsstrans_rssi_rate_map_t *) (buf + buflen);
+			rssi = (int8 *)map->cck;
+			buflen += sizeof(*map);
+			map->ver = WL_BSSTRANS_RSSI_RATE_MAP_VERSION;
+			while (*argv) {
+				*rssi++ = (int8) strtol(*argv, NULL, 0);
+				len++;
+				argv++;
+			}
+			map->len = sizeof(map->ver) + sizeof(map->len) + len;
+			err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+			return err;
+		}
+	} else { /* Mode 1 */
+		uint32 phy_type, band, streams;
+
+		if (*++(argv) == NULL) {
+			goto insufficient_params;
+		}
+		if (!strcmp(*argv, "cck")) {
+			phy_type = RSSI_RATE_MAP_PHY_TYPE_CCK;
+		}
+		else if (!strcmp(*argv, "ofdm")) {
+			phy_type = RSSI_RATE_MAP_PHY_TYPE_OFDM;
+		}
+		else if (!strcmp(*argv, "11n")) {
+			phy_type = RSSI_RATE_MAP_PHY_TYPE_N;
+		}
+		else if (!strcmp(*argv, "11ac")) {
+			phy_type = RSSI_RATE_MAP_PHY_TYPE_AC;
+		}
+		else {
+			printf("Wrong phy-type: only cck/ofdm/11n/11ac supported\n");
+			return BCME_ERROR;
+		}
+
+		if (*++(argv) == NULL) {
+			goto insufficient_params;
+		}
+
+		if (!strcmp(*argv, "2g")) {
+			band = 0;
+		}
+		else if (!strcmp(*argv, "5g")) {
+			if (phy_type == RSSI_RATE_MAP_PHY_TYPE_CCK) {
+				printf("cck not allowed on 5g\n");
+				return BCME_ERROR;
+			}
+			band = 1;
+		}
+		else {
+			printf("Wrong band-type: only '2g' and '5g' are supported\n");
+			return BCME_ERROR;
+		}
+
+		if (*++(argv) == NULL) {
+			goto insufficient_params;
+		}
+
+		streams = atoi(*argv);
+		if (streams < 1 || streams > 4) {
+			printf("Wrong number of streams: Only 1 to 4 supported\n");
+			return BCME_ERROR;
+		}
+		if ((phy_type == RSSI_RATE_MAP_PHY_TYPE_CCK ||
+			phy_type == RSSI_RATE_MAP_PHY_TYPE_OFDM) && streams > 1) {
+			printf("Only 1 stream allowed for CCK/OFDM\n");
+			return BCME_ERROR;
+		}
+
+		buf[buflen] = '\0';
+		err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+		if (err < 0) {
+			return err;
+		}
+		map = (wl_bsstrans_rssi_rate_map_t *)buf;
+
+		/* GET */
+		if (*++(argv) == NULL) {
+			switch (phy_type) {
+			case RSSI_RATE_MAP_PHY_TYPE_CCK:
+				printf("cck rssi-2g:\n");
+				for (i = 0; i < WL_NUM_RATES_CCK; i++) {
+					printf("%d, ", map->cck[i].rssi_2g);
+				}
+				printf("\n");
+				break;
+			case RSSI_RATE_MAP_PHY_TYPE_OFDM:
+				printf("ofdm rssi-%sg:\n", band == 0?"2":"5");
+				for (i = 0; i < WL_NUM_RATES_OFDM; i++) {
+					if (band == 0)
+						printf("%d, ", map->ofdm[i].rssi_2g);
+					else
+						printf("%d, ", map->ofdm[i].rssi_5g);
+				}
+				printf("\n");
+				break;
+			case RSSI_RATE_MAP_PHY_TYPE_N:
+				printf("11N streams:%dx%d rssi-%sg:\n", streams,
+					streams, band == 0 ? "2" : "5");
+				for (i = 0; i < WL_NUM_RATES_MCS_1STREAM; i++) {
+					if (band == 0) {
+						printf("%d, ", map->phy_n[streams-1][i].rssi_2g);
+					} else {
+						printf("%d, ", map->phy_n[streams-1][i].rssi_5g);
+					}
+				}
+				printf("\n");
+				break;
+			case RSSI_RATE_MAP_PHY_TYPE_AC:
+				printf("11AC streams:%dx%d rssi-%sg:\n", streams,
+					streams, band == 0 ? "2" : "5");
+				for (i = 0; i < WL_NUM_RATES_VHT; i++) {
+					if (band == 0) {
+						printf("%d, ", map->phy_ac[streams-1][i].rssi_2g);
+					} else {
+						printf("%d, ", map->phy_ac[streams-1][i].rssi_5g);
+					}
+				}
+				printf("\n");
+				break;
+			}
+		} else { /* Set */
+			int cmdlen = strlen(cmd->name);
+
+			/* Make space for writing cmd name */
+			memmove(buf+cmdlen+1, buf, sizeof(*map));
+
+			buflen = sprintf(buf, "%s", cmd->name) + 1;
+			buf[buflen] = '\0';
+
+			/* SET */
+			map = (wl_bsstrans_rssi_rate_map_t *) (buf + buflen);
+
+			switch (phy_type) {
+			case RSSI_RATE_MAP_PHY_TYPE_CCK:
+				for (i = 0; i < WL_NUM_RATES_CCK; i++) {
+					if (*argv == NULL) {
+						break;
+					}
+					map->cck[i].rssi_2g = (int8) strtol(*argv, NULL, 0);
+					argv++;
+				}
+				break;
+			case RSSI_RATE_MAP_PHY_TYPE_OFDM:
+				for (i = 0; i < WL_NUM_RATES_OFDM; i++) {
+					if (*argv == NULL) {
+						break;
+					}
+					if (band == 0) {
+						map->ofdm[i].rssi_2g = (int8)strtol(*argv, NULL, 0);
+					} else {
+						map->ofdm[i].rssi_5g = (int8)strtol(*argv, NULL, 0);
+					}
+					argv++;
+				}
+				break;
+			case RSSI_RATE_MAP_PHY_TYPE_N:
+				for (i = 0; i < WL_NUM_RATES_MCS_1STREAM; i++) {
+					if (*argv == NULL) {
+						break;
+					}
+					if (band == 0) {
+						map->phy_n[streams-1][i].rssi_2g =
+							(int8)strtol(*argv, NULL, 0);
+					} else {
+						map->phy_n[streams-1][i].rssi_5g =
+							(int8)strtol(*argv, NULL, 0);
+					}
+					argv++;
+				}
+				break;
+			case RSSI_RATE_MAP_PHY_TYPE_AC:
+				for (i = 0; i < WL_NUM_RATES_VHT; i++) {
+					if (*argv == NULL) {
+						break;
+					}
+					if (band == 0) {
+						map->phy_ac[streams-1][i].rssi_2g =
+							(int8)strtol(*argv, NULL, 0);
+					} else {
+						map->phy_ac[streams-1][i].rssi_5g =
+							(int8)strtol(*argv, NULL, 0);
+					}
+					argv++;
+				}
+				break;
+			}
+
+			buflen += sizeof(*map);
+			map->ver = WL_BSSTRANS_RSSI_RATE_MAP_VERSION;
+			map->len = sizeof(*map);
+			err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+			return err;
+		}
+		return 0;
+insufficient_params:
+		printf("Insufficient params for mode 1\n");
+		return BCME_ERROR;
+	} /* Mode 1 */
+	return 0;
+}
+
+static dbg_msg_t wl_wnm_msgs[] = {
+	{WL_WNM_BSSTRANS,	"BSS-Transition"},
+	{WL_WNM_PROXYARP,	"Proxy-ARP"},
+	{WL_WNM_MAXIDLE,	"BSS-Max-Idle-Period"},
+	{WL_WNM_TIMBC,		"TIM-Broadcast"},
+	{WL_WNM_TFS,		"Traffic-Filtering"},
+	{WL_WNM_SLEEP,		"WNM-Sleep-Mode"},
+	{WL_WNM_DMS,		"Directed-Multicast"},
+	{WL_WNM_FMS,		"Flexible-Multicast"},
+	{WL_WNM_NOTIF,		"Notification"},
+	{0, ""}
+};
+
+static int
+wl_wnm(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret, i;
+	uint val;
+	int wnmmask;
+	char *s;
+
+	ret = wlu_iovar_getint(wl, cmd->name, &wnmmask);
+	if (ret < 0)
+		return ret;
+
+	if (!*++argv) {
+		printf("0x%x:", wnmmask);
+		for (i = 0; wl_wnm_msgs[i].value; i++)
+			if (wnmmask & wl_wnm_msgs[i].value)
+				printf("  %s", wl_wnm_msgs[i].string);
+		printf("\n");
+		return 0;
+	}
+
+	s = *argv;
+	if (*s == '+' || *s == '-')
+		s++;
+
+	if (!*s)
+		goto usage;
+
+	val = strtoul(s, &s, 0);
+	if (*s)
+		goto usage;
+
+	if (**argv == '+')
+		wnmmask |= val;
+	else if (**argv == '-')
+		wnmmask &= ~val;
+	else
+		wnmmask = val;
+
+	return wlu_iovar_setint(wl, cmd->name, wnmmask);
+
+usage:
+	fprintf(stderr, "WNM mask is a bitfield from the following set. "
+		"Use + or - prefix to combine with current value:\n");
+
+	for (i = 0; wl_wnm_msgs[i].value; i++)
+		fprintf(stderr, " 0x%04x %s\n", wl_wnm_msgs[i].value, wl_wnm_msgs[i].string);
+
+	return 0;
+}
+
+static int
+wl_wnm_bsstq(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wlc_ssid_t ssid;
+
+	UNUSED_PARAMETER(cmd);
+
+	strcpy(buf, "wnm_bsstrans_query");
+	buflen = strlen("wnm_bsstrans_query") + 1;
+
+	if (*++argv) {
+		uint32 len;
+
+		len = strlen(*argv);
+		if (len > DOT11_MAX_SSID_LEN) {
+			printf("ssid too long\n");
+			return (-1);
+		}
+		memset(&ssid, 0, sizeof(wlc_ssid_t));
+		memcpy(ssid.SSID, *argv, len);
+		ssid.SSID_len = len;
+		memcpy(&buf[buflen], &ssid, sizeof(wlc_ssid_t));
+		buflen += sizeof(wlc_ssid_t);
+	}
+
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+#define TCLAS_ARG_CHECK(argv, str) \
+	do { \
+		if (*++(argv) == NULL) { \
+			printf("TCLAS Frame Classifier: %s not provided\n", (str)); \
+			return BCME_ERROR; \
+		} \
+	} while (0)
+
+static int
+wl_tclas_add(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1, buflen;
+	dot11_tclas_fc_t *fc;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	/* Check the user priority value */
+	TCLAS_ARG_CHECK(argv, "user priority");
+	buf[buflen++] = (uint8)strtoul(*argv, NULL, 0);
+
+	/* unaligned! */
+	fc = (dot11_tclas_fc_t *) (buf + buflen);
+	memset((void *)fc, 0, sizeof(dot11_tclas_fc_t));
+
+	/* Parse frame classifier type and mask */
+	TCLAS_ARG_CHECK(argv, "type");
+	fc->hdr.type = (uint8)strtoul(*argv, NULL, 0);
+
+	TCLAS_ARG_CHECK(argv, "mask");
+	fc->hdr.mask = (uint8)strtoul(*argv, NULL, 0);
+	if (fc->hdr.type ==  DOT11_TCLAS_FC_0_ETH) {
+		dot11_tclas_fc_0_eth_t *fc_eth = (dot11_tclas_fc_0_eth_t *)fc;
+
+		TCLAS_ARG_CHECK(argv, "src mac");
+		if (strlen(*argv) > 1) {
+			if (!wl_ether_atoe(*argv, (struct ether_addr *)fc_eth->sa)) {
+				printf(" ERROR: no valid src ether addr provided\n");
+				return BCME_ERROR;
+			}
+		}
+		else
+			memset(fc_eth->sa, 0, ETHER_ADDR_LEN);
+
+		TCLAS_ARG_CHECK(argv, "dst mac");
+		if (strlen(*argv) > 1) {
+			if (!wl_ether_atoe(*argv, (struct ether_addr *)fc_eth->da)) {
+				printf(" ERROR: no valid dst ether addr provided\n");
+				return BCME_ERROR;
+			}
+		}
+		else
+			memset(fc_eth->da, 0, ETHER_ADDR_LEN);
+
+		TCLAS_ARG_CHECK(argv, "ether type");
+		fc_eth->eth_type = hton16((uint16)strtoul(*argv, NULL, 0));
+
+		buflen += DOT11_TCLAS_FC_0_ETH_LEN;
+
+		err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+	}
+	else if (fc->hdr.type == DOT11_TCLAS_FC_1_IP ||
+		fc->hdr.type == DOT11_TCLAS_FC_4_IP_HIGHER) {
+		uint8 version;
+
+		TCLAS_ARG_CHECK(argv, "ip version");
+		version = (uint8)strtoul(*argv, NULL, 0);
+		if (version == IP_VER_6) {
+			dot11_tclas_fc_4_ipv6_t *fc_ipv6 = (dot11_tclas_fc_4_ipv6_t *)fc;
+			uint32 fl;
+
+			fc_ipv6->version = version;
+
+			TCLAS_ARG_CHECK(argv, "ipv6 source ip");
+			if (!wl_atoipv6(*argv, (struct ipv6_addr *)&fc_ipv6->saddr)) {
+				printf("incorrect ipv6 source ip format\n");
+				return BCME_ERROR;
+			}
+
+			TCLAS_ARG_CHECK(argv, "ipv6 dest ip");
+			if (!wl_atoipv6(*argv, (struct ipv6_addr *)&fc_ipv6->daddr)) {
+				printf("incorrect ipv6 dest ip format\n");
+				return BCME_ERROR;
+			}
+
+			TCLAS_ARG_CHECK(argv, "ipv6 source port");
+			fc_ipv6->src_port = hton16((uint16)strtoul(*argv, NULL, 0));
+
+			TCLAS_ARG_CHECK(argv, "ipv6 dest port");
+			fc_ipv6->dst_port = hton16((uint16)strtoul(*argv, NULL, 0));
+
+			TCLAS_ARG_CHECK(argv, "ipv6 dscp");
+			fc_ipv6->dscp = (uint8)strtoul(*argv, NULL, 0);
+
+			TCLAS_ARG_CHECK(argv, "ipv6 next header");
+			fc_ipv6->nexthdr = (uint8)strtoul(*argv, NULL, 0);
+
+			TCLAS_ARG_CHECK(argv, "ipv6 flow label");
+			fl = (uint32) strtoul(*argv, NULL, 0);
+			fc_ipv6->flow_lbl[2] = (fl >> 16) & 0xFF;
+			fc_ipv6->flow_lbl[1] = (fl >> 8) & 0xFF;
+			fc_ipv6->flow_lbl[0] = (fl >> 0) & 0xFF;
+
+			buflen += DOT11_TCLAS_FC_4_IPV6_LEN;
+
+			err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+		} else
+		if (version == IP_VER_4) {
+			dot11_tclas_fc_1_ipv4_t *fc_ipv4 = (dot11_tclas_fc_1_ipv4_t *)fc;
+
+			fc_ipv4->version = version;
+
+			TCLAS_ARG_CHECK(argv, "ipv4 source ip");
+			if (!wl_atoip(*argv, (struct ipv4_addr *)&fc_ipv4->src_ip)) {
+				printf("incorrect source ip format\n");
+				return BCME_ERROR;
+			}
+
+			TCLAS_ARG_CHECK(argv, "ipv4 dest ip");
+			if (!wl_atoip(*argv, (struct ipv4_addr *)&fc_ipv4->dst_ip)) {
+				printf("incorrect dest ip format\n");
+				return BCME_ERROR;
+			}
+
+			TCLAS_ARG_CHECK(argv, "ipv4 source port");
+			fc_ipv4->src_port = (uint16)strtoul(*argv, NULL, 0);
+			fc_ipv4->src_port = hton16(fc_ipv4->src_port);
+
+			TCLAS_ARG_CHECK(argv, "ipv4 dest port");
+			fc_ipv4->dst_port = (uint16)strtoul(*argv, NULL, 0);
+			fc_ipv4->dst_port = hton16(fc_ipv4->dst_port);
+
+			TCLAS_ARG_CHECK(argv, "ipv4 dscp");
+			fc_ipv4->dscp = (uint8)strtoul(*argv, NULL, 0);
+
+			TCLAS_ARG_CHECK(argv, "ipv4 protocol");
+			fc_ipv4->protocol = (uint8)strtoul(*argv, NULL, 0);
+
+			buflen += DOT11_TCLAS_FC_1_IPV4_LEN;
+
+			err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+		} else
+			return BCME_ERROR;
+	} else {
+		printf("Unsupported frame classifier type 0x%2x\n", fc->hdr.type);
+		return BCME_ERROR;
+	}
+
+	return err;
+}
+
+static int
+wl_tclas_del(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen, totlen;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+	totlen = buflen + 2;
+
+	/* Set initial length */
+	buf[buflen] = 0;	/* first value present for init index */
+	buf[buflen + 1] = 0;	/* second value present for delete count */
+
+	/* Check idx and add if present */
+	if (*++argv == NULL)
+		goto set;
+	buf[buflen] = 1;
+	buf[buflen + 1] = (uint8)strtoul(*argv, NULL, 0);
+
+	/* Check len and add if present */
+	if (*++argv == NULL)
+		goto set;
+	buf[buflen] = 2;
+	buf[buflen + 2] = (uint8)strtoul(*argv, NULL, 0);
+
+	if (*++argv) {
+		printf("Too much args provided\n");
+		return BCME_ERROR;
+	}
+set:
+	err = wlu_set(wl, WLC_SET_VAR, buf, totlen);
+
+	return err;
+}
+
+
+static void
+wl_tclas_dump(wl_tclas_t *tclas)
+{
+	dot11_tclas_fc_hdr_t *fc = &tclas->fc.hdr;
+	dot11_tclas_fc_0_eth_t *eth = &tclas->fc.t0_eth;
+	dot11_tclas_fc_1_ipv4_t *ipv4 = &tclas->fc.t1_ipv4;
+	dot11_tclas_fc_4_ipv6_t *ipv6 = &tclas->fc.t4_ipv6;
+
+#define TCDMP(x) ((fc->mask & (x))?'+':'-')
+
+	printf("up %d  type %d  mask 0x%x  ", tclas->user_priority, fc->type, fc->mask);
+
+	/* Check frame classifier parameter type */
+	if (fc->type == DOT11_TCLAS_FC_0_ETH) {
+		printf("(Eth: ");
+		printf("%cSA %s  ", TCDMP(1), wl_ether_etoa((struct ether_addr*)eth->sa));
+		printf("%cDA %s  ", TCDMP(2), wl_ether_etoa((struct ether_addr*)eth->da));
+		printf("%ctype 0x%04x", TCDMP(4), ntoh16(eth->eth_type));
+		printf(")\n");
+	} else if (fc->type == DOT11_TCLAS_FC_1_IP ||
+		(fc->type == DOT11_TCLAS_FC_4_IP_HIGHER && ipv4->version == IP_VER_4)) {
+		/* Check parameter type 1/4 IPv4 version */
+		printf("(IPv4: ");
+		printf("%cver %d  ", TCDMP(1), ipv4->version);
+		printf("%csip %s  ", TCDMP(2), wl_iptoa((struct ipv4_addr *)&ipv4->src_ip));
+		printf("%cdip %s  ", TCDMP(4), wl_iptoa((struct ipv4_addr *)&ipv4->dst_ip));
+		printf("%csp %d  ", TCDMP(8), ntoh16(ipv4->src_port));
+		printf("%cdp %d  ", TCDMP(16), ntoh16(ipv4->dst_port));
+		printf("%cdscp 0x%x  ", TCDMP(32), ipv4->dscp);
+		printf("%cprot %d", TCDMP(64), ipv4->protocol);
+		printf(")\n");
+	} else if (fc->type == DOT11_TCLAS_FC_4_IP_HIGHER && ipv6->version == IP_VER_6) {
+		/* Check parameter type 4 IPv6 version */
+		printf("(IPv6: ");
+		printf("%cver %d  ", TCDMP(1), ipv6->version);
+		printf("%csip %s  ", TCDMP(2), wl_ipv6toa(ipv6->saddr));
+		printf("%cdip %s  ", TCDMP(4), wl_ipv6toa(ipv6->daddr));
+		printf("%csp %d  ", TCDMP(8), ntoh16(ipv6->src_port));
+		printf("%cdp %d  ", TCDMP(16), ntoh16(ipv6->dst_port));
+		printf("%cdscp 0x%x  ", TCDMP(32), ipv6->dscp);
+		printf("%cprot %d", TCDMP(64), ipv6->nexthdr);
+		printf("%cfl %d", TCDMP(64),
+			ipv6->flow_lbl[2]<<16 | ipv6->flow_lbl[1]<<8 | ipv6->flow_lbl[0]);
+		printf(")\n");
+	} else {
+		printf("(type unsupported)\n");
+	}
+}
+
+static int
+wl_tclas_list_parse(wl_tclas_list_t *list)
+{
+	uint32 i;
+	uint8 *ptr = (uint8 *)&list->tclas[0];
+	int retlen = 0;
+
+	for (i = 0; i < list->num; i++) {
+		wl_tclas_t *tclas = (wl_tclas_t *)ptr;
+
+		printf("tclas idx %d: ", i);
+
+		wl_tclas_dump(tclas);
+
+		retlen += WL_TCLAS_FIXED_SIZE + tclas->fc_len;
+
+		/* Move to the next tclas frame classifier parameter */
+		ptr += WL_TCLAS_FIXED_SIZE + tclas->fc_len;
+	}
+
+	return retlen;
+}
+
+static int
+wl_tclas_list(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	wl_tclas_list_t *tclas_list = NULL;
+	void *ptr = NULL;
+
+	if (*++argv) {
+		printf("Too much args provided\n");
+		return BCME_ERROR;
+	}
+
+	err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr);
+	if (err == BCME_OK) {
+		tclas_list = (wl_tclas_list_t *)ptr;
+		if (tclas_list->num == 0)
+			printf("No tclas frame classifier parameter entry\n");
+		else
+			wl_tclas_list_parse(tclas_list);
+	}
+
+	return err;
+}
+
+static int
+wl_wnm_tfsreq_add(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int err = -1, buflen;
+	wl_tfs_req_t tfs_req;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++)
+		;
+
+	strcpy(buf, "wnm_tfsreq_add");
+	buflen = strlen("wnm_tfsreq_add") + 1;
+
+	if (argc != 5 || *++(argv) == NULL) {
+		printf("Incorrect args provided\n");
+		return BCME_ERROR;
+	}
+
+	tfs_req.tfs_id = (uint8)strtoul(*argv++, NULL, 0);
+
+	if (*argv != NULL)
+		tfs_req.tfs_actcode = (uint8)strtoul(*argv++, NULL, 0);
+	else {
+		printf("Incorrect args provided\n");
+		return BCME_ERROR;
+	}
+
+	if (*argv != NULL)
+		tfs_req.tfs_subelem_id = (uint8)strtoul(*argv++, NULL, 0);
+	else {
+		printf("Incorrect args provided\n");
+		return BCME_ERROR;
+	}
+
+	if (*argv != NULL)
+		tfs_req.send = strtoul(*argv, NULL, 0) == 0 ? FALSE : TRUE;
+	else {
+		printf("Incorrect args provided\n");
+		return BCME_ERROR;
+	}
+
+	if (tfs_req.tfs_id == 0 ||
+		tfs_req.tfs_actcode > 3 ||
+		tfs_req.tfs_subelem_id > 1) {
+		printf("Input args not in range\n");
+		return BCME_ERROR;
+	}
+
+	buf[buflen++] = tfs_req.tfs_id;
+	buf[buflen++] = tfs_req.tfs_actcode;
+	buf[buflen++] = tfs_req.tfs_subelem_id;
+	buf[buflen++] = tfs_req.send;
+
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+static int
+wl_wnm_dms_set(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_dms_set_t *dms_set;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+	dms_set = (wl_dms_set_t *) (buf + buflen);
+	dms_set->user_id = 0;
+	dms_set->tclas_proc = 0;
+	buflen += sizeof(wl_dms_set_t);
+
+	if (*++(argv) == NULL) {
+		printf("Missing <send> argument\n");
+		return BCME_ERROR;
+	}
+	dms_set->send = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	dms_set->user_id = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	dms_set->tclas_proc = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv)) {
+		printf("extra argument\n");
+		return BCME_ERROR;
+	}
+set:
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+static int
+wl_wnm_dms_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	wl_dms_status_t *dms_list = (wl_dms_status_t *)buf;
+	uint8 *p = (uint8 *)dms_list->desc;
+
+	strcpy(buf, argv[0]);
+
+	ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+	if (ret < 0)
+		return ret;
+
+	dms_list->cnt = dtoh32(dms_list->cnt);
+
+	while (dms_list->cnt--) {
+
+		wl_dms_desc_t *desc = (wl_dms_desc_t *)p;
+
+		printf("DMS desc UserID %d:\n", desc->user_id);
+		printf("\tstatus:%d   token:%d   DMS ID:%d   TCLAS proc:%d\n",
+			desc->status, desc->token, desc->dms_id, desc->tclas_proc);
+
+		p += WL_DMS_DESC_FIXED_SIZE;
+
+		if (desc->mac_len) {
+			printf("\tRegistered STA:\n");
+
+			while (desc->mac_len) {
+				printf("\t\t- %s\n", wl_ether_etoa((struct ether_addr*)p));
+				p += ETHER_ADDR_LEN;
+				desc->mac_len -= ETHER_ADDR_LEN;
+			}
+		}
+
+		printf("\tTCLAS:\n");
+		while (desc->tclas_len) {
+			wl_tclas_t *tclas = (wl_tclas_t *)p;
+
+			printf("\t\t- ");
+			wl_tclas_dump(tclas);
+
+			p += WL_TCLAS_FIXED_SIZE + tclas->fc_len;
+			desc->tclas_len -= WL_TCLAS_FIXED_SIZE + tclas->fc_len;
+		}
+	}
+
+	return 0;
+}
+
+static int
+wl_wnm_dms_term(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_dms_term_t *dms_term;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	dms_term = (wl_dms_term_t *) (buf + buflen);
+	dms_term->user_id = 0;
+	buflen += sizeof(wl_dms_term_t);
+
+	if (*++(argv) == NULL) {
+		printf("Missing <del> argument\n");
+		return BCME_ERROR;
+	}
+	dms_term->del = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	dms_term->user_id = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv)) {
+		printf("extra argument\n");
+		return BCME_ERROR;
+	}
+set:
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+static int
+wl_wnm_service_term(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_service_term_t *term;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	term = (wl_service_term_t *) (buf + buflen);
+	term->u.dms.user_id = 0;
+	buflen += sizeof(wl_service_term_t);
+
+	if (*++(argv) == NULL) {
+		printf("Missing <service> argument\n");
+		return BCME_ERROR;
+	}
+	term->service = (uint8) strtoul(*argv, NULL, 0);
+
+	/* Need per service processing from here? */
+	if (*++(argv) == NULL) {
+		printf("Missing <del> argument\n");
+		return BCME_ERROR;
+	}
+	term->u.dms.del = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	term->u.dms.user_id = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv)) {
+		printf("extra argument\n");
+		return BCME_ERROR;
+	}
+set:
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+static int
+wl_wnm_timbc_offset(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_timbc_offset_t *timbc_offset;
+	char *p = buf;
+	int size;
+	UNUSED_PARAMETER(cmd);
+
+	size = sprintf(p, "%s", *argv++) + 1;
+
+	if (*argv == NULL) {
+		/* retrieve bss idle period if argument count incorrect */
+		int err = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+		if (err < 0)
+			return err;
+
+		timbc_offset = (wl_timbc_offset_t *)buf;
+		printf("TIMBC offset: %d, tsf_present: %d, fix_interval: %d, rate_override: %d\n",
+			timbc_offset->offset, timbc_offset->tsf_present, timbc_offset->fix_intv,
+			timbc_offset->rate_override);
+
+		return BCME_OK;
+
+	} else {
+		if (!isdigit((int)*argv[0]))
+			return BCME_ERROR;
+
+		timbc_offset = (wl_timbc_offset_t *)(p + size);
+
+		timbc_offset->offset = (int16)strtoul(*argv++, NULL, 0);
+		timbc_offset->tsf_present = TRUE;
+		timbc_offset->fix_intv = 0;
+		timbc_offset->rate_override = 0;
+
+		if (*argv != NULL) {
+			timbc_offset->tsf_present = (bool)strtoul(*argv++, NULL, 0);
+			if (*argv != NULL) {
+				timbc_offset->fix_intv = (uint16)strtoul(*argv++, NULL, 0);
+				if (*argv != NULL) {
+					timbc_offset->rate_override =
+						(uint16)strtoul(*argv++, NULL, 0);
+				}
+			}
+		}
+
+		return wlu_set(wl, WLC_SET_VAR, buf, size + sizeof(wl_timbc_offset_t));
+	}
+}
+
+static int
+wl_wnm_timbc_set(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, buflen;
+	wl_timbc_set_t *req;
+
+	UNUSED_PARAMETER(cmd);
+
+	buflen = sprintf(buf, "%s", *argv) + 1;
+
+	req = (wl_timbc_set_t *) (buf + buflen);
+	req->flags = 0;
+	req->rate_min = 0;
+	req->rate_max = 0;
+	buflen += sizeof(wl_timbc_set_t);
+
+	if (*++(argv) == NULL) {
+		printf("Missing <interval> argument\n");
+		return BCME_ERROR;
+	}
+	req->interval = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	req->flags = (uint8) strtoul(*argv, NULL, 0);
+
+	if (*++(argv) == NULL)
+		goto set;
+	req->rate_min = htod16(rate_string2int(*argv));
+
+	if (*++(argv) == NULL)
+		goto set;
+	req->rate_max = htod16(rate_string2int(*argv));
+
+	if (*++(argv)) {
+		printf("Too many arguments\n");
+		return BCME_ERROR;
+	}
+set:
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+static int
+wl_wnm_timbc_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int ret;
+	wl_timbc_status_t *status = (wl_timbc_status_t *)buf;
+	char hrate[16], lrate[16];
+
+	strcpy(buf, argv[0]);
+
+	ret = wlu_get(wl, cmd->get, buf, WLC_IOCTL_MAXLEN);
+	if (ret < 0)
+		return ret;
+
+	printf("TIM BC current status: %d  status_ap: %d\n"
+		"  interval: %d   offset: %d\n"
+		"  high rate: %s   low rate: %s\n",
+		status->status_sta,
+		status->status_ap,
+		status->interval, status->offset,
+		rate_int2string(hrate, status->rate_high),
+		rate_int2string(lrate, status->rate_low));
+
+	return BCME_OK;
+}
+
+static int
+wl_wnm_maxidle(void *wl, cmd_t *cmd, char **argv)
+{
+	struct {
+		int period;
+		int protect;
+	} params = { 0, 0 };
+	char *endptr;
+
+	if (*++argv == NULL) {
+		/* retrieve bss idle period if argument count incorrect */
+		int err = wlu_iovar_getint(wl, cmd->name, &params.period);
+		if (err < 0)
+			return err;
+
+		printf("BSS Max Idle Period: %d\n", dtoh32(params.period));
+		return BCME_OK;
+
+	} else {
+		/* parse the idle period */
+		params.period = strtoul(*argv++, &endptr, 0);
+		htod32(params.period);
+		if (*endptr != '\0')
+			return BCME_USAGE_ERROR;
+
+		/* parse the optional keep-alive protect flag */
+		if (*argv) {
+			params.protect = strtoul(*argv, &endptr, 0);
+			htod32(params.protect);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+
+		return wlu_var_setbuf(wl, cmd->name, &params, sizeof(params));
+	}
+}
+
+static int
+wl_wnm_bsstrans_req(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	wl_bsstrans_req_t bsstrans_req;
+	int buflen = sprintf(buf, "%s", *argv) + 1;
+	int tmp;
+
+	UNUSED_PARAMETER(cmd);
+
+	/* req mode parsing */
+	if (*++argv == NULL) {
+		fprintf(stderr, "%s: error: reqmode missing\n", __FUNCTION__);
+		return BCME_ERROR;
+	}
+	bsstrans_req.reqmode = strtoul(*argv, NULL, 0);
+
+	/* tbtt parsing */
+	if (*++argv == NULL) {
+		fprintf(stderr, "%s: error: tbtt missing\n", __FUNCTION__);
+		return BCME_ERROR;
+	}
+	tmp = strtoul(*argv, NULL, 0);
+	if (tmp > 65535 || tmp < 0) {
+		fprintf(stderr, "%s: error: tbtt out of range(%d)\n", __FUNCTION__, tmp);
+		return BCME_ERROR;
+	}
+	else
+		bsstrans_req.tbtt = tmp;
+
+	/* dur parsing */
+	if (*++argv == NULL) {
+		fprintf(stderr, "%s: error: dur missing\n", __FUNCTION__);
+		return BCME_ERROR;
+	}
+	tmp = strtoul(*argv, NULL, 0);
+	if (tmp > 65535 || tmp < 0) {
+		fprintf(stderr, "%s: error: dur out of range(%d)\n", __FUNCTION__, tmp);
+		return BCME_ERROR;
+	}
+	else
+		bsstrans_req.dur = tmp;
+
+	/* unicast/broadcast parsing */
+	if (*++argv != NULL)
+		bsstrans_req.unicast = strtoul(*argv, NULL, 0);
+	else
+		bsstrans_req.unicast = 1;
+
+	memcpy(&buf[buflen], &bsstrans_req, sizeof(bsstrans_req));
+	buflen += sizeof(bsstrans_req);
+
+	err = wlu_set(wl, WLC_SET_VAR, buf, buflen);
+
+	return err;
+}
+
+/*
+ * Get or Set wnm keepalive configuration
+ */
+static int
+wl_wnm_keepalives_max_idle(void *wl, cmd_t *cmd, char **argv)
+{
+	int err, argc;
+	keepalives_max_idle_t keepalive;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	if (*argv == NULL) {
+		/* get current params */
+		if ((err = wlu_iovar_get(wl, cmd->name, (void *) &keepalive,
+			(sizeof(keepalive)))) < 0)
+			return (err);
+
+		printf("Keepalives_max_idle parameters -\n");
+		printf("num_of_keepalives_per_bss_max_idle\t\t= %d\nmkeep_alive_index\t= %d"
+			"\nmax_interval\t= %d\n", keepalive.keepalive_count,
+			keepalive.mkeepalive_index, keepalive.max_interval);
+	} else {
+		char *endptr;
+		/* Validate num of entries */
+		for (argc = 0; argv[argc]; argc++);
+		if (argc < 2 || argc > 3)
+			return BCME_ERROR;
+
+		keepalive.keepalive_count = strtol(argv[0], &endptr, 0);
+		keepalive.mkeepalive_index = strtol(argv[1], &endptr, 0);
+		if (argc == 3)
+			keepalive.max_interval = strtol(argv[2], &endptr, 0);
+		else
+			keepalive.max_interval = 0;
+
+		/* Set params */
+		err = wlu_iovar_set(wl, cmd->name, (void *) &keepalive,
+			(sizeof(keepalives_max_idle_t)));
+	}
+
+	return err;
+}
+
+static int
+wl_wnm_url(void *wl, cmd_t *cmd, char **argv)
+{
+	void *ptr;
+	int err;
+	uchar *data;
+	uchar datalen, count;
+	wnm_url_t *url;
+
+	if (!*++argv) {
+		err = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr);
+		if (err == 0) {
+			data = (uchar *)ptr;
+			datalen = data[0];
+			data ++;
+			*(data + datalen) = '\0';
+			printf("%s URL len %d\n", cmd->name, datalen);
+			printf("%s URL: %s\n", cmd->name, data);
+		}
+		else {
+			fprintf(stderr, "Error %d getting IOVar\n", err);
+		}
+		return err;
+	}
+
+	/* get URL length */
+	datalen = (uchar)atoi(argv[0]);
+
+	if (datalen > 0) {
+		if (!argv[1]) {
+			fprintf(stderr, "URL string should be specified for URL length %d\n",
+				datalen);
+			return BCME_BADARG;
+		}
+		else {
+			if ((int)strlen (argv[1]) != datalen) {
+				fprintf(stderr, "length is not matching to string\n");
+				return BCME_BADARG;
+			}
+		}
+	}
+
+	if ((datalen == 0) && (argv[1] != NULL))
+		fprintf(stderr, "Ignoring data bytes for length %d\n", datalen);
+
+	count = sizeof(wnm_url_t) + datalen - 1;
+	data = malloc(count);
+	if (data == NULL) {
+		fprintf(stderr, "memory alloc failure\n");
+		return BCME_NOMEM;
+	}
+
+	url = (wnm_url_t *) data;
+	url->len = datalen;
+	if (datalen > 0) {
+		memcpy(url->data, argv[1], datalen);
+	}
+
+	err = wlu_var_setbuf(wl, cmd->name, data, count);
+
+	free(data);
+	return (err);
+}
+
+static int
+wl_wnm_bss_select_table(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int ret;
+	char *endptr = NULL;
+	wnm_bss_select_factor_cfg_t *btcfg;
+	int btcfg_size = WNM_BSS_SELECT_FIXED_SIZE +
+		(sizeof(wnm_bss_select_factor_params_t) * BSS_MAXTABLE_SIZE);
+	int i;
+
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	/* minimum 2 argument required */
+	if ((argc < 2) || (argc / 3) > BSS_MAXTABLE_SIZE) {
+		return BCME_USAGE_ERROR;
+	}
+
+	/* invalid set argument */
+	if ((argc > 2) && ((argc - 1) % 3)) {
+		if ((((argc - 1) % 3) == 2) || (stricmp(argv[argc-1], "a") &&
+			stricmp(argv[argc-1], "b") &&	stricmp(argv[argc-1], "all"))) {
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	btcfg = (wnm_bss_select_factor_cfg_t *)malloc(btcfg_size);
+	if (btcfg == NULL) {
+		fprintf(stderr, "memory alloc failure\n");
+		return BCME_NOMEM;
+	}
+	memset(btcfg, 0, btcfg_size);
+
+	btcfg->version = WNM_BSS_SELECT_FACTOR_VERSION;
+	btcfg->band = WLC_BAND_AUTO;
+	btcfg->type = 0;
+	btcfg->count = 0;
+
+	/* First arg: type */
+	if (argc >= 2) {
+		if (!strcmp(argv[0], "rssi"))
+			btcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
+		else if (!strcmp(argv[0], "cu"))
+			btcfg->type = WNM_BSS_SELECT_TYPE_CU;
+		else {
+			free(btcfg);
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	/* Second arg: value or band */
+	for (i = 1; i < argc; i = i + 3) {
+		if (!stricmp(argv[i], "a")) {
+			btcfg->band = WLC_BAND_5G;
+			break;
+		} else if (!stricmp(argv[i], "b")) {
+			btcfg->band = WLC_BAND_2G;
+			break;
+		} else if (!stricmp(argv[i], "all")) {
+			btcfg->band = WLC_BAND_ALL;
+			break;
+		} else {
+			btcfg->params[i/3].low = strtol(argv[i+0], &endptr, 0);
+			if (*endptr != '\0') {
+				free(btcfg);
+				return BCME_USAGE_ERROR;
+			}
+
+			btcfg->params[i/3].high = strtol(argv[i+1], &endptr, 0);
+			if (*endptr != '\0') {
+				free(btcfg);
+				return BCME_USAGE_ERROR;
+			}
+
+			btcfg->params[i/3].factor = strtol(argv[i+2], &endptr, 0);
+			if (*endptr != '\0') {
+				free(btcfg);
+				return BCME_USAGE_ERROR;
+			}
+		}
+	}
+
+	/* number of elements */
+	btcfg->count = i / 3;
+
+	/* issue the get or set ioctl */
+	if ((argc == 2) && (btcfg->band != WLC_BAND_AUTO)) {
+		void *ptr = NULL;
+		if (btcfg->band == WLC_BAND_ALL) {
+			printf("band option \"all\" is for set only, not get\n");
+			free(btcfg);
+			return BCME_USAGE_ERROR;
+		}
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, btcfg, btcfg_size, &ptr)) < 0) {
+			free(btcfg);
+			return ret;
+		}
+
+		memcpy(btcfg, ptr, WNM_BSS_SELECT_FIXED_SIZE);
+
+		btcfg_size = WNM_BSS_SELECT_FIXED_SIZE +
+			(btcfg->count * sizeof(wnm_bss_select_factor_params_t));
+		memcpy(btcfg, ptr, btcfg_size);
+
+		printf("no of entries in table: %d\n", btcfg->count);
+		printf("%s factor table\n",
+			(btcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU");
+		printf("low\thigh\tfactor\n");
+		for (i = 0; i < btcfg->count; i++) {
+			printf("%d\t%d\t%d\n", btcfg->params[i].low,
+				btcfg->params[i].high, btcfg->params[i].factor);
+		}
+		printf("\n");
+	} else {
+		if (btcfg->band == WLC_BAND_AUTO) {
+			btcfg->band = WLC_BAND_ALL;
+		}
+
+		btcfg_size = WNM_BSS_SELECT_FIXED_SIZE +
+			(btcfg->count * sizeof(wnm_bss_select_factor_params_t));
+		ret = wlu_var_setbuf(wl, cmd->name, btcfg, btcfg_size);
+	}
+
+	free(btcfg);
+	return ret;
+}
+
+static int
+wl_wnm_bss_select_weight(void *wl, cmd_t *cmd, char **argv)
+{
+	int argc;
+	int ret;
+	char *endptr = NULL;
+	wnm_bss_select_weight_cfg_t bwcfg;
+
+	argv++;
+
+	/* arg count */
+	for (argc = 0; argv[argc]; argc++);
+
+	bwcfg.version = WNM_BSSLOAD_MONITOR_VERSION;
+	bwcfg.band = WLC_BAND_AUTO;
+	bwcfg.type = 0;
+	bwcfg.weight = 0;
+
+	/* minimum 2 argument required */
+	if (argc < 2) {
+		return BCME_USAGE_ERROR;
+	}
+
+	/* First arg: type */
+	if (argc >= 2) {
+		if (!strcmp(argv[0], "rssi"))
+			bwcfg.type = WNM_BSS_SELECT_TYPE_RSSI;
+		else if (!strcmp(argv[0], "cu"))
+			bwcfg.type = WNM_BSS_SELECT_TYPE_CU;
+		else
+			return BCME_USAGE_ERROR;
+	}
+
+	/* Second arg: value or band */
+	if (argc >= 2) {
+		if (!stricmp(argv[1], "a"))
+			bwcfg.band = WLC_BAND_5G;
+		else if (!stricmp(argv[1], "b"))
+			bwcfg.band = WLC_BAND_2G;
+		else if (!stricmp(argv[1], "all"))
+			bwcfg.band = WLC_BAND_ALL;
+		else {
+			bwcfg.weight = strtol(argv[1], &endptr, 0);
+			if (*endptr != '\0')
+				return BCME_USAGE_ERROR;
+		}
+	}
+
+	/* third arg: band */
+	if (argc >= 3) {
+		if (!stricmp(argv[2], "a"))
+			bwcfg.band = WLC_BAND_5G;
+		else if (!stricmp(argv[2], "b"))
+			bwcfg.band = WLC_BAND_2G;
+		else if (!stricmp(argv[2], "all"))
+			bwcfg.band = WLC_BAND_ALL;
+		else
+			return BCME_USAGE_ERROR;
+	}
+
+	/* issue the get or set ioctl */
+	if ((argc == 2) && (bwcfg.band != WLC_BAND_AUTO)) {
+		void *ptr = NULL;
+		if (bwcfg.band == WLC_BAND_ALL) {
+			printf("band option \"all\" is for set only, not get\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, &bwcfg, sizeof(bwcfg), &ptr)) < 0)
+			return ret;
+
+		memcpy(&bwcfg, ptr, sizeof(bwcfg));
+		printf("%s %s weight = %d\n",
+			(bwcfg.type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU",
+			(bwcfg.band == WLC_BAND_2G) ? "2G" : "5G", bwcfg.weight);
+	} else {
+		if (bwcfg.band == WLC_BAND_AUTO) {
+			bwcfg.band = WLC_BAND_ALL;
+		}
+		ret = wlu_var_setbuf(wl, cmd->name, &bwcfg, sizeof(bwcfg));
+	}
+
+	return ret;
+}
diff --git a/wl/src/wl/exe/wluc_wowl.c b/wl/src/wl/exe/wluc_wowl.c
new file mode 100644
index 0000000..c79ff61
--- /dev/null
+++ b/wl/src/wl/exe/wluc_wowl.c
@@ -0,0 +1,1177 @@
+/*
+ * wl wowl command module
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wluc_wowl.c 458728 2014-02-27 18:15:25Z $
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include <wlioctl.h>
+
+#if	defined(DONGLEBUILD)
+#include <typedefs.h>
+#include <osl.h>
+#endif
+
+/* Because IL_BIGENDIAN was removed there are few warnings that need
+ * to be fixed. Windows was not compiled earlier with IL_BIGENDIAN.
+ * Hence these warnings were not seen earlier.
+ * For now ignore the following warnings
+ */
+#ifdef WIN32
+#pragma warning(push)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4761)
+#endif
+
+#include <bcmutils.h>
+#include <bcmendian.h>
+#include "wlu_common.h"
+#include "wlu.h"
+
+static cmd_func_t wl_nshostip;
+static cmd_func_t wl_wowl_pattern, wl_wowl_wakeind, wl_wowl_pkt, wl_wowl_status;
+static cmd_func_t wl_wowl_wake_reason, wl_wowl_extended_magic, wl_wowl_radio_duty_cycle;
+static cmd_func_t wl_wowl_wog_appid;
+static cmd_func_t wl_wowl_wog_resp;
+
+static cmd_t wl_wowl_cmds[] = {
+	{ "ns_hostip", wl_nshostip, WLC_GET_VAR, WLC_SET_VAR,
+	"Add a ns-ip address or display then"},
+	{ "ns_hostip_clear", wl_var_void, -1, WLC_SET_VAR,
+	"Clear all ns-ip addresses"},
+	{ "wowl", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Enable/disable WOWL events\n"
+	"  0   - Clear all events\n"
+	"Bit 0 - Wakeup on Magic Packet\n"
+	"Bit 1 - Wakeup on NetPattern (use 'wl wowl_pattern' to configure pattern)\n"
+	"Bit 2 - Wakeup on loss-of-link due to Disassociation/Deauth\n"
+	"Bit 3 - Wakeup on retrograde tsf\n"
+	"Bit 4 - Wakeup on loss of beacon (use 'wl wowl_bcn_loss' to configure time)"},
+	{ "wowl_radio_duty_cycle", wl_wowl_radio_duty_cycle, -1, -1,
+	"usage: wowl_radio_duty_cycle [ wake interval , sleep interval]\n"
+	"No options -- lists existing power intervals\n"
+	"wake interval -- Time of radio on period in MS  \n"
+	"sleep interval -- Time of sleep period in MS "
+	},
+	{ "wowl_bcn_loss", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"Set #of seconds of beacon loss for wakeup event"},
+	{ "wowl_pattern", wl_wowl_pattern, -1, -1,
+	"usage: wowl_pattern [ [clr | [[ add | del ] offset mask value ]]]\n"
+	"No options -- lists existing pattern list\n"
+	"add -- Adds the pattern to the list\n"
+	"del -- Removes a pattern from the list\n"
+	"clr -- Clear current list\n"
+	"offset -- Starting offset for the pattern\n"
+	"mask -- Mask to be used for pattern. Bit i of mask => byte i of the pattern\n"
+	"value -- Value of the pattern"
+	},
+	{ "wowl_wakeind", wl_wowl_wakeind, WLC_GET_VAR, WLC_SET_VAR,
+	"usage: wowl_wakeind [clear]\n"
+	"Shows last system wakeup event indications from PCI and D11 cores\n"
+	"clear - Clear the indications"
+	},
+	{ "wowl_status", wl_wowl_status, WLC_GET_VAR, -1,
+	"usage: wowl_status [clear]\n"
+	"Shows last system wakeup setting"
+	},
+	{"wowl_pkt", wl_wowl_pkt, -1, -1,
+	"Send a wakeup frame to wakup a sleeping STA in WAKE mode\n"
+	"Usage: wl wowl_pkt <len> <dst ea | bcast | ucast <STA ea>>"
+	"[ magic [<STA ea>] | net <offset> <pattern> <reason code> ]\n"
+	"e.g. To send bcast magic frame -- "
+	"wl wowl_pkt 102 bcast magic 00:90:4c:AA:BB:CC\n"
+	"     To send ucast magic frame -- "
+	"wl wowl_pkt 102 ucast 00:90:4c:aa:bb:cc magic\n"
+	"     To send a frame with L2 unicast - "
+	"wl wowl_pkt 102 00:90:4c:aa:bb:cc net 0 0x00904caabbcc 0x03\n"
+	" NOTE: offset for netpattern frame starts from \"Dest EA\" of ethernet frame."
+	"So dest ea will be used only when offset is >= 6\n"
+	"     To send a eapol identity frame with L2 unicast - "
+	"wl wowl_pkt 102 00:90:4c:aa:bb:cc eapid id-string"},
+	{"wowl_ext_magic", wl_wowl_extended_magic, WLC_GET_VAR, WLC_SET_VAR,
+	"Set 6-byte extended magic pattern\n"
+	"Usage: wl wowl_ext_magic 0x112233445566"},
+	{ "wowl_wakeup_reason", wl_wowl_wake_reason, WLC_GET_VAR, -1 /* Set not reqd */,
+	"Returns pattern id and associated wakeup reason"},
+	{ "wowl_rls_wake_pkt", wl_var_void, -1, WLC_SET_VAR,
+	"Release packet that triggered the host wake up"},
+	{ "wowl_wog", wl_varint, WLC_GET_VAR, WLC_SET_VAR,
+	"WOG(Wake On Googlecast) on/off\n"
+	"Setting is available only under wowl mode deativated\n"
+	"\tUsage:\n\t wl wowl_wog [0|1]\n"},
+	{ "wowl_wog_appid", wl_wowl_wog_appid, WLC_GET_VAR, WLC_SET_VAR,
+	"App/Del/Clear/List Application IDs\n"
+	"\tUsage:\n\t wl wowl_wog_appid add <_APPID>\n"
+	"\t wl wowl_wog_appid del <_APPID>\n"
+	"\t wl wowl_wog_appid clear\n"
+	"\t wl wowl_wog_appid list\n"
+	"\t wl wowl_wog_appid maxcnt [max_appid_count]\n"
+	"\t\t max_appid_count > 1 and if maxcnt is changed AppId list will be cleared.\n"
+	"\t\t   if maxcnt is same with before, maxcnt won't be applied.\n"},
+	{ "wowl_wog_resp", wl_wowl_wog_resp, WLC_GET_VAR, WLC_SET_VAR,
+	"Set/Get Wake On Googlecast Response\n"
+	"\tUsage:\n\t wl wowl_wog_resp devname <devname>"
+	" ip <x.x.x.x> [ttl <ttl>]\n"
+	"\t    txt id <uuid> [ca <capability>] [st <receiver_status_flag>] "
+	"[ve <version>] [md <model_name>]\n"
+	"\t       [pk <public_key>] [fn <friendly_name>] "
+	"[rs <receiver_status>] [ttl <txt_ttl>]\n"
+	"\t    [srv port <port> [ttl <srv_ttl>]]\n"
+	"\t    [a ttl]\n"
+	"\n\t wl wowl_wog_resp show\n\n"},
+	{ NULL, NULL, 0, 0, NULL }
+};
+
+static char *buf;
+
+/* module initialization */
+void
+wluc_wowl_module_init(void)
+{
+	/* get the global buf */
+	buf = wl_get_buf();
+
+	/* register wowl commands */
+	wl_module_cmds_register(wl_wowl_cmds);
+}
+
+/*
+ * If a host IP address is given, add it to the host-cache,
+ * e.g. "wl nd_hostip fe00:0:0:0:0:290:1fc0:18c0 ".
+ * If no address is given, dump all the addresses.
+ */
+static int
+wl_nshostip(void *wl, cmd_t *cmd, char **argv)
+{
+
+	int ret = 0, i;
+	struct ipv6_addr ipa_set, *ipa_get, null_ipa;
+	uint16 *ip_addr;
+	if (!*++argv) {
+		/* Get */
+		void *ptr = NULL;
+
+		if ((ret = wlu_var_getbuf(wl, cmd->name, NULL, 0, &ptr)) < 0)
+			return ret;
+		ip_addr = (uint16*)ptr;
+		memset(null_ipa.addr, 0, IPV6_ADDR_LEN);
+		for (ipa_get = (struct ipv6_addr *)ptr;
+			memcmp(null_ipa.addr, ipa_get->addr, IPV6_ADDR_LEN) != 0;
+			ipa_get++) {
+				/* Print ipv6 Addr */
+				for (i = 0; i < 8; i++)
+				{
+					printf("%x", ntoh16(ip_addr[i]));
+					if (i < 7)
+						printf(":");
+				}
+			}
+			printf("\r\n");
+			ip_addr += 8;
+		}
+	else {
+		/* Add */
+		if (!wl_atoipv6(*argv, &ipa_set))
+			return -1;
+		/* we add one ip-addr at a time */
+		return wlu_var_setbuf(wl, cmd->name,
+		&ipa_set, IPV6_ADDR_LEN);
+		}
+	return ret;
+}
+
+static int
+wl_wowl_status(void *wl, cmd_t *cmd, char **argv)
+{
+	int flags_prev = 0;
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	if ((err = wlu_iovar_getint(wl, "wowl_status", &flags_prev)))
+		return err;
+
+	printf("Status of last wakeup:\n");
+	printf("\tflags:0x%x\n", flags_prev);
+
+	if (flags_prev & WL_WOWL_BCN)
+		printf("\t\tWake-on-Loss-of-Beacons enabled\n");
+
+	if (flags_prev & WL_WOWL_MAGIC)
+		printf("\t\tWake-on-Magic frame enabled\n");
+	if (flags_prev & WL_WOWL_NET)
+		printf("\t\tWake-on-Net pattern enabled\n");
+	if (flags_prev & WL_WOWL_DIS)
+		printf("\t\tWake-on-Deauth enabled\n");
+
+	if (flags_prev & WL_WOWL_RETR)
+		printf("\t\tRetrograde TSF enabled\n");
+	if (flags_prev & WL_WOWL_TST)
+		printf("\t\tTest-mode enabled\n");
+
+	printf("\n");
+
+	return 0;
+}
+
+static int
+wl_wowl_wakeind(void *wl, cmd_t *cmd, char **argv)
+{
+	wl_wowl_wakeind_t wake = {0, 0};
+	int err;
+
+	UNUSED_PARAMETER(cmd);
+
+	argv++;
+
+	if (*argv) {
+		if (strcmp(*argv, "clear"))
+			return BCME_USAGE_ERROR;
+		memset(&wake, 0, sizeof(wake));
+		memcpy(&wake, *argv, strlen("clear"));
+		err = wlu_iovar_set(wl, "wowl_wakeind", &wake, sizeof(wl_wowl_wakeind_t));
+		return err;
+	}
+
+	if ((err = wlu_iovar_get(wl, "wowl_wakeind", &wake, sizeof(wl_wowl_wakeind_t))) < 0)
+		return err;
+
+	if (wake.pci_wakeind)
+		printf("PCI Indication set\n");
+	wake.ucode_wakeind = dtoh32(wake.ucode_wakeind);
+	if (wake.ucode_wakeind != 0) {
+		printf("MAC Indication set\n");
+
+		if ((wake.ucode_wakeind & WL_WOWL_MAGIC) == WL_WOWL_MAGIC)
+			printf("\tMAGIC packet received\n");
+		if ((wake.ucode_wakeind & WL_WOWL_NET) == WL_WOWL_NET)
+			printf("\tPacket received with Netpattern\n");
+		if ((wake.ucode_wakeind & WL_WOWL_DIS) == WL_WOWL_DIS)
+			printf("\tDisassociation/Deauth received\n");
+		if ((wake.ucode_wakeind & WL_WOWL_RETR) == WL_WOWL_RETR)
+			printf("\tRetrograde TSF detected\n");
+		if ((wake.ucode_wakeind & WL_WOWL_BCN) == WL_WOWL_BCN)
+			printf("\tBeacons Lost\n");
+		if ((wake.ucode_wakeind & WL_WOWL_TST) == WL_WOWL_TST)
+			printf("\tTest Mode\n");
+		if ((wake.ucode_wakeind & WL_WOWL_M1) == WL_WOWL_M1)
+			printf("\tPTK Refresh received.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_EAPID) == WL_WOWL_EAPID)
+			printf("\tEAP-Identity request received\n");
+		if ((wake.ucode_wakeind & WL_WOWL_GTK_FAILURE) == WL_WOWL_GTK_FAILURE)
+			printf("\tWake on GTK failure.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_EXTMAGPAT) == WL_WOWL_EXTMAGPAT)
+			printf("\tExtended Magic Packet received.\n");
+		if ((wake.ucode_wakeind & WL_WOWL_KEYROT) == WL_WOWL_KEYROT)
+			printf("\tKey Rotation Packet received.\n");
+		if ((wake.ucode_wakeind & (WL_WOWL_NET | WL_WOWL_MAGIC | WL_WOWL_EXTMAGPAT))) {
+			if ((wake.ucode_wakeind & WL_WOWL_BCAST) == WL_WOWL_BCAST)
+				printf("\t\tBroadcast/Mcast frame received\n");
+			else
+				printf("\t\tUnicast frame received\n");
+		}
+	}
+
+	if (!wake.pci_wakeind && wake.ucode_wakeind == 0)
+		printf("No wakeup indication set\n");
+
+	return 0;
+}
+/* Used by NINTENDO2 */
+static int
+wl_wowl_wake_reason(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = -1;
+	wl_wr_t wr;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv) {
+		err = wlu_iovar_get(wl, "wakeup_reason", &wr, sizeof(wl_wr_t));
+		if (err)
+			return err;
+
+		if (wr.reason && wr.reason < REASON_LAST) {
+			printf("ID: %d\t", wr.id);
+
+			if (wr.reason == LCD_ON)
+			printf("Reason: LCD_ON\n");
+			else if (wr.reason == LCD_OFF)
+			printf("Reason: LCD_OFF\n");
+			else if (wr.reason == DRC1_WAKE)
+			printf("Reason: DRC1_WAKE\n");
+			else if (wr.reason == DRC2_WAKE)
+			printf("Reason: DRC2_WAKE\n");
+		}
+		else
+			printf("Unknown wakeup Reason\n");
+	}
+		return err;
+}
+
+/* Send a wakeup frame to sta in WAKE mode */
+static int
+wl_wowl_pkt(void *wl, cmd_t *cmd, char **argv)
+{
+	char *arg = buf;
+	const char *str;
+	char *dst;
+	uint tot = 0;
+	uint16 type, pkt_len;
+	int dst_ea = 0; /* 0 == manual, 1 == bcast, 2 == ucast */
+	char *ea[ETHER_ADDR_LEN];
+	if (!*++argv)
+		return BCME_USAGE_ERROR;
+
+	UNUSED_PARAMETER(cmd);
+
+	str = "wowl_pkt";
+	strncpy(arg, str, strlen(str));
+	arg[strlen(str)] = '\0';
+	dst = arg + strlen(str) + 1;
+	tot += strlen(str) + 1;
+
+	pkt_len = (uint16)htod32(strtoul(*argv, NULL, 0));
+
+	*((uint16*)dst) = pkt_len;
+
+	dst += sizeof(pkt_len);
+	tot += sizeof(pkt_len);
+
+	if (!*++argv) {
+		printf("Dest of the packet needs to be provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	/* Dest of the frame */
+	if (!strcmp(*argv, "bcast")) {
+		dst_ea = 1;
+		if (!wl_ether_atoe("ff:ff:ff:ff:ff:ff", (struct ether_addr *)dst))
+			return BCME_USAGE_ERROR;
+	} else if (!strcmp(*argv, "ucast")) {
+		dst_ea = 2;
+		if (!*++argv) {
+			printf("EA of ucast dest of the packet needs to be provided\n");
+			return BCME_USAGE_ERROR;
+		}
+		if (!wl_ether_atoe(*argv, (struct ether_addr *)dst))
+			return BCME_USAGE_ERROR;
+		/* Store it */
+		memcpy(ea, dst, ETHER_ADDR_LEN);
+	} else if (!wl_ether_atoe(*argv, (struct ether_addr *)dst))
+		return BCME_USAGE_ERROR;
+
+	dst += ETHER_ADDR_LEN;
+	tot += ETHER_ADDR_LEN;
+
+	if (!*++argv) {
+		printf("type - magic/net needs to be provided\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (strncmp(*argv, "magic", strlen("magic")) == 0)
+		type = WL_WOWL_MAGIC;
+	else if (strncmp(*argv, "net", strlen("net")) == 0)
+		type = WL_WOWL_NET;
+	else if (strncmp(*argv, "eapid", strlen("eapid")) == 0)
+		type = WL_WOWL_EAPID;
+	else
+		return BCME_USAGE_ERROR;
+
+	*((uint16*)dst) = type;
+	dst += sizeof(type);
+	tot += sizeof(type);
+
+	if (type == WL_WOWL_MAGIC) {
+		if (pkt_len < MAGIC_PKT_MINLEN)
+			return BCME_BADARG;
+
+		if (dst_ea == 2)
+			memcpy(dst, ea, ETHER_ADDR_LEN);
+		else {
+			if (!*++argv)
+				return BCME_USAGE_ERROR;
+
+			if (!wl_ether_atoe(*argv, (struct ether_addr *)dst))
+				return BCME_USAGE_ERROR;
+		}
+		tot += ETHER_ADDR_LEN;
+	} else if (type == WL_WOWL_NET) {
+		wl_wowl_pattern_t *wl_pattern;
+		wl_pattern = (wl_wowl_pattern_t *)dst;
+
+		if (!*++argv) {
+			printf("Starting offset not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		wl_pattern->offset = (uint)htod32(strtoul(*argv, NULL, 0));
+
+		wl_pattern->masksize = 0;
+
+		wl_pattern->patternoffset = (uint)htod32(sizeof(wl_wowl_pattern_t));
+
+		dst += sizeof(wl_wowl_pattern_t);
+
+		if (!*++argv) {
+			printf("pattern not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		wl_pattern->patternsize =
+		        (uint)htod32(wl_pattern_atoh((char *)(uintptr)*argv, dst));
+		dst += wl_pattern->patternsize;
+		tot += sizeof(wl_wowl_pattern_t) + wl_pattern->patternsize;
+
+		wl_pattern->reasonsize = 0;
+		if (*++argv) {
+			wl_pattern->reasonsize =
+				(uint)htod32(wl_pattern_atoh((char *)(uintptr)*argv, dst));
+			tot += wl_pattern->reasonsize;
+		}
+	} else {	/* eapid */
+		if (!*++argv) {
+			printf("EAPOL identity string not provided\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		*dst++ = strlen(*argv);
+		strncpy(dst, *argv, strlen(*argv));
+		tot += 1 + strlen(*argv);
+	}
+	return (wlu_set(wl, WLC_SET_VAR, arg, tot));
+}
+
+static int
+wl_wowl_pattern(void *wl, cmd_t *cmd, char **argv)
+{
+	int err;
+	uint i, j;
+	uint8 *ptr;
+	wl_wowl_pattern_t *wl_pattern;
+
+	UNUSED_PARAMETER(cmd);
+
+	if (*++argv) {
+		char *arg = buf;
+		const char *str;
+		char *dst;
+		uint tot = 0;
+
+		if (strcmp(*argv, "add") != 0 && strcmp(*argv, "del") != 0 &&
+		    strcmp(*argv, "clr") != 0) {
+			return BCME_USAGE_ERROR;
+		}
+
+		str = "wowl_pattern";
+		strncpy(arg, str, strlen(str));
+		arg[strlen(str)] = '\0';
+		dst = arg + strlen(str) + 1;
+		tot += strlen(str) + 1;
+
+		str = *argv;
+		strncpy(dst, str, strlen(str));
+		tot += strlen(str) + 1;
+
+		if (strcmp(str, "clr") != 0) {
+			wl_pattern = (wl_wowl_pattern_t *)(dst + strlen(str) + 1);
+			dst = (char*)wl_pattern + sizeof(wl_wowl_pattern_t);
+			if (!*++argv) {
+				printf("Starting offset not provided\n");
+				return BCME_USAGE_ERROR;
+			}
+			wl_pattern->offset = htod32(strtoul(*argv, NULL, 0));
+			if (!*++argv) {
+				printf("Mask not provided\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			/* Parse the mask */
+			str = *argv;
+			wl_pattern->masksize = htod32(wl_pattern_atoh((char *)(uintptr)str, dst));
+			if (wl_pattern->masksize == (uint)-1)
+				return BCME_USAGE_ERROR;
+
+			dst += wl_pattern->masksize;
+			wl_pattern->patternoffset = htod32((sizeof(wl_wowl_pattern_t) +
+			                                    wl_pattern->masksize));
+
+			if (!*++argv) {
+				printf("Pattern value not provided\n");
+				return BCME_USAGE_ERROR;
+			}
+
+			/* Parse the value */
+			str = *argv;
+			wl_pattern->patternsize =
+			        htod32(wl_pattern_atoh((char *)(uintptr)str, dst));
+			if (wl_pattern->patternsize == (uint)-1)
+				return BCME_USAGE_ERROR;
+			tot += sizeof(wl_wowl_pattern_t) + wl_pattern->patternsize +
+			        wl_pattern->masksize;
+		}
+
+		return (wlu_set(wl, WLC_SET_VAR, arg, tot));
+	} else {
+		wl_wowl_pattern_list_t *list;
+		if ((err = wlu_iovar_get(wl, "wowl_pattern", buf, WLC_IOCTL_MAXLEN)) < 0)
+			return err;
+		list = (wl_wowl_pattern_list_t *)buf;
+		printf("#of patterns :%d\n", list->count);
+		ptr = (uint8 *)list->pattern;
+		for (i = 0; i < list->count; i++) {
+			uint8 *pattern;
+
+			wl_pattern = (wl_wowl_pattern_t *)ptr;
+			printf("Pattern %d:\n", i+1);
+			printf("ID         :0x%x\n"
+				"Offset     :%d\n"
+				"Masksize   :%d\n"
+				"Mask       :0x",
+				(uint32)wl_pattern->id, wl_pattern->offset, wl_pattern->masksize);
+			pattern = ((uint8 *)wl_pattern + sizeof(wl_wowl_pattern_t));
+			for (j = 0; j < wl_pattern->masksize; j++)
+				printf("%02x", pattern[j]);
+			printf("\n"
+			       "PatternSize:%d\n"
+			       "Pattern    :0x", wl_pattern->patternsize);
+			/* Go to end to find pattern */
+			pattern = ((uint8*)wl_pattern + wl_pattern->patternoffset);
+			for (j = 0; j < wl_pattern->patternsize; j++)
+				printf("%02x", pattern[j]);
+			printf("\n\n");
+			ptr += (wl_pattern->masksize + wl_pattern->patternsize +
+			        sizeof(wl_wowl_pattern_t));
+		}
+	}
+
+	return err;
+}
+
+
+static int
+wl_wowl_radio_duty_cycle(void *wl, cmd_t *cmd, char **argv)
+{
+	int err = 0;
+	char *endptr = NULL;
+	int argc;
+	wowl_radio_duty_cycle_t cfg;
+
+	UNUSED_PARAMETER(cmd);
+
+	for (argc = 0; argv[argc]; argc++);
+	argc--;
+
+	if (argc != 0 && argc != 2) {
+		printf("required args: wake interval and sleep interval\n");
+		return BCME_USAGE_ERROR;
+	}
+
+	if (argc == 0)
+	{
+		err = wl_var_get(wl, cmd, argv);
+		if (err < 0)
+			return err;
+		printf(" wake interval =%d ms\n sleep interval = %d ms\n",
+		   ((wowl_radio_duty_cycle_t*)buf)->wake_interval,
+		   ((wowl_radio_duty_cycle_t*)buf)->sleep_interval);
+	}
+	else
+	{
+		cfg.wake_interval = htod16((uint16)(strtoul(argv[1], &endptr, 0)));
+		cfg.sleep_interval = htod16((uint16)(strtoul(argv[2], &endptr, 0)));
+		err = wlu_var_setbuf(wl, cmd->name, &cfg, sizeof(wowl_radio_duty_cycle_t));
+		printf(" wake interval = %d ms\n sleep interval = %d ms\n",
+			cfg.wake_interval, cfg.sleep_interval);
+	}
+
+	return err;
+
+}
+
+static int
+wl_wowl_extended_magic(void *wl, cmd_t *cmd, char **argv)
+{
+	char *arg = buf;
+	const char *str;
+	char *dst;
+	uint tot;
+	int ret;
+
+	str = "wowl_ext_magic";
+	strncpy(arg, str, strlen(str));
+	arg[strlen(str)] = '\0';
+
+	if (*++argv) {
+		dst = arg + strlen(str) + 1;
+		tot = strlen(str) + 1;
+		ret = wl_pattern_atoh(*argv, dst);
+		if (ret == -1)
+			return BCME_USAGE_ERROR;
+		if (ret != 6) {
+			printf("Extended magic pattern must be 6-byte length\n");
+			return BCME_USAGE_ERROR;
+		}
+		tot += 6;
+
+		ret = wlu_set(wl, cmd->set, arg, tot);
+		return ret;
+	}
+
+
+	if ((ret = wlu_get(wl, cmd->get, arg, WLC_IOCTL_MAXLEN)) < 0)
+		return ret;
+
+	printf("0x");
+	for (ret = 0; ret < 6; ret++)
+		printf("%02x", (uint8)arg[ret]);
+	printf("\n");
+
+	return 0;
+
+}
+
+static int
+wl_wowl_wog_appid(void *wl, cmd_t *cmd, char **argv)
+{
+	wog_appid_iov_t *wog_appid;
+	char *appid, *command;
+	uint len;
+	int ret = BCME_OK;
+
+	if (!*++argv) {
+		return BCME_USAGE_ERROR;
+	}
+
+	wog_appid = (wog_appid_iov_t *)malloc(sizeof(*wog_appid));
+
+	if (wog_appid == NULL) {
+		return BCME_NOMEM;
+	}
+
+	memset(wog_appid, 0, sizeof(*wog_appid));
+
+	wog_appid->ver = htod32(WOG_APPID_IOV_VER);
+
+	command = *argv;
+	if (!strncmp(command, "add", 4) || !strncmp(command, "del", 4)) {
+		appid = *++argv;
+
+		if (!appid) {
+			ret = BCME_USAGE_ERROR;
+			goto EXIT;
+		}
+
+		len = strlen(appid);
+
+		if (!len || appid[0] != '_') {
+			printf("Appid should start with '_'\n");
+			ret = BCME_USAGE_ERROR;
+			goto EXIT;
+		}
+
+		wog_appid->cnt = htod32(1);
+		wog_appid->operation = (!strncmp(command, "add", 4))? htod32(WOG_APPID_ADD) :
+			htod32(WOG_APPID_DEL);
+		if (len > MAX_DNS_LABEL) {
+			len = MAX_DNS_LABEL;
+		}
+		memcpy(wog_appid->appids[0].appID, appid, len);
+		wog_appid->appids[0].appID[len] = 0;
+		ret = wlu_iovar_set(wl, cmd->name, wog_appid, sizeof(*wog_appid));
+	} else if (!strncmp(command, "clear", 6)) {
+		wog_appid->operation = htod32(WOG_APPID_CLEAR);
+		ret = wlu_iovar_set(wl, cmd->name, wog_appid, sizeof(*wog_appid));
+	} else if (!strncmp(command, "list", 5)) {
+		wog_appid_iov_t *list;
+		uint i;
+
+		wog_appid->operation = htod32(WOG_APPID_LIST);
+		ret = wlu_iovar_getbuf(wl, cmd->name, wog_appid, sizeof(*wog_appid),
+			buf, WLC_IOCTL_MAXLEN);
+		if (ret != BCME_OK) {
+			goto EXIT;
+		}
+
+		list = (wog_appid_iov_t *)buf;
+		list->cnt = dtoh32(list->cnt);
+		printf("AppID count : %d\n", list->cnt);
+		for (i = 0; i < list->cnt; i++) {
+			printf("AppID[%d]=%s\n", i, list->appids[i].appID);
+		}
+	} else if (!strncmp(command, "maxcnt", 7)) {
+		int max_count;
+
+		wog_appid->operation = htod32(WOG_MAX_APPID_CNT);
+
+		argv++;
+		if (*argv) {
+			max_count = atoi(*argv);
+			if (max_count < 1) {
+				printf("Maximum AppID count should be greater than 0\n");
+				ret = BCME_USAGE_ERROR;
+				goto EXIT;
+			}
+			wog_appid->cnt = htod32(max_count);
+			ret = wlu_iovar_set(wl, cmd->name, wog_appid, sizeof(*wog_appid));
+		} else {
+			wog_appid_iov_t *appid;
+			ret = wlu_iovar_getbuf(wl, cmd->name, wog_appid, sizeof(*wog_appid),
+				buf, WLC_IOCTL_SMLEN);
+			if (ret != BCME_OK) {
+				goto EXIT;
+			}
+
+			appid = (wog_appid_iov_t *)buf;
+			appid->cnt = dtoh32(appid->cnt);
+			printf("Maximum AppID count : %d\n", appid->cnt);
+		}
+	} else {
+		ret = BCME_USAGE_ERROR;
+	}
+
+EXIT:
+	if (wog_appid) {
+		free(wog_appid);
+	}
+	return ret;
+}
+
+#define WOG_RESP_MAX_CMD_LEN 11
+#define WOG_RESP_MAX_SUBCMD 10
+typedef struct wowl_wog_resp_subcmd {
+	int mandatory;
+	char subname[WOG_RESP_MAX_CMD_LEN + 1];
+} wowl_wog_resp_subcmd_t;
+
+#define WOG_CMD_DEVNAME 0
+#define WOG_CMD_IP 1
+#define WOG_CMD_TTL 2
+#define WOG_CMD_TXT 3
+#define WOG_CMD_SRV 4
+#define WOG_CMD_A 5
+
+#define WOG_SUBCMD_TXT_ID 0
+#define WOG_SUBCMD_TXT_CA 1
+#define WOG_SUBCMD_TXT_ST 2
+#define WOG_SUBCMD_TXT_VE 3
+#define WOG_SUBCMD_TXT_MD 4
+#define WOG_SUBCMD_TXT_PK 5
+#define WOG_SUBCMD_TXT_FN 6
+#define WOG_SUBCMD_TXT_RS 7
+#define WOG_SUBCMD_TXT_TTL 8
+
+#define WOG_SUBCMD_SRV_PORT 0
+#define WOG_SUBCMD_SRV_TTL 1
+
+#define WOG_SUBCMD_A_TTL 0
+
+typedef struct wowl_wog_resp_cmd {
+	int mandatory;
+	char cname[WOG_RESP_MAX_CMD_LEN + 1];
+	int subcnt;
+	wowl_wog_resp_subcmd_t subcmd[WOG_RESP_MAX_SUBCMD];
+} wowl_wog_resp_cmd_t;
+
+const wowl_wog_resp_cmd_t wog_resp_cmdlist[] = {
+	{1, "devname", 0, {{0, {0, }}, }},
+	{1, "ip", 0, {{0, {0, }}, }},
+	{0, "ttl", 0, {{0, {0, }}, }},
+	{1, "txt", 9,
+	{{1, "id"}, {0, "ca"}, {0, "st"}, {0, "ve"}, {0, "md"},
+	{0, "pk"}, {0, "fn"}, {0, "rs"}, {0, "ttl"}, }
+	},
+	{0, "srv", 2, {{1, "port"}, {0, "ttl"}, }},
+	{0, "a", 1, {{1, "ttl"}, }}
+};
+
+static int
+wl_wowl_wog_parse_txt(char ***argv, wog_sd_resp_t *resp,
+	int subcnt, wowl_wog_resp_subcmd_t *sublist)
+{
+	int ret = BCME_OK;
+	int subidx;
+	int i;
+	int val;
+	char *stop;
+
+	while (**argv) {
+		subidx = -1;
+		for (i = 0; i < subcnt; i++) {
+			if (!strncmp(**argv, sublist[i].subname,
+				WOG_RESP_MAX_CMD_LEN + 1)) {
+				subidx = i;
+				break;
+			}
+		}
+
+		/* Toss cmd to upper layer */
+		if (subidx < 0) {
+			goto EXIT;
+		}
+
+		if (!*++*argv) {
+			printf("no subparam for txt record.\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		switch (subidx) {
+		case WOG_SUBCMD_TXT_ID:
+			strncpy(resp->txt.id, **argv, GCAST_UUID_LEN);
+			resp->txt.id[GCAST_UUID_LEN] = 0;
+			break;
+		case WOG_SUBCMD_TXT_CA:
+			val = strtoul(**argv, &stop, 16);
+			if (val > 0x0f ||
+				(!val && stop == **argv)) {
+				printf("TXT capability should be 0 to f and hex value\n");
+				return BCME_BADARG;
+			}
+			resp->txt.capability = ***argv;
+			break;
+		case WOG_SUBCMD_TXT_ST:
+			val = strtoul(**argv, NULL, 16);
+			if ((val != 0) && (val != 1)) {
+				printf("TXT receiver_status_flag should be 0 or 1\n");
+				return BCME_BADARG;
+			}
+			resp->txt.receiver_status_flag = ***argv;
+			break;
+		case WOG_SUBCMD_TXT_VE:
+			val = strtoul(**argv, NULL, 16);
+			if (val < 2 || val > 255) {
+				printf("TXT version >= 2 && version <= 255\n");
+				return BCME_BADARG;
+			}
+			snprintf(resp->txt.ver, GCAST_VER_LEN + 1, "%02x", val);
+			break;
+		case WOG_SUBCMD_TXT_MD:
+			strncpy(resp->txt.model_name, **argv, GCAST_MAX_MODEL_NAME_LEN);
+			resp->txt.model_name[GCAST_MAX_MODEL_NAME_LEN] = 0;
+			break;
+		case WOG_SUBCMD_TXT_PK:
+			strncpy(resp->txt.public_key, **argv, GCAST_PUBLICKEY_ID_LEN);
+			resp->txt.public_key[GCAST_PUBLICKEY_ID_LEN] = 0;
+			break;
+		case WOG_SUBCMD_TXT_FN:
+			strncpy(resp->txt.friendly_name, **argv, GCAST_MAX_FNAME_LEN);
+			resp->txt.friendly_name[GCAST_MAX_FNAME_LEN] = 0;
+			break;
+		case WOG_SUBCMD_TXT_RS:
+			strncpy(resp->txt.receiver_status, **argv, GCAST_MAX_RS_LEN);
+			resp->txt.receiver_status[GCAST_MAX_RS_LEN] = 0;
+			break;
+		case WOG_SUBCMD_TXT_TTL:
+			val = atoi(**argv);
+			if (val <= 0) {
+				printf("TXT ttl > 0\n");
+				return BCME_BADARG;
+			}
+			resp->txt.ttl = htod32(val);
+			break;
+		}
+
+		sublist[subidx].mandatory = 0;
+		++*argv;
+	}
+
+
+EXIT:
+	--*argv; /* rewind for upper layer */
+
+	for (i = 0; i < subcnt; i++) {
+		if (sublist[i].mandatory) {
+			return BCME_USAGE_ERROR;
+		}
+	}
+	return ret;
+}
+
+static int
+wl_wowl_wog_parse_srv(char ***argv, wog_sd_resp_t *resp,
+	int subcnt, wowl_wog_resp_subcmd_t *sublist)
+{
+	int ret = BCME_OK;
+	int subidx;
+	int i, val;
+
+	while (**argv) {
+		subidx = -1;
+		for (i = 0; i < subcnt; i++) {
+			if (!strncmp(**argv, sublist[i].subname,
+				WOG_RESP_MAX_CMD_LEN + 1)) {
+				subidx = i;
+				break;
+			}
+		}
+
+		/* Toss cmd to upper layer */
+		if (subidx < 0) {
+			goto EXIT;
+		}
+
+		if (!*++*argv) {
+			printf("no subparam for SRV record.\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		switch (subidx) {
+		case WOG_SUBCMD_SRV_PORT:
+			val = atoi(**argv);
+			if (val <= 0 || val > 0xffff) {
+				printf("SRV port : 0 < port && port <= 0xffff\n");
+				return BCME_BADARG;
+			}
+			resp->srv.port = htod16(val);
+			break;
+		case WOG_SUBCMD_SRV_TTL:
+			val = atoi(**argv);
+			if (val <= 0) {
+				printf("SRV ttl > 0\n");
+				return BCME_BADARG;
+			}
+			resp->srv.ttl = htod32(val);
+			break;
+		}
+
+		sublist[subidx].mandatory = 0;
+		++*argv;
+	}
+
+EXIT:
+	--*argv; /* rewind for upper layer */
+
+	for (i = 0; i < subcnt; i++) {
+		if (sublist[i].mandatory) {
+			printf("No input for srv port or ttl\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+
+	return ret;
+}
+
+static int
+wl_wowl_wog_parse_a(char ***argv, wog_sd_resp_t *resp,
+	int subcnt, wowl_wog_resp_subcmd_t *sublist)
+{
+	int ret = BCME_OK;
+	int subidx;
+	int i, val;
+
+	while (**argv) {
+		subidx = -1;
+		for (i = 0; i < subcnt; i++) {
+			if (!strncmp(**argv, sublist[i].subname,
+				WOG_RESP_MAX_CMD_LEN + 1)) {
+				subidx = i;
+				break;
+			}
+		}
+
+		/* Toss cmd to upper layer */
+		if (subidx < 0) {
+			goto EXIT;
+		}
+
+		if (!*++*argv) {
+			printf("no subparam for A record.\n");
+			return BCME_USAGE_ERROR;
+		}
+
+		switch (subidx) {
+		case WOG_SUBCMD_A_TTL:
+			val = atoi(**argv);
+			if (val <= 0) {
+				printf("A ttl > 0\n");
+				return BCME_BADARG;
+			}
+
+			resp->a.ttl = htod32(val);
+			break;
+		}
+
+		sublist[subidx].mandatory = 0;
+		++*argv;
+	}
+
+EXIT:
+	--*argv; /* rewind for upper layer */
+
+	for (i = 0; i < subcnt; i++) {
+		if (sublist[i].mandatory) {
+			printf("No input for a ttl\n");
+			return BCME_USAGE_ERROR;
+		}
+	}
+	return ret;
+}
+
+static int
+wl_wowl_wog_resp(void *wl, cmd_t *cmd, char **argv)
+{
+	wog_sd_resp_t *resp = NULL;
+	int ret = BCME_OK;
+	int cmdcnt;
+	int cmdidx;
+	int i, val;
+	struct ipv4_addr ip;
+	wowl_wog_resp_cmd_t *cmdlist = NULL;
+
+	UNUSED_PARAMETER(wl);
+	UNUSED_PARAMETER(cmd);
+
+	if (!*++argv) {
+		return BCME_USAGE_ERROR;
+	}
+
+	resp = (wog_sd_resp_t *)malloc(sizeof(*resp));
+	cmdlist = (wowl_wog_resp_cmd_t *)malloc(sizeof(wog_resp_cmdlist));
+
+	if (!resp || !cmdlist) {
+		ret = BCME_NOMEM;
+		goto EXIT;
+	}
+
+	memset(resp, 0, sizeof(*resp));
+	memcpy(cmdlist, wog_resp_cmdlist, sizeof(wog_resp_cmdlist));
+	cmdcnt = sizeof(wog_resp_cmdlist)/sizeof(wowl_wog_resp_cmd_t);
+
+	resp->ver = WOG_SD_RESP_VER;
+
+	if (!strncmp(*argv, "show", 5)) {
+		wog_sd_resp_t *r;
+		ret = wlu_iovar_getbuf(wl, cmd->name, NULL, 0, buf, WLC_IOCTL_MAXLEN);
+		if (ret != BCME_OK) {
+			goto EXIT;
+		}
+
+		r = (wog_sd_resp_t *)buf;
+
+		if (r->ver != WOG_SD_RESP_VER) {
+			ret = BCME_VERSION;
+			goto EXIT;
+		}
+
+		printf("device name=%s\n"
+			"ip=%d.%d.%d.%d, answer ttl=%d\n"
+			"txt id=%s, capability=%c, receiver_status_flag=%c, "
+			"version=%s, model_name=%s, public_key=%s, "
+			"friendly_name=%s, receiver_status=%s, txt ttl=%d\n"
+			"srv port=%d, srv ttl=%d\n"
+			"a ttl=%d\n",
+			r->device_name,
+			r->ip[0], r->ip[1], r->ip[2], r->ip[3],
+			dtoh32(r->ptr_ttl),
+			r->txt.id, r->txt.capability, r->txt.receiver_status_flag,
+			r->txt.ver, r->txt.model_name, r->txt.public_key,
+			r->txt.friendly_name, r->txt.receiver_status,
+			dtoh32(r->txt.ttl),
+			dtoh16(r->srv.port), dtoh32(r->srv.ttl),
+			dtoh32(r->a.ttl));
+		goto EXIT;
+	}
+
+	while (*argv) {
+		cmdidx = -1;
+		for (i = 0; i < cmdcnt; i++) {
+			if (!strncmp(*argv, cmdlist[i].cname,
+				WOG_RESP_MAX_CMD_LEN + 1)) {
+				cmdidx = i;
+				break;
+			}
+		}
+
+		if (cmdidx < 0 || !*++argv) {
+			ret = BCME_USAGE_ERROR;
+			goto EXIT;
+		}
+
+		switch (cmdidx) {
+		case WOG_CMD_DEVNAME:
+			strncpy(resp->device_name, *argv, MAX_DNS_LABEL);
+			resp->device_name[MAX_DNS_LABEL] = 0;
+			break;
+		case WOG_CMD_IP:
+			if (!wl_atoip(*argv, &ip)) {
+				ret = BCME_USAGE_ERROR;
+				goto EXIT;
+			}
+			memcpy(resp->ip, ip.addr, IPV4_ADDR_LEN);
+			break;
+		case WOG_CMD_TTL:
+			val = atoi(*argv);
+			if (val <= 0) {
+				printf("PTR ttl > 0\n");
+				ret = BCME_BADARG;
+				goto EXIT;
+			}
+			resp->ptr_ttl = htod32(val);
+			break;
+		case WOG_CMD_TXT:
+			if (wl_wowl_wog_parse_txt(&argv, resp,
+				cmdlist[WOG_CMD_TXT].subcnt,
+				cmdlist[WOG_CMD_TXT].subcmd) != BCME_OK) {
+				ret = BCME_USAGE_ERROR;
+				goto EXIT;
+			}
+			break;
+		case WOG_CMD_SRV:
+			if (wl_wowl_wog_parse_srv(&argv, resp,
+				cmdlist[WOG_CMD_SRV].subcnt,
+				cmdlist[WOG_CMD_SRV].subcmd) != BCME_OK) {
+				ret = BCME_USAGE_ERROR;
+				goto EXIT;
+			}
+			break;
+		case WOG_CMD_A:
+			if (wl_wowl_wog_parse_a(&argv, resp,
+				cmdlist[WOG_CMD_A].subcnt,
+				cmdlist[WOG_CMD_A].subcmd) != BCME_OK) {
+				ret = BCME_USAGE_ERROR;
+				goto EXIT;
+			}
+			break;
+		default:
+			ret = BCME_USAGE_ERROR;
+			goto EXIT;
+		}
+		cmdlist[cmdidx].mandatory = 0;
+		argv++;
+	}
+
+	/* Check if all mendatory fields exist or not */
+	for (i = 0; i < cmdcnt; i++) {
+		if (cmdlist[i].mandatory) {
+			ret = BCME_USAGE_ERROR;
+			goto EXIT;
+		}
+	}
+
+	ret = wlu_iovar_set(wl, cmd->name, resp, sizeof(*resp));
+
+EXIT:
+	if (resp) {
+		free(resp);
+	}
+	if (cmdlist) {
+		free(cmdlist);
+	}
+	return ret;
+}
diff --git a/wl/src/wl/ppr/include/wlc_ppr.h b/wl/src/wl/ppr/include/wlc_ppr.h
new file mode 100644
index 0000000..5818b75
--- /dev/null
+++ b/wl/src/wl/ppr/include/wlc_ppr.h
@@ -0,0 +1,461 @@
+/**
+ * @file
+ * @brief
+ * PHY module Power-per-rate API. Provides interface functions and definitions for opaque
+ * ppr structure for use containing regulatory and board limits and tx power targets.
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id$
+ */
+
+/** Twiki's: [MfgcPresentations] [PPRTxPowerCache] */
+
+#ifndef _wlc_ppr_h_
+#define _wlc_ppr_h_
+
+#include <bcmwifi_rates.h>
+#include <bcmutils.h>
+#include <bcmwifi_channels.h>
+
+#ifdef EVENT_LOG_COMPILE
+#include <event_log.h>
+#endif /* EVENT_LOG_COMPILE */
+
+#ifdef BCMDRIVER
+#include <osl.h>
+
+#ifdef BCMDBG_ERR
+#if defined(ERR_USE_EVENT_LOG)
+#define	PPR_ERROR(args)		EVENT_LOG_COMPACT_CAST_PAREN_ARGS(EVENT_LOG_TAG_WL_ERROR, args)
+#else
+#define	PPR_ERROR(args)		printf args
+#endif /* ERR_USE_EVENT_LOG */
+#else
+#define	PPR_ERROR(args)
+#endif /* BCMDBG_ERR */
+#else
+#include <stdio.h>
+#define osl_t void
+#define	PPR_ERROR(args)		printf args
+#endif /* BCMDRIVER */
+
+#ifndef BCMPHYCORENUM
+#define PPR_MAX_TX_CHAINS 4
+#else
+#if (BCMPHYCORENUM < 1) || (BCMPHYCORENUM > 4)
+#error Invalid number of PHY cores
+#endif /* BCMPHYCORENUM < 1 || BCMPHYCORENUM > 4 */
+#define PPR_MAX_TX_CHAINS (BCMPHYCORENUM)
+#endif /* !defined(BCMPHYCORENUM) */
+
+#define WL_RATE_GROUP_VHT_INDEX_MCS_7  7
+#define WL_RATE_GROUP_VHT_INDEX_MCS_87 8
+#define WL_RATE_GROUP_VHT_INDEX_MCS_88 9
+
+#ifdef NO_EXTRA_BW_SUPPORT /* For ROM compatiblity */
+#define PPR_CHSPEC_BW(x) (CHSPEC_IS80(x) ? WL_TX_BW_80 : \
+	(CHSPEC_IS40(x) ? WL_TX_BW_40 : WL_TX_BW_20))
+#else
+#define PPR_CHSPEC_BW(x) ppr_chanspec_bw(x)
+#endif /* NO_EXTRA_BW_SUPPORT */
+
+
+/* Opaque PPR data - it keeps its structure to itself */
+typedef struct ppr ppr_t;
+
+
+/* Power values for DSSS 1, 2, 5.5, 11 */
+typedef struct ppr_dsss_rateset { int8 pwr[WL_RATESET_SZ_DSSS]; } ppr_dsss_rateset_t;
+
+/* Power values for OFDM 6, 9, 12... 54 */
+typedef struct ppr_ofdm_rateset { int8 pwr[WL_RATESET_SZ_OFDM]; } ppr_ofdm_rateset_t;
+
+/* Power values one set of 8 HT MCS values (0-7, 8-15, etc) */
+typedef struct ppr_ht_mcs_rateset { int8 pwr[WL_RATESET_SZ_HT_MCS]; } ppr_ht_mcs_rateset_t;
+
+/* Power values one set of 10 VHT MCS values (0-9) */
+
+#ifdef NO_PROPRIETARY_VHT_RATES
+typedef struct ppr_vht_mcs_rateset { int8 pwr[WL_RATESET_SZ_VHT_MCS]; } ppr_vht_mcs_rateset_t;
+#else
+typedef struct ppr_vht_mcs_rateset { int8 pwr[WL_RATESET_SZ_VHT_MCS_P]; } ppr_vht_mcs_rateset_t;
+#endif
+
+
+/* API Routines */
+
+/* Initialization routine for opaque PPR struct */
+void ppr_init(ppr_t* pprptr, wl_tx_bw_t bw);
+
+/* Reinitialization routine for opaque PPR struct */
+void ppr_clear(ppr_t* pprptr);
+
+
+/* Size routine for user alloc/dealloc */
+uint32 ppr_size(wl_tx_bw_t bw);
+
+/* Size routine for user serialization alloc */
+uint32 ppr_ser_size(const ppr_t* pprptr);
+
+/* Size routine for user serialization alloc for a given bw */
+uint32 ppr_ser_size_by_bw(wl_tx_bw_t bw);
+
+/* Init allocated memory with a ppr serialization head
+ * This function must be called if serialization side has different
+ * compilation conditions (e.g PPR_MAX_TX_CHAINS, WL_BEAMFORMING etc.)
+ */
+int ppr_init_ser_mem_by_bw(uint8* pbuf, wl_tx_bw_t bw, uint32 len);
+
+/* Init allocated memory with a ppr serialization head for the given ppr pointer
+ * This function must be called if serialization side has different
+ * compilation conditions (e.g PPR_MAX_TX_CHAINS, WL_BEAMFORMING etc.)
+ */
+int ppr_init_ser_mem(uint8* pbuf, ppr_t * ppr, uint32 len);
+
+/* Constructor routine for opaque PPR struct */
+ppr_t* ppr_create(osl_t* osh, wl_tx_bw_t bw);
+
+/* Constructor routine for opaque PPR struct on pre-alloc memory */
+ppr_t* ppr_create_prealloc(wl_tx_bw_t bw, int8 *buf, uint len);
+
+/* Update the bw for the given opaque PPR struct */
+void ppr_set_ch_bw(ppr_t* pprptr, wl_tx_bw_t bw);
+
+/* Destructor routine for opaque PPR struct */
+void ppr_delete(osl_t* osh, ppr_t* pprptr);
+
+/* Type routine for inferring opaque structure size */
+wl_tx_bw_t ppr_get_ch_bw(const ppr_t* pprptr);
+
+/* Type routine to get ppr supported maximum bw */
+wl_tx_bw_t ppr_get_max_bw(void);
+/* Get the maximum power in the dsss ppr set */
+int8 ppr_get_dsss_max(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains);
+/* Get the DSSS values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_get_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains,
+	ppr_dsss_rateset_t* dsss);
+
+/* Get the OFDM values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_get_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	ppr_ofdm_rateset_t* ofdm);
+
+/* Get the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_get_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, ppr_ht_mcs_rateset_t* mcs);
+
+/* Get the VHT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_get_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+ wl_tx_chains_t tx_chains, ppr_vht_mcs_rateset_t* mcs);
+
+/* Get the minimum power for a VHT MCS rate specified by Nss, with the given bw and tx chains.
+ * Disabled rates are ignored
+ */
+int ppr_get_vht_mcs_min(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+ wl_tx_chains_t tx_chains, int8* mcs_min);
+
+
+/* Routines to set target powers per rate for a whole rate set */
+
+/* Set the DSSS values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains,
+	const ppr_dsss_rateset_t* dsss);
+
+/* Set the OFDM values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	const ppr_ofdm_rateset_t* ofdm);
+
+/* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const ppr_ht_mcs_rateset_t* mcs);
+
+/* Set the VHT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const ppr_vht_mcs_rateset_t* mcs);
+
+
+/* Routines to set a whole rate set to a single target value */
+
+/* Set the DSSS values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_same_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains, const int8 power);
+
+/* Set the OFDM values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_same_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	const int8 power);
+
+/* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_same_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const int8 power);
+
+
+/* Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_same_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const int8 power);
+
+
+/* Helper routines to operate on the entire ppr set */
+
+/* Ensure no rate limit is greater than the specified maximum */
+uint ppr_apply_max(ppr_t* pprptr, int8 max);
+
+/* Make disabled rates explicit. If one rate in a group is disabled, disable the whole group */
+int ppr_force_disabled(ppr_t* pprptr, int8 threshold);
+
+/* Explicitly disable all VHT-only MIMO rates - i.e. vht8SS2 and above. */
+int ppr_disable_vht_mimo_rates(ppr_t* pprptr);
+
+/*
+ * Reduce total transmitted power to level of constraint.
+ * For two chain rates, the per-antenna power must be halved.
+ * For three chain rates, it must be a third of the constraint.
+ */
+uint ppr_apply_constraint_total_tx(ppr_t* pprptr, int8 constraint);
+
+/* Ensure no rate limit is lower than the specified minimum */
+uint ppr_apply_min(ppr_t* pprptr, int8 min);
+
+
+/* Ensure no rate limit in this ppr set is greater than the corresponding limit in ppr_cap */
+uint ppr_apply_vector_ceiling(ppr_t* pprptr, const ppr_t* ppr_cap);
+
+/* Ensure no rate limit in this ppr set is lower than the corresponding limit in ppr_min */
+uint ppr_apply_vector_floor(ppr_t* pprptr, const ppr_t* ppr_min);
+
+
+/* Get the maximum power in the ppr set */
+int8 ppr_get_max(ppr_t* pprptr);
+
+/*
+ * Get the minimum power in the ppr set excluding disallowed
+ * rates and powers set to the minimum for the phy
+ */
+int8 ppr_get_min(ppr_t* pprptr, int8 floor);
+
+
+/* Get the maximum power for a given bandwidth in the ppr set */
+int8 ppr_get_max_for_bw(ppr_t* pprptr, wl_tx_bw_t bw);
+
+/* Get the minimum power for a given bandwidth  in the ppr set */
+int8 ppr_get_min_for_bw(ppr_t* pprptr, wl_tx_bw_t bw);
+
+
+typedef void (*ppr_mapfn_t)(void *context, uint8 *a, uint8 *b);
+
+/* Map the given function with its context value over the two power vectors */
+void ppr_map_vec_dsss(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_chains_t tx_chains);
+
+/* Map the given function with its context value over the two power vectors */
+void ppr_map_vec_ofdm(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains);
+
+/* Map the given function with its context value over the two power vectors */
+void ppr_map_vec_ht_mcs(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains);
+
+/* Map the given function with its context value over the two power vectors */
+void ppr_map_vec_vht_mcs(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains);
+
+/* Map the given function with its context value over the two power vectors */
+void ppr_map_vec_all(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2);
+
+/* Get the first index that is larger than a given power level */
+int16 ppr_get_idx(ppr_t* pprptr, int8 pwr);
+
+/* Set PPR struct to a certain power level */
+void ppr_set_cmn_val(ppr_t* pprptr, int8 val);
+
+/* Make an identical copy of a ppr structure (for ppr_bw==all case) */
+void ppr_copy_struct(ppr_t* pprptr_s, ppr_t* pprptr_d);
+
+/* Subtract each power from a common value and re-store */
+void ppr_cmn_val_minus(ppr_t* pprptr, int8 val);
+
+/* Compare two ppr variables p1 and p2, save the min. value of each
+ * contents to variable p1
+ */
+void ppr_compare_min(ppr_t* p1, ppr_t* p2);
+
+/* compare two ppr variables p1 and p2, save the max. value of each
+ * contents to variable p1
+ */
+void ppr_compare_max(ppr_t* p1, ppr_t* p2);
+
+/* Serialize the contents of the opaque ppr struct.
+ * Writes number of bytes copied, zero on error.
+ * Returns error code, BCME_OK if successful.
+ */
+int ppr_serialize(const ppr_t* pprptr, uint8* buf, uint buflen, uint* bytes_copied);
+
+/* Deserialize the contents of a buffer into an existing opaque ppr struct.
+ * The ppr struct *must* be of the same type as the one that was serialized.
+ * Returns error code, BCME_OK if successful.
+ */
+int ppr_deserialize(ppr_t* pprptr, const uint8* buf, uint buflen);
+
+/* Deserialize the contents of a buffer into a new opaque ppr struct.
+ * Creates an opaque structure referenced by *pptrptr, NULL on error.
+ * Returns error code, BCME_OK if successful.
+ */
+int ppr_deserialize_create(osl_t* osh, const uint8* buf, uint buflen, ppr_t** pprptr);
+
+/* Subtract a common value from each power and re-store */
+void ppr_minus_cmn_val(ppr_t* pprptr, int8 val);
+
+/* Add a common value to the given bw struct components */
+void ppr_plus_cmn_val(ppr_t* pprptr, int8 val);
+
+/* Multiply a percentage */
+void ppr_multiply_percentage(ppr_t* pprptr, uint8 val);
+
+/* Get transmit channel bandwidths from chanspec */
+wl_tx_bw_t ppr_chanspec_bw(chanspec_t chspec);
+
+#if defined(WL_EXPORT_CURPOWER) || !defined(BCMDRIVER)
+/* Convert ppr structure to TLV data */
+void ppr_convert_to_tlv(ppr_t* pprptr, wl_tx_bw_t bw, uint8 *to_tlv_buf, uint32 tlv_buf_len,
+	wl_tx_chains_t max_chain);
+
+/* Convert TLV data to ppr structure */
+int ppr_convert_from_tlv(ppr_t* pprptr, uint8 *from_tlv_buf, uint32 tlv_buf_len);
+
+/* Get the total ppr TLV buffer size for given bandwidth and chain number */
+uint32 ppr_get_tlv_size(ppr_t* pprptr, wl_tx_bw_t bw, uint32 max_chain);
+
+/* Get current PPR TLV version */
+uint32 ppr_get_tlv_ver(void);
+#endif /* WL_EXPORT_CURPOWER || !BCMDRIVER */
+
+/* Forward declaration */
+typedef struct tx_pwr_cache_entry tx_pwr_cache_entry_t;
+
+#ifdef WLTXPWR_CACHE
+
+/**
+ * Usage of the WLTXPWR_CACHE API:
+ * 1. Reserve one or more entries in the cache for a specific chanspec:
+ * 		wlc_phy_txpwr_setup_entry(chanspec1);
+ * 		wlc_phy_txpwr_setup_entry(chanspec2);
+ * 2. Use any of the getter/setter functions. Note that they may return an error on a chanspec
+ *    that was not reserved. For setter functions, for pointer type arguments (e.g. ppr_t), the
+ *    cache maintains a reference to the caller provided object rather than copying it.
+ * 3. Use wlc_phy_txpwr_cache_clear() or wlc_phy_txpwr_cache_invalidate() to get rid of cache
+ *    entries. Note that this clears, amongst others, ppr_t structs.
+ *
+ * For non-BMAC builds, only the cache is allowed to delete the ppr_t object, and the driver code is
+ * not allowed to reuse it for another channel as it can when the cache is not being used.
+ *
+ * For BMAC builds, the cache has to be made to release the stf offsets object to avoid some nasty
+ * race conditions.
+ *
+ * Mike thinks when this is reimplemented for trunk he would consider having a reference count
+ * associated with each object to make this cleaner.
+ *
+ * Note that the functions start with wlc_phy_* despite not residing in the PHY code. This is
+ * probably for historical reasons.
+ */
+
+enum txpwr_cache_info_type {
+	TXPWR_CACHE_STF_OFFSETS,	/* PPR offsets for stf */
+	TXPWR_CACHE_POWER_OFFSETS,	/* PPR offsets for phy */
+	TXPWR_CACHE_NUM_TYPES,	/* How many types of pwr info */
+};
+
+#define TXPWR_STF_PWR_MIN_INVALID 0x80
+#define TXPWR_STF_TARGET_PWR_MIN_INVALID 0x40
+#define TXPWR_STF_TARGET_PWR_NOT_CACHED 0x20
+extern bool wlc_phy_get_cached_pwr(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+		uint pwr_type, ppr_t* pprptr);
+
+extern ppr_t* wlc_phy_get_cached_ppr_ptr(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint pwr_type);
+
+extern int wlc_phy_set_cached_pwr(osl_t* osh, tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint pwr_type, ppr_t* pwrptr);
+
+extern int8 wlc_phy_get_cached_boardlim(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint core);
+
+extern int wlc_phy_set_cached_boardlim(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint core, int8 board_lim);
+
+extern uint8 wlc_phy_get_cached_pwr_max(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint core);
+
+extern int wlc_phy_set_cached_pwr_max(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint core, uint8 max_pwr);
+
+extern uint8 wlc_phy_get_cached_pwr_min(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint core);
+
+extern int wlc_phy_set_cached_pwr_min(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint core, uint8 min_pwr);
+
+extern int wlc_phy_get_cached_stf_target_pwr_min(tx_pwr_cache_entry_t* cacheptr,
+	chanspec_t chanspec);
+
+extern int wlc_phy_set_cached_stf_target_pwr_min(tx_pwr_cache_entry_t* cacheptr,
+	chanspec_t chanspec, int min_pwr);
+
+extern int8 wlc_phy_get_cached_txchain_offsets(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint core);
+
+extern int wlc_phy_set_cached_txchain_offsets(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint core, int8 offset);
+
+extern bool wlc_phy_txpwr_cache_is_cached(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec);
+
+extern bool wlc_phy_is_pwr_cached(tx_pwr_cache_entry_t* cacheptr, uint pwr_type, ppr_t* pwrptr);
+
+extern void wlc_phy_uncache_pwr(tx_pwr_cache_entry_t* cacheptr, uint pwr_type, ppr_t* pwrptr);
+
+extern chanspec_t wlc_phy_txpwr_cache_find_other_cached_chanspec(tx_pwr_cache_entry_t* cacheptr,
+	chanspec_t chanspec);
+
+extern tx_pwr_cache_entry_t* wlc_phy_txpwr_cache_create(osl_t* osh);
+
+extern void wlc_phy_txpwr_cache_clear(osl_t* osh, tx_pwr_cache_entry_t* cacheptr,
+	chanspec_t chanspec);
+
+extern void wlc_phy_txpwr_cache_invalidate(tx_pwr_cache_entry_t* cacheptr);
+
+extern void wlc_phy_txpwr_cache_close(osl_t* osh, tx_pwr_cache_entry_t* cacheptr);
+
+extern int wlc_phy_txpwr_setup_entry(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec);
+
+#ifdef WL_SARLIMIT
+void wlc_phy_set_cached_sar_lims(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint32 sar_lims);
+
+uint32 wlc_phy_get_cached_sar_lims(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec);
+#endif
+
+#ifndef WLTXPWR_CACHE_PHY_ONLY
+extern bool wlc_phy_get_stf_ppr_cached(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec);
+
+extern void wlc_phy_set_stf_ppr_cached(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	bool bcached);
+
+extern int wlc_phy_get_cached_stf_pwr_min_dbm(tx_pwr_cache_entry_t* cacheptr);
+
+extern void wlc_phy_set_cached_stf_pwr_min_dbm(tx_pwr_cache_entry_t* cacheptr, int min_pwr);
+
+extern void wlc_phy_set_cached_stf_max_offset(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint8 max_offset);
+
+extern uint8 wlc_phy_get_cached_stf_max_offset(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec);
+#endif /* WLTXPWR_CACHE_PHY_ONLY */
+#endif /* WLTXPWR_CACHE */
+#endif	/* _wlc_ppr_h_ */
diff --git a/wl/src/wl/ppr/src/wlc_ppr.c b/wl/src/wl/ppr/src/wlc_ppr.c
new file mode 100644
index 0000000..29f92be
--- /dev/null
+++ b/wl/src/wl/ppr/src/wlc_ppr.c
@@ -0,0 +1,3515 @@
+/**
+ * @file
+ * @brief
+ * PHY module Power-per-rate API. Provides interface functions and definitions for
+ * ppr structure for use containing regulatory and board limits and tx power targets.
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: $
+ */
+
+/**
+ * @file
+ * @brief
+ * Sometimes not all rates should reach the same max power, in order to comply with FCC. Different
+ * rates (even different sub-band bands) may want different max power.
+ *
+ * real_max_power[antenna, rate] = max_power[antenna] - power_offset[rate]
+ *
+ * Both regulatory restrictions (by wlc_channel.c) and SPROM restrictions (SPROm is read by phy
+ * code) determine this power offset.
+ */
+
+
+#if defined(__FreeBSD__)
+#if defined(_KERNEL)
+#include <wlc_cfg.h>
+#endif /* defined(_KERNEL) */
+#endif 
+
+#include <typedefs.h>
+#include <bcmendian.h>
+#include <bcmwifi_channels.h>
+#include <wlc_ppr.h>
+#include <bcmutils.h>
+
+#ifndef BCMDRIVER
+
+#ifndef WL_BEAMFORMING
+#define WL_BEAMFORMING /* enable TxBF definitions for utility code */
+#endif
+
+#ifndef WL11AC_160
+#define WL11AC_160 /* Enable WL11AC_160 for utility code */
+#endif
+
+#ifndef WL11AC_80P80
+#define WL11AC_80P80 /* Enable WL11AC_80P80 for utility code */
+#endif
+
+#ifndef bcopy
+#include <string.h>
+#include <stdlib.h>
+#define	bcopy(src, dst, len)	memcpy((dst), (src), (len))
+#endif
+
+#ifndef ASSERT
+#define ASSERT(exp)	do {} while (0)
+#endif
+#endif /* BCMDRIVER */
+
+/* ppr local TXBF_ENAB() macro because wlc->pub struct is not accessible */
+#ifdef WL_BEAMFORMING
+#if defined(WLTXBF_DISABLED)
+#define PPR_TXBF_ENAB()	(0)
+#else
+#define PPR_TXBF_ENAB()	(1)
+#endif
+#else
+#define PPR_TXBF_ENAB()	(0)
+#endif /* WL_BEAMFORMING */
+
+typedef enum ppr_tlv_id {
+	PPR_RGRP_DSSS_ID = 1,
+	PPR_RGRP_OFDM_ID,
+	PPR_RGRP_MCS_ID
+} ppr_tlv_id_t;
+
+/* This marks the start of a packed structure section. */
+#include <packed_section_start.h>
+
+#define PPR_SERIALIZATION_VER 3
+#define PPR_TLV_VER (PPR_SERIALIZATION_VER + 1)
+
+/** ppr deserialization header */
+typedef BWL_PRE_PACKED_STRUCT struct ppr_deser_header {
+	uint8  version;
+	uint8  bw;
+	uint16 per_band_size;
+	uint32 flags;
+	uint16 chain3size; /* ppr data size of 3 Tx chains, needed in deserialisation process */
+} BWL_POST_PACKED_STRUCT ppr_deser_header_t;
+
+
+typedef BWL_PRE_PACKED_STRUCT struct ppr_ser_mem_flag {
+	uint32 magic_word;
+	uint32 flag;
+} BWL_POST_PACKED_STRUCT ppr_ser_mem_flag_t;
+
+
+#define WLC_TXPWR_DB_FACTOR 4 /* conversion for phy txpwr cacluations that use .25 dB units */
+
+
+/* QDB() macro takes a dB value and converts to a quarter dB value */
+#ifdef QDB
+#undef QDB
+#endif
+#define QDB(n) ((n) * WLC_TXPWR_DB_FACTOR)
+
+#define PPR_HDR_CUR_BW_MASK		0x000000FF
+#define PPR_HDR_ALLOC_BW_MASK		0x0000FF00
+#define PPR_HDR_FLAG_MASK		0xFFFF0000
+#define PPR_HDR_ALLOC_BW_SHIFT		8
+
+/* PPR flags, start defining from left to right, in case bandwidth needs more bits */
+#define PPR_HDR_FLAG_PREALLOC		0x80000000 /* ppr structure is on a pre-allocaed memory */
+
+/* Flag bits in serialization/deserialization */
+#define PPR_MAX_TX_CHAIN_MASK	0x0000007 /* mask of Tx chains */
+#define PPR_SER_MEM_WORD	0xBEEFC0FF /* magic word indicates serialization start */
+
+
+/* size of serialization header */
+#define SER_HDR_LEN    sizeof(ppr_deser_header_t)
+
+/** Per band tx powers */
+typedef BWL_PRE_PACKED_STRUCT struct pprpb {
+	/* start of 20MHz tx power limits */
+	int8 p_1x1dsss[WL_RATESET_SZ_DSSS];			/* Legacy CCK/DSSS */
+	int8 p_1x1ofdm[WL_RATESET_SZ_OFDM]; 		/* 20 MHz Legacy OFDM transmission */
+	int8 p_1x1vhtss1[WL_RATESET_SZ_VHT_MCS_P];	/* 10HT/12VHT pwrs from 1x1mcs0 */
+#if (PPR_MAX_TX_CHAINS > 1)
+	int8 p_1x2dsss[WL_RATESET_SZ_DSSS];			/* Legacy CCK/DSSS */
+	int8 p_1x2cdd_ofdm[WL_RATESET_SZ_OFDM];		/* 20 MHz Legacy OFDM CDD transmission */
+	int8 p_1x2cdd_vhtss1[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 1x2cdd_mcs0 */
+	int8 p_2x2stbc_vhtss1[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 2x2stbc_mcs0 */
+	int8 p_2x2vhtss2[WL_RATESET_SZ_VHT_MCS_P];	/* 10HT/12VHT pwrs from 2x2sdm_mcs8 */
+	int8 p_1x2txbf_ofdm[WL_RATESET_SZ_OFDM];	/* 20 MHz Legacy OFDM TXBF transmission */
+	int8 p_1x2txbf_vhtss1[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 1x2txbf_mcs0 */
+	int8 p_2x2txbf_vhtss2[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 2x2txbf_mcs8 */
+#if (PPR_MAX_TX_CHAINS > 2)
+	int8 p_1x3dsss[WL_RATESET_SZ_DSSS];			/* Legacy CCK/DSSS */
+	int8 p_1x3cdd_ofdm[WL_RATESET_SZ_OFDM];		/* 20 MHz Legacy OFDM CDD transmission */
+	int8 p_1x3cdd_vhtss1[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 1x3cdd_mcs0 */
+	int8 p_2x3stbc_vhtss1[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 2x3stbc_mcs0 */
+	int8 p_2x3vhtss2[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 2x3sdm_mcs8 spexp1 */
+	int8 p_3x3vhtss3[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 3x3sdm_mcs16 */
+	int8 p_1x3txbf_ofdm[WL_RATESET_SZ_OFDM];	/* 20 MHz Legacy OFDM TXBF transmission */
+	int8 p_1x3txbf_vhtss1[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 1x3txbf_mcs0 */
+	int8 p_2x3txbf_vhtss2[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 2x3txbf_mcs8 */
+	int8 p_3x3txbf_vhtss3[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 3x3txbf_mcs16 */
+#if (PPR_MAX_TX_CHAINS > 3)
+	int8 p_1x4dsss[WL_RATESET_SZ_DSSS];			/* Legacy CCK/DSSS */
+	int8 p_1x4cdd_ofdm[WL_RATESET_SZ_OFDM];		/* 20 MHz Legacy OFDM CDD transmission */
+	int8 p_1x4cdd_vhtss1[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 1x4cdd_mcs0 */
+	int8 p_2x4stbc_vhtss1[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 2x4stbc_mcs0 */
+	int8 p_2x4vhtss2[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 2x4sdm_mcs8 spexp1 */
+	int8 p_3x4vhtss3[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 3x4 ht_vht */
+	int8 p_4x4vhtss4[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 4x4 */
+	int8 p_1x4txbf_ofdm[WL_RATESET_SZ_OFDM];	/* 20 MHz Legacy OFDM TXBF transmission */
+	int8 p_1x4txbf_vhtss1[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 1x4txbf_mcs0 */
+	int8 p_2x4txbf_vhtss2[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 2x4txbf_mcs8 */
+	int8 p_3x4txbf_vhtss3[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 3x4txbf_mcs16 */
+	int8 p_4x4txbf_vhtss4[WL_RATESET_SZ_VHT_MCS_P]; /* 10HT/12VHT pwrs from 4x4txbf_mcs16 */
+#endif /* PPR_MAX_TX_CHAINS > 3 */
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+} BWL_POST_PACKED_STRUCT pprpbw_t;
+
+
+#define PPR_CHAIN1_FIRST OFFSETOF(pprpbw_t, p_1x1dsss)
+#define PPR_CHAIN1_END   (OFFSETOF(pprpbw_t, p_1x1vhtss1) + sizeof(((pprpbw_t *)0)->p_1x1vhtss1))
+#define PPR_CHAIN1_SIZE  PPR_CHAIN1_END
+#if (PPR_MAX_TX_CHAINS > 1)
+#define PPR_CHAIN2_FIRST OFFSETOF(pprpbw_t, p_1x2dsss)
+#define PPR_CHAIN2_FIRST_MCS OFFSETOF(pprpbw_t, p_1x2cdd_vhtss1)
+#define PPR_CHAIN2_END   (OFFSETOF(pprpbw_t, p_2x2txbf_vhtss2) + \
+	sizeof(((pprpbw_t *)0)->p_2x2txbf_vhtss2))
+#define PPR_CHAIN2_SIZE  (PPR_CHAIN2_END - PPR_CHAIN2_FIRST)
+#define PPR_CHAIN2_MCS_END (OFFSETOF(pprpbw_t, p_2x2vhtss2) + sizeof(((pprpbw_t *)0)->p_2x2vhtss2))
+#define PPR_CHAIN2_MCS_SIZE  (PPR_CHAIN2_MCS_END - PPR_CHAIN2_FIRST_MCS)
+#define PPR_BF_CHAIN2_FIRST OFFSETOF(pprpbw_t, p_1x2txbf_ofdm)
+#define PPR_BF_CHAIN2_FIRST_MCS OFFSETOF(pprpbw_t, p_1x2txbf_vhtss1)
+#define PPR_BF_CHAIN2_END   (OFFSETOF(pprpbw_t, p_2x2txbf_vhtss2) + \
+	sizeof(((pprpbw_t *)0)->p_2x2txbf_vhtss2))
+#define PPR_BF_CHAIN2_SIZE  (PPR_BF_CHAIN2_END - PPR_BF_CHAIN2_FIRST)
+#define PPR_BF_CHAIN2_MCS_SIZE  (PPR_BF_CHAIN2_END - PPR_BF_CHAIN2_FIRST_MCS)
+#if (PPR_MAX_TX_CHAINS > 2)
+#define PPR_CHAIN3_FIRST OFFSETOF(pprpbw_t, p_1x3dsss)
+#define PPR_CHAIN3_FIRST_MCS OFFSETOF(pprpbw_t, p_1x3cdd_vhtss1)
+#define PPR_CHAIN3_END   (OFFSETOF(pprpbw_t, p_3x3txbf_vhtss3) + \
+	sizeof(((pprpbw_t *)0)->p_3x3txbf_vhtss3))
+#define PPR_CHAIN3_SIZE  (PPR_CHAIN3_END - PPR_CHAIN3_FIRST)
+#define PPR_CHAIN3_MCS_END (OFFSETOF(pprpbw_t, p_3x3vhtss3) + sizeof(((pprpbw_t *)0)->p_3x3vhtss3))
+#define PPR_CHAIN3_MCS_SIZE  (PPR_CHAIN3_MCS_END - PPR_CHAIN3_FIRST_MCS)
+#define PPR_BF_CHAIN3_FIRST OFFSETOF(pprpbw_t, p_1x3txbf_ofdm)
+#define PPR_BF_CHAIN3_FIRST_MCS OFFSETOF(pprpbw_t, p_1x3txbf_vhtss1)
+#define PPR_BF_CHAIN3_END   (OFFSETOF(pprpbw_t, p_3x3txbf_vhtss3) + \
+	sizeof(((pprpbw_t *)0)->p_3x3txbf_vhtss3))
+#define PPR_BF_CHAIN3_SIZE  (PPR_BF_CHAIN3_END - PPR_BF_CHAIN3_FIRST)
+#define PPR_BF_CHAIN3_MCS_SIZE  (PPR_BF_CHAIN3_END - PPR_BF_CHAIN3_FIRST_MCS)
+#if (PPR_MAX_TX_CHAINS > 3)
+#define PPR_CHAIN4_FIRST OFFSETOF(pprpbw_t, p_1x4dsss)
+#define PPR_CHAIN4_FIRST_MCS OFFSETOF(pprpbw_t, p_1x4cdd_vhtss1)
+#define PPR_CHAIN4_END   (OFFSETOF(pprpbw_t, p_4x4txbf_vhtss4) + \
+	sizeof(((pprpbw_t *)0)->p_4x4txbf_vhtss4))
+#define PPR_CHAIN4_SIZE  (PPR_CHAIN4_END - PPR_CHAIN4_FIRST)
+#define PPR_CHAIN4_MCS_END (OFFSETOF(pprpbw_t, p_4x4vhtss4) + sizeof(((pprpbw_t *)0)->p_4x4vhtss4))
+#define PPR_CHAIN4_MCS_SIZE  (PPR_CHAIN4_MCS_END - PPR_CHAIN4_FIRST_MCS)
+#define PPR_BF_CHAIN4_FIRST OFFSETOF(pprpbw_t, p_1x4txbf_ofdm)
+#define PPR_BF_CHAIN4_FIRST_MCS OFFSETOF(pprpbw_t, p_1x4txbf_vhtss1)
+#define PPR_BF_CHAIN4_END   (OFFSETOF(pprpbw_t, p_4x4txbf_vhtss4) + \
+	sizeof(((pprpbw_t *)0)->p_4x4txbf_vhtss4))
+#define PPR_BF_CHAIN4_SIZE  (PPR_BF_CHAIN4_END - PPR_BF_CHAIN4_FIRST)
+#define PPR_BF_CHAIN4_MCS_SIZE  (PPR_BF_CHAIN4_END - PPR_BF_CHAIN4_FIRST_MCS)
+#endif /* PPR_MAX_TX_CHAINS > 3 */
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+
+/* Maximum supported bandwidth */
+#if defined(WL11AC_80P80)
+#define PPR_BW_MAX WL_TX_BW_8080
+#define MAX_PPR_SIZE (sizeof(ppr_bw_8080_t) + sizeof(wl_tx_bw_t))
+#elif defined(WL11AC_160)
+#define PPR_BW_MAX WL_TX_BW_160
+#define MAX_PPR_SIZE (sizeof(ppr_bw_160_t) + sizeof(wl_tx_bw_t))
+#else
+#define PPR_BW_MAX WL_TX_BW_80
+#define MAX_PPR_SIZE (sizeof(ppr_bw_80_t) + sizeof(wl_tx_bw_t))
+#endif
+
+/* If a bw is ULB */
+#define IS_ULB_BW(bw) ((bw == WL_TX_BW_2P5) || (bw == WL_TX_BW_5) || (bw == WL_TX_BW_10))
+
+/** Structure to contain ppr values for a 20MHz channel */
+typedef BWL_PRE_PACKED_STRUCT struct ppr_bw_20 {
+	/* 20MHz tx power limits */
+	pprpbw_t b20;
+} BWL_POST_PACKED_STRUCT ppr_bw_20_t;
+
+/** Structure to contain ppr values for a 40MHz channel */
+typedef BWL_PRE_PACKED_STRUCT struct ppr_bw_40 {
+	/* 40MHz tx power limits */
+	pprpbw_t b40;
+	/* 20in40MHz tx power limits */
+	pprpbw_t b20in40;
+} BWL_POST_PACKED_STRUCT ppr_bw_40_t;
+
+
+/** Structure to contain ppr values for an 80MHz channel */
+typedef BWL_PRE_PACKED_STRUCT struct ppr_bw_80 {
+	/* 80MHz tx power limits */
+	pprpbw_t b80;
+	/* 20in80MHz tx power limits */
+	pprpbw_t b20in80;
+	/* 40in80MHz tx power limits */
+	pprpbw_t b40in80;
+} BWL_POST_PACKED_STRUCT ppr_bw_80_t;
+
+/** Structure to contain ppr values for a 160MHz channel */
+typedef BWL_PRE_PACKED_STRUCT struct ppr_bw_160 {
+	/* 160MHz tx power limits */
+	pprpbw_t b160;
+	/* 20in160MHz tx power limits */
+	pprpbw_t b20in160;
+	/* 40in160MHz tx power limits */
+	pprpbw_t b40in160;
+	/* 80in160MHz tx power limits */
+	pprpbw_t b80in160;
+} BWL_POST_PACKED_STRUCT ppr_bw_160_t;
+
+
+/** Structure to contain ppr values for an 80+80MHz channel */
+typedef BWL_PRE_PACKED_STRUCT struct ppr_bw_8080 {
+	/* 80+80MHz chan1 tx power limits */
+	pprpbw_t b80ch1;
+	/* 80+80MHz chan2 tx power limits */
+	pprpbw_t b80ch2;
+	/* 80in80+80MHz (chan1 subband) tx power limits */
+	pprpbw_t b80in8080;
+	/* 20in80+80MHz (chan1 subband) tx power limits */
+	pprpbw_t b20in8080;
+	/* 40in80+80MHz (chan1 subband) tx power limits */
+	pprpbw_t b40in8080;
+} BWL_POST_PACKED_STRUCT ppr_bw_8080_t;
+
+/**
+ * This is the initial implementation of the structure we're hiding. It is sized to contain only
+ * the set of powers it requires, so the union is not necessarily the size of the largest member.
+ */
+BWL_PRE_PACKED_STRUCT struct ppr {
+	uint32 hdr;
+
+	BWL_PRE_PACKED_STRUCT union {
+		ppr_bw_20_t ch20;
+		ppr_bw_40_t ch40;
+		ppr_bw_80_t ch80;
+		ppr_bw_160_t ch160;
+		ppr_bw_8080_t ch8080;
+	} ppr_bw;
+} BWL_POST_PACKED_STRUCT;
+
+typedef BWL_PRE_PACKED_STRUCT struct ppr_dsss_tlv {
+	uint8 bw;
+	uint8 chains;
+	uint8 pwr[];
+} BWL_POST_PACKED_STRUCT ppr_dsss_tlv_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct ppr_ofdm_tlv {
+	uint8 bw;
+	uint8 chains;
+	uint8 mode;
+	uint8 pwr[];
+} BWL_POST_PACKED_STRUCT ppr_ofdm_tlv_t;
+
+typedef BWL_PRE_PACKED_STRUCT struct ppr_mcs_tlv {
+	uint8 bw;
+	uint8 chains;
+	uint8 mode;
+	uint8 nss;
+	uint8 pwr[];
+} BWL_POST_PACKED_STRUCT ppr_mcs_tlv_t;
+
+/* This marks the end of a packed structure section. */
+#include <packed_section_end.h>
+
+static wl_tx_bw_t ppr_get_cur_bw(const ppr_t* p)
+{
+	return ((p->hdr) & PPR_HDR_CUR_BW_MASK);
+}
+
+#ifdef BCMDRIVER
+static wl_tx_bw_t ppr_get_alloc_bw(uint32 hdr)
+{
+	return (((hdr) & PPR_HDR_ALLOC_BW_MASK) >> PPR_HDR_ALLOC_BW_SHIFT);
+}
+#endif
+
+#if (defined(BCMDBG_ASSERT) || defined(BCMASSERT_LOG)) && defined(BCMDRIVER)
+static bool ppr_is_valid_bw(wl_tx_bw_t bw)
+{
+	bool ret = FALSE;
+	if ((bw == WL_TX_BW_20) || (bw == WL_TX_BW_40) || (bw == WL_TX_BW_80) ||
+		(bw == WL_TX_BW_160) || (bw == WL_TX_BW_8080) || (bw == PPR_BW_MAX) ||
+		IS_ULB_BW(bw)) {
+		ret = TRUE;
+	}
+
+	return ret;
+}
+#endif
+
+/** Returns a flag of ppr conditions (chains, txbf etc.) */
+static uint32 ppr_get_flag(void)
+{
+	uint32 flag = 0;
+	flag  |= PPR_MAX_TX_CHAINS & PPR_MAX_TX_CHAIN_MASK;
+	return flag;
+}
+
+static uint16 ppr_ser_size_per_band(uint32 flags)
+{
+	uint16 ret = PPR_CHAIN1_SIZE; /* at least 1 chain rates should be there */
+	uint8 chain   = flags & PPR_MAX_TX_CHAIN_MASK;
+	BCM_REFERENCE(chain);
+#if (PPR_MAX_TX_CHAINS > 1)
+	if (chain > 1) {
+		ret += PPR_CHAIN2_SIZE;
+	}
+#if (PPR_MAX_TX_CHAINS > 2)
+	if (chain > 2) {
+		ret += PPR_CHAIN3_SIZE;
+	}
+#if (PPR_MAX_TX_CHAINS > 3)
+	if (chain > 3) {
+		ret += PPR_CHAIN4_SIZE;
+	}
+#endif /* PPR_MAX_TX_CHAINS > 3 */
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+	return ret;
+}
+
+/** Returns the number of bands for a specific bandwidth bw */
+static uint ppr_bands_by_bw(wl_tx_bw_t bw)
+{
+	switch (bw) {
+	case WL_TX_BW_2P5:
+	case WL_TX_BW_5:
+	case WL_TX_BW_10:
+	case WL_TX_BW_20:
+		return sizeof(ppr_bw_20_t)/sizeof(pprpbw_t);
+	case WL_TX_BW_40:
+		return sizeof(ppr_bw_40_t)/sizeof(pprpbw_t);
+	case WL_TX_BW_80:
+		return sizeof(ppr_bw_80_t)/sizeof(pprpbw_t);
+	case WL_TX_BW_160:
+		return sizeof(ppr_bw_160_t)/sizeof(pprpbw_t);
+	case WL_TX_BW_8080:
+		return sizeof(ppr_bw_8080_t)/sizeof(pprpbw_t);
+	default:
+		ASSERT(0);
+		return 0;
+	}
+}
+
+/** Return the required serialization size based on the flag field. */
+static uint ppr_ser_size_by_flag(uint32 flag, wl_tx_bw_t bw)
+{
+	return ppr_ser_size_per_band(flag) * ppr_bands_by_bw(bw);
+}
+
+#define COPY_PPR_TOBUF(x, y) do { bcopy(&pprbuf[x], *buf, y); \
+	*buf += y; ret += y; } while (0);
+
+
+/** Serialize ppr data of a bandwidth into the given buffer */
+static uint ppr_serialize_block(const uint8* pprbuf, uint8** buf, uint32 serflag)
+{
+	uint ret = 0;
+#if (PPR_MAX_TX_CHAINS > 1)
+	uint chain   = serflag & PPR_MAX_TX_CHAIN_MASK; /* chain number in serialized block */
+#endif
+
+	COPY_PPR_TOBUF(PPR_CHAIN1_FIRST, PPR_CHAIN1_SIZE);
+#if (PPR_MAX_TX_CHAINS > 1)
+	if (chain > 1) {
+		COPY_PPR_TOBUF(PPR_CHAIN2_FIRST, PPR_CHAIN2_SIZE);
+	}
+#if (PPR_MAX_TX_CHAINS > 2)
+	if (chain > 2) {
+		COPY_PPR_TOBUF(PPR_CHAIN3_FIRST, PPR_CHAIN3_SIZE);
+	}
+#if (PPR_MAX_TX_CHAINS > 3)
+	if (chain > 3) {
+		COPY_PPR_TOBUF(PPR_CHAIN4_FIRST, PPR_CHAIN4_SIZE);
+	}
+#endif /* (PPR_MAX_TX_CHAINS > 2) */
+#endif /* (PPR_MAX_TX_CHAINS > 2) */
+#endif /* (PPR_MAX_TX_CHAINS > 1) */
+	return ret;
+}
+
+
+/** Serialize ppr data of each bandwidth into the given buffer, returns bytes copied */
+static uint ppr_serialize_data(const ppr_t *pprptr, uint8* buf, uint32 serflag)
+{
+	uint i;
+	uint bands;
+	const uint8* pprbuf;
+
+	uint ret = sizeof(ppr_deser_header_t);
+	ppr_deser_header_t* header = (ppr_deser_header_t*)buf;
+	ASSERT(pprptr && buf);
+	header->version = PPR_SERIALIZATION_VER;
+	header->bw      = (uint8)ppr_get_cur_bw(pprptr);
+	header->flags   = HTON32(ppr_get_flag());
+	header->per_band_size	= HTON16(ppr_ser_size_per_band(serflag));
+
+	buf += sizeof(*header);
+
+	bands = ppr_bands_by_bw(header->bw);
+	pprbuf = (const uint8*)&pprptr->ppr_bw;
+	for (i = 0; i < bands; i++) {
+		ret += ppr_serialize_block(pprbuf, &buf, serflag);
+		pprbuf += sizeof(pprpbw_t); /* Jump to next band */
+	}
+
+	return ret;
+}
+
+
+/** Copy serialized ppr data of a bandwidth */
+static void
+ppr_copy_serdata(uint8* pobuf, const uint8** inbuf, uint32 flag, uint16 per_band_size)
+{
+	uint chain   = flag & PPR_MAX_TX_CHAIN_MASK;
+	uint16 len   = PPR_CHAIN1_SIZE;
+	BCM_REFERENCE(chain);
+	bcopy(*inbuf, pobuf, PPR_CHAIN1_SIZE);
+	*inbuf += PPR_CHAIN1_SIZE;
+#if (PPR_MAX_TX_CHAINS > 1)
+	if (chain > 1) {
+		bcopy(*inbuf, &pobuf[PPR_CHAIN2_FIRST], PPR_CHAIN2_SIZE);
+		*inbuf += PPR_CHAIN2_SIZE;
+		len += PPR_CHAIN2_SIZE;
+	}
+#if (PPR_MAX_TX_CHAINS > 2)
+	if (chain > 2) {
+		bcopy(*inbuf, &pobuf[PPR_CHAIN3_FIRST], PPR_CHAIN3_SIZE);
+		*inbuf += PPR_CHAIN3_SIZE;
+		len += PPR_CHAIN3_SIZE;
+	}
+#if (PPR_MAX_TX_CHAINS > 3)
+	if (chain > 3) {
+		bcopy(*inbuf, &pobuf[PPR_CHAIN4_FIRST], PPR_CHAIN4_SIZE);
+		*inbuf += PPR_CHAIN4_SIZE;
+		len += PPR_CHAIN4_SIZE;
+	}
+#endif /* (PPR_MAX_TX_CHAINS > 3) */
+#endif /* (PPR_MAX_TX_CHAINS > 2) */
+#endif /* (PPR_MAX_TX_CHAINS > 1) */
+	if (len < per_band_size) {
+		 *inbuf += (per_band_size - len);
+	}
+}
+
+
+/* Deserialize data into a ppr_t structure */
+static void
+ppr_deser_cpy(ppr_t* pptr, const uint8* inbuf, uint32 flag, wl_tx_bw_t bw, uint16 per_band_size)
+{
+	uint i;
+	uint bands;
+	uint8* pobuf;
+
+	ppr_set_ch_bw(pptr, bw);
+	bands = ppr_bands_by_bw(bw);
+	pobuf = (uint8*)&pptr->ppr_bw;
+	for (i = 0; i < bands; i++) {
+		ppr_copy_serdata(pobuf, &inbuf, flag, per_band_size);
+		pobuf += sizeof(pprpbw_t); /* Jump to next band */
+	}
+}
+
+
+/** Get a pointer to the power values for a given channel bandwidth */
+static pprpbw_t* ppr_get_bw_powers_20(ppr_t* p, wl_tx_bw_t bw)
+{
+	pprpbw_t* pwrs = NULL;
+
+	if (bw == WL_TX_BW_20 || IS_ULB_BW(bw))
+		pwrs = &p->ppr_bw.ch20.b20;
+	/* else */
+	/*   ASSERT(0); */
+	return pwrs;
+}
+
+
+/** Get a pointer to the power values for a given channel bandwidth */
+static pprpbw_t* ppr_get_bw_powers_40(ppr_t* p, wl_tx_bw_t bw)
+{
+	pprpbw_t* pwrs = NULL;
+
+	switch (bw) {
+	case WL_TX_BW_40:
+		pwrs = &p->ppr_bw.ch40.b40;
+	break;
+	case WL_TX_BW_2P5:
+	case WL_TX_BW_5:
+	case WL_TX_BW_10:
+	case WL_TX_BW_20:
+
+	case WL_TX_BW_20IN40:
+		pwrs = &p->ppr_bw.ch40.b20in40;
+	break;
+	default:
+		/* ASSERT(0); */
+	break;
+	}
+	return pwrs;
+}
+
+
+/** Get a pointer to the power values for a given channel bandwidth */
+static pprpbw_t* ppr_get_bw_powers_80(ppr_t* p, wl_tx_bw_t bw)
+{
+	pprpbw_t* pwrs = NULL;
+
+	switch (bw) {
+	case WL_TX_BW_80:
+		pwrs = &p->ppr_bw.ch80.b80;
+	break;
+	case WL_TX_BW_2P5:
+	case WL_TX_BW_5:
+	case WL_TX_BW_10:
+	case WL_TX_BW_20:
+	case WL_TX_BW_20IN40:
+	case WL_TX_BW_20IN80:
+		pwrs = &p->ppr_bw.ch80.b20in80;
+	break;
+	case WL_TX_BW_40:
+	case WL_TX_BW_40IN80:
+		pwrs = &p->ppr_bw.ch80.b40in80;
+	break;
+	default:
+		/* ASSERT(0); */
+	break;
+	}
+	return pwrs;
+}
+
+/** Get a pointer to the power values for a given channel bandwidth */
+static pprpbw_t* ppr_get_bw_powers_160(ppr_t* p, wl_tx_bw_t bw)
+{
+	pprpbw_t* pwrs = NULL;
+
+	switch (bw) {
+	case WL_TX_BW_160:
+	case WL_TX_BW_8080:		// stf function doesn't care much if we're 160 or 80p80
+		pwrs = &p->ppr_bw.ch160.b160;
+	break;
+	case WL_TX_BW_2P5:
+	case WL_TX_BW_5:
+	case WL_TX_BW_10:
+	case WL_TX_BW_20:
+	case WL_TX_BW_20IN40:
+	case WL_TX_BW_20IN80:
+	case WL_TX_BW_20IN160:
+		pwrs = &p->ppr_bw.ch160.b20in160;
+	break;
+	case WL_TX_BW_40:
+	case WL_TX_BW_40IN80:
+	case WL_TX_BW_40IN160:
+		pwrs = &p->ppr_bw.ch160.b40in160;
+	break;
+	case WL_TX_BW_80:
+	case WL_TX_BW_80IN160:
+		pwrs = &p->ppr_bw.ch160.b80in160;
+	break;
+	default:
+		/* ASSERT(0); */
+	break;
+	}
+	return pwrs;
+}
+
+
+/** Get a pointer to the power values for a given channel bandwidth */
+static pprpbw_t* ppr_get_bw_powers_8080(ppr_t* p, wl_tx_bw_t bw)
+{
+	pprpbw_t* pwrs = NULL;
+
+	switch (bw) {
+	case WL_TX_BW_160:		// stf function doesn't care much if we're 160 or 80p80
+	case WL_TX_BW_8080:
+		pwrs = &p->ppr_bw.ch8080.b80ch1;
+	break;
+	case WL_TX_BW_8080CHAN2:
+		pwrs = &p->ppr_bw.ch8080.b80ch2;
+	break;
+	case WL_TX_BW_2P5:
+	case WL_TX_BW_5:
+	case WL_TX_BW_10:
+	case WL_TX_BW_20:
+	case WL_TX_BW_20IN40:
+	case WL_TX_BW_20IN80:
+	case WL_TX_BW_20IN160:
+	case WL_TX_BW_20IN8080:
+		pwrs = &p->ppr_bw.ch8080.b20in8080;
+	break;
+	case WL_TX_BW_40:
+	case WL_TX_BW_40IN80:
+	case WL_TX_BW_40IN160:
+	case WL_TX_BW_40IN8080:
+		pwrs = &p->ppr_bw.ch8080.b40in8080;
+	break;
+	case WL_TX_BW_80:
+	case WL_TX_BW_80IN160:
+	case WL_TX_BW_80IN8080:
+		pwrs = &p->ppr_bw.ch8080.b80in8080;
+	break;
+	default:
+		/* ASSERT(0); */
+	break;
+	}
+	return pwrs;
+}
+
+typedef pprpbw_t* (*wlc_ppr_get_bw_pwrs_fn_t)(ppr_t* p, wl_tx_bw_t bw);
+
+typedef struct {
+	wl_tx_bw_t ch_bw;		/* Bandwidth of the channel for which powers are stored */
+	/* Function to retrieve the powers for the requested bandwidth */
+	wlc_ppr_get_bw_pwrs_fn_t fn;
+} wlc_ppr_get_bw_pwrs_pair_t;
+
+
+static const wlc_ppr_get_bw_pwrs_pair_t ppr_get_bw_pwrs_fn[] = {
+	{WL_TX_BW_20, ppr_get_bw_powers_20},
+	{WL_TX_BW_40, ppr_get_bw_powers_40},
+	{WL_TX_BW_80, ppr_get_bw_powers_80},
+	{WL_TX_BW_160, ppr_get_bw_powers_160},
+	{WL_TX_BW_8080, ppr_get_bw_powers_8080},
+	{WL_TX_BW_2P5, ppr_get_bw_powers_20},
+	{WL_TX_BW_5, ppr_get_bw_powers_20},
+	{WL_TX_BW_10, ppr_get_bw_powers_20},
+};
+
+
+/** Get a pointer to the power values for a given channel bandwidth */
+static pprpbw_t* ppr_get_bw_powers(ppr_t* p, wl_tx_bw_t bw)
+{
+	uint32 i;
+
+	if (p == NULL) {
+		return NULL;
+	}
+
+	for (i = 0; i < (int)ARRAYSIZE(ppr_get_bw_pwrs_fn); i++) {
+		if (ppr_get_bw_pwrs_fn[i].ch_bw == ppr_get_cur_bw(p))
+			return ppr_get_bw_pwrs_fn[i].fn(p, bw);
+	}
+
+	ASSERT(0);
+	return NULL;
+}
+
+
+/**
+ * Rate group power finder functions: ppr_get_xxx_group()
+ * To preserve the opacity of the PPR struct, even inside the API we try to limit knowledge of
+ * its details. Almost all API functions work on the powers for individual rate groups, rather than
+ * directly accessing the struct. Once the section of the structure corresponding to the bandwidth
+ * has been identified using ppr_get_bw_powers(), the ppr_get_xxx_group() functions use knowledge
+ * of the number of spatial streams, the number of tx chains, and the expansion mode to return a
+ * pointer to the required group of power values.
+ */
+
+/** Get a pointer to the power values for the given dsss rate group for a given channel bandwidth */
+static int8* ppr_get_dsss_group(pprpbw_t* bw_pwrs, wl_tx_chains_t tx_chains)
+{
+	int8* group_pwrs = NULL;
+
+	switch (tx_chains) {
+#if (PPR_MAX_TX_CHAINS > 1)
+#if (PPR_MAX_TX_CHAINS > 2)
+#if (PPR_MAX_TX_CHAINS > 3)
+	case WL_TX_CHAINS_4:
+		group_pwrs = bw_pwrs->p_1x4dsss;
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 3 */
+	case WL_TX_CHAINS_3:
+		group_pwrs = bw_pwrs->p_1x3dsss;
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+	case WL_TX_CHAINS_2:
+		group_pwrs = bw_pwrs->p_1x2dsss;
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+	case WL_TX_CHAINS_1:
+		group_pwrs = bw_pwrs->p_1x1dsss;
+		break;
+	default:
+		ASSERT(0);
+		break;
+	}
+	return group_pwrs;
+}
+
+
+/** Get a pointer to the power values for the given ofdm rate group for a given channel bandwidth */
+static int8* ppr_get_ofdm_group(pprpbw_t* bw_pwrs, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains)
+{
+	int8* group_pwrs = NULL;
+	BCM_REFERENCE(mode);
+	switch (tx_chains) {
+#if (PPR_MAX_TX_CHAINS > 1)
+#if (PPR_MAX_TX_CHAINS > 2)
+#if (PPR_MAX_TX_CHAINS > 3)
+	case WL_TX_CHAINS_4:
+		if (mode == WL_TX_MODE_TXBF) {
+			group_pwrs = bw_pwrs->p_1x4txbf_ofdm;
+		} else {
+			group_pwrs = bw_pwrs->p_1x4cdd_ofdm;
+		}
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 3 */
+	case WL_TX_CHAINS_3:
+		if (mode == WL_TX_MODE_TXBF)
+			group_pwrs = bw_pwrs->p_1x3txbf_ofdm;
+		else
+			group_pwrs = bw_pwrs->p_1x3cdd_ofdm;
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+	case WL_TX_CHAINS_2:
+		if (mode == WL_TX_MODE_TXBF)
+			group_pwrs = bw_pwrs->p_1x2txbf_ofdm;
+		else
+			group_pwrs = bw_pwrs->p_1x2cdd_ofdm;
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+	case WL_TX_CHAINS_1:
+		group_pwrs = bw_pwrs->p_1x1ofdm;
+		break;
+	default:
+		ASSERT(0);
+		break;
+	}
+	return group_pwrs;
+}
+
+
+/**
+ * Tables to provide access to HT/VHT rate group powers. This avoids an ugly nested switch with
+ * messy conditional compilation.
+ *
+ * Access to a given table entry is via table[chains - Nss][mode], except for the Nss3 table, which
+ * only has one row, so it can be indexed directly by table[mode].
+ *
+ * Separate tables are provided for each of Nss1, Nss2 and Nss3 because they are all different
+ * sizes. A combined table would be very sparse, and this arrangement also simplifies the
+ * conditional compilation.
+ *
+ * Each row represents a given number of chains, so there's no need for a zero row. Because
+ * chains >= Nss is always true, there is no one-chain row for Nss2 and there are no one- or
+ * two-chain rows for Nss3. With the tables correctly sized, we can index the rows
+ * using [chains - Nss].
+ *
+ * Then, inside each row, we index by mode:
+ * WL_TX_MODE_NONE, WL_TX_MODE_STBC, WL_TX_MODE_CDD, WL_TX_MODE_TXBF.
+ */
+
+#define OFFSNONE (-1)
+
+static const int mcs_groups_nss1[PPR_MAX_TX_CHAINS][WL_NUM_TX_MODES] = {
+	/* WL_TX_MODE_NONE
+	   WL_TX_MODE_STBC
+	   WL_TX_MODE_CDD
+	   WL_TX_MODE_TXBF
+	*/
+	/* 1 chain */
+	{OFFSETOF(pprpbw_t, p_1x1vhtss1),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 1)
+	/* 2 chain */
+	{OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_1x2cdd_vhtss1),
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 2)
+	/* 3 chain */
+	{OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_1x3cdd_vhtss1),
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 3)
+	/* 4 chain */
+	{OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_1x4cdd_vhtss1),
+	OFFSNONE}
+#endif /* PPR_MAX_TX_CHAINS > 3 */
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+};
+
+/** mcs group with TXBF data */
+static const int mcs_groups_nss1_txbf[PPR_MAX_TX_CHAINS][WL_NUM_TX_MODES] = {
+	/* WL_TX_MODE_NONE
+	   WL_TX_MODE_STBC
+	   WL_TX_MODE_CDD
+	   WL_TX_MODE_TXBF
+	*/
+	/* 1 chain */
+	{OFFSETOF(pprpbw_t, p_1x1vhtss1),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 1)
+	/* 2 chain */
+	{OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_1x2cdd_vhtss1),
+	OFFSETOF(pprpbw_t, p_1x2txbf_vhtss1)},
+#if (PPR_MAX_TX_CHAINS > 2)
+	/* 3 chain */
+	{OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_1x3cdd_vhtss1),
+	OFFSETOF(pprpbw_t, p_1x3txbf_vhtss1)},
+#if (PPR_MAX_TX_CHAINS > 3)
+	/* 4 chain */
+	{OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_1x4cdd_vhtss1),
+	OFFSETOF(pprpbw_t, p_1x4txbf_vhtss1)}
+#endif /* PPR_MAX_TX_CHAINS > 3 */
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+};
+
+#if (PPR_MAX_TX_CHAINS > 1)
+static const int mcs_groups_nss2[PPR_MAX_TX_CHAINS - 1][WL_NUM_TX_MODES] = {
+	/* 2 chain */
+	{OFFSETOF(pprpbw_t, p_2x2vhtss2),
+	OFFSETOF(pprpbw_t, p_2x2stbc_vhtss1),
+	OFFSNONE,
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 2)
+	/* 3 chain */
+	{OFFSETOF(pprpbw_t, p_2x3vhtss2),
+	OFFSETOF(pprpbw_t, p_2x3stbc_vhtss1),
+	OFFSNONE,
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 3)
+	/* 4 chain */
+	{OFFSETOF(pprpbw_t, p_2x4vhtss2),
+	OFFSETOF(pprpbw_t, p_2x4stbc_vhtss1),
+	OFFSNONE,
+	OFFSNONE}
+#endif /* PPR_MAX_TX_CHAINS > 3 */
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+};
+
+/** mcs group with TXBF data */
+static const int mcs_groups_nss2_txbf[PPR_MAX_TX_CHAINS - 1][WL_NUM_TX_MODES] = {
+	/* 2 chain */
+	{OFFSETOF(pprpbw_t, p_2x2vhtss2),
+	OFFSETOF(pprpbw_t, p_2x2stbc_vhtss1),
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_2x2txbf_vhtss2)},
+#if (PPR_MAX_TX_CHAINS > 2)
+	/* 3 chain */
+	{OFFSETOF(pprpbw_t, p_2x3vhtss2),
+	OFFSETOF(pprpbw_t, p_2x3stbc_vhtss1),
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_2x3txbf_vhtss2)},
+#if (PPR_MAX_TX_CHAINS > 3)
+	/* 4 chain */
+	{OFFSETOF(pprpbw_t, p_2x4vhtss2),
+	OFFSETOF(pprpbw_t, p_2x4stbc_vhtss1),
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_2x4txbf_vhtss2)}
+#endif /* PPR_MAX_TX_CHAINS > 3  */
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+};
+#if (PPR_MAX_TX_CHAINS > 2)
+static const int mcs_groups_nss3[PPR_MAX_TX_CHAINS - 2][WL_NUM_TX_MODES] = {
+/* 3 chains */
+	{OFFSETOF(pprpbw_t, p_3x3vhtss3),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSNONE},
+#if (PPR_MAX_TX_CHAINS > 3)
+	{OFFSETOF(pprpbw_t, p_3x4vhtss3),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSNONE}
+#endif /* PPR_MAX_TX_CHAINS > 3  */
+};
+
+/** mcs group with TXBF data */
+static const int mcs_groups_nss3_txbf[PPR_MAX_TX_CHAINS - 2][WL_NUM_TX_MODES] = {
+/* 3 chains */
+	{OFFSETOF(pprpbw_t, p_3x3vhtss3),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_3x3txbf_vhtss3)},
+#if (PPR_MAX_TX_CHAINS > 3)
+	{OFFSETOF(pprpbw_t, p_3x4vhtss3),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_3x4txbf_vhtss3)}
+#endif /* PPR_MAX_TX_CHAINS > 3  */
+};
+#if (PPR_MAX_TX_CHAINS > 3)
+static const int mcs_groups_nss4[WL_NUM_TX_MODES] = {
+/* 4 chains only */
+	OFFSETOF(pprpbw_t, p_4x4vhtss4),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSNONE,
+};
+/** mcs group with TXBF data */
+static const int mcs_groups_nss4_txbf[WL_NUM_TX_MODES] = {
+/* 4 chains only */
+	OFFSETOF(pprpbw_t, p_4x4vhtss4),
+	OFFSNONE,
+	OFFSNONE,
+	OFFSETOF(pprpbw_t, p_4x4txbf_vhtss4)
+};
+#endif /* PPR_MAX_TX_CHAINS > 3 */
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+
+/** Get a pointer to the power values for the given rate group for a given channel bandwidth */
+static int8* ppr_get_mcs_group(pprpbw_t* bw_pwrs, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains)
+{
+	int8* group_pwrs = NULL;
+	int offset;
+
+	switch (Nss) {
+#if (PPR_MAX_TX_CHAINS > 1)
+#if (PPR_MAX_TX_CHAINS > 2)
+#if (PPR_MAX_TX_CHAINS > 3)
+	case WL_TX_NSS_4:
+		if (tx_chains == WL_TX_CHAINS_4) {
+			if (mode == WL_TX_MODE_TXBF && PPR_TXBF_ENAB()) {
+				 offset = mcs_groups_nss4_txbf[mode];
+			} else {
+				offset = mcs_groups_nss4[mode];
+			}
+			if (offset != OFFSNONE) {
+				group_pwrs = (int8*)bw_pwrs + offset;
+			}
+		}
+		else
+			ASSERT(0);
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 3 */
+	case WL_TX_NSS_3:
+		if ((tx_chains >= WL_TX_CHAINS_3) && (tx_chains <= PPR_MAX_TX_CHAINS)) {
+			if (PPR_TXBF_ENAB()) {
+				offset = mcs_groups_nss3_txbf[tx_chains - Nss][mode];
+			} else {
+				offset = mcs_groups_nss3[tx_chains - Nss][mode];
+			}
+			if (offset != OFFSNONE) {
+				group_pwrs = (int8*)bw_pwrs + offset;
+			}
+		}
+		else
+			ASSERT(0);
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+	case WL_TX_NSS_2:
+		if ((tx_chains >= WL_TX_CHAINS_2) && (tx_chains <= PPR_MAX_TX_CHAINS)) {
+			if (PPR_TXBF_ENAB()) {
+				offset = mcs_groups_nss2_txbf[tx_chains - Nss][mode];
+			} else {
+				offset = mcs_groups_nss2[tx_chains - Nss][mode];
+			}
+			if (offset != OFFSNONE) {
+				group_pwrs = (int8*)bw_pwrs + offset;
+			}
+		}
+		else
+			ASSERT(0);
+		break;
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+	case WL_TX_NSS_1:
+		if (tx_chains <= PPR_MAX_TX_CHAINS) {
+			if (PPR_TXBF_ENAB()) {
+				offset = mcs_groups_nss1_txbf[tx_chains - Nss][mode];
+			} else {
+				offset = mcs_groups_nss1[tx_chains - Nss][mode];
+			}
+			if (offset != OFFSNONE) {
+				group_pwrs = (int8*)bw_pwrs + offset;
+			}
+		}
+		else
+			ASSERT(0);
+		break;
+	default:
+#ifdef BCMQT
+		printf("%s: %d: WL_TX_CHAINS_4 not supported yet, ignoring for now!!\n",
+			__FUNCTION__, __LINE__);
+#else
+		ASSERT(0);
+#endif
+		break;
+	}
+	return group_pwrs;
+}
+
+/** Size routine for user alloc/dealloc */
+static uint32 ppr_pwrs_size(uint32 hdr)
+{
+	uint32 size;
+
+	switch ((hdr & PPR_HDR_CUR_BW_MASK)) {
+	case WL_TX_BW_2P5:
+	case WL_TX_BW_5:
+	case WL_TX_BW_10:
+	case WL_TX_BW_20:
+		size = sizeof(ppr_bw_20_t);
+	break;
+	case WL_TX_BW_40:
+		size = sizeof(ppr_bw_40_t);
+	break;
+	case WL_TX_BW_80:
+		size = sizeof(ppr_bw_80_t);
+	break;
+#ifdef WL11AC_160
+	case WL_TX_BW_160:
+		size = sizeof(ppr_bw_160_t);
+	break;
+#endif
+#ifdef WL11AC_80P80
+	case WL_TX_BW_8080:
+		size = sizeof(ppr_bw_8080_t);
+	break;
+#endif
+	default:
+		ASSERT(0);
+		size = 0;
+	break;
+	}
+	return size;
+}
+
+
+/** Initialization routine */
+void ppr_init(ppr_t* pprptr, wl_tx_bw_t bw)
+{
+	memset(pprptr, (int8)WL_RATE_DISABLED, ppr_size(bw));
+	pprptr->hdr = 0;
+	pprptr->hdr |= (bw & PPR_HDR_CUR_BW_MASK);
+	pprptr->hdr |= ((bw << PPR_HDR_ALLOC_BW_SHIFT) & PPR_HDR_ALLOC_BW_MASK);
+}
+
+
+/** Reinitialization routine for opaque PPR struct */
+void ppr_clear(ppr_t* pprptr)
+{
+	memset((uchar*)&pprptr->ppr_bw, (int8)WL_RATE_DISABLED,
+		ppr_pwrs_size(pprptr->hdr));
+}
+
+
+/** Size routine for user alloc/dealloc */
+uint32 ppr_size(wl_tx_bw_t bw)
+{
+	uint32 ret = ppr_pwrs_size(bw) + sizeof(wl_tx_bw_t);
+	ASSERT(ret <= MAX_PPR_SIZE);
+	return ret;
+}
+
+
+/** Size routine for user serialization alloc */
+uint32 ppr_ser_size(const ppr_t* pprptr)
+{
+	return ppr_pwrs_size(pprptr->hdr) + SER_HDR_LEN;	/* struct size plus headers */
+}
+
+
+/** Size routine for user serialization alloc */
+uint32 ppr_ser_size_by_bw(wl_tx_bw_t bw)
+{
+	return ppr_pwrs_size(bw) + SER_HDR_LEN;
+}
+
+
+/** Constructor routine for opaque PPR struct */
+ppr_t* ppr_create(osl_t *osh, wl_tx_bw_t bw)
+{
+	ppr_t* pprptr;
+
+	ASSERT(ppr_is_valid_bw(bw));
+#ifndef BCMDRIVER
+	BCM_REFERENCE(osh);
+	if ((pprptr = (ppr_t*)malloc((uint)ppr_size(bw))) != NULL) {
+#else
+	if ((pprptr = (ppr_t*)MALLOC_NOPERSIST(osh, (uint)ppr_size(bw))) != NULL) {
+#endif
+		ppr_init(pprptr, bw);
+	} else {
+		PPR_ERROR(("%s: MALLOC(%d) failed\n", __FUNCTION__, (int)ppr_size(bw)));
+	}
+	return pprptr;
+}
+
+
+/* Constructor routine for opaque PPR struct on pre-alloc memory */
+ppr_t* ppr_create_prealloc(wl_tx_bw_t bw, int8 *buf, uint len)
+{
+	ppr_t* pprptr = NULL;
+	ASSERT(ppr_is_valid_bw(bw));
+
+	if (ppr_size(bw) <= len) {
+		pprptr = (ppr_t*) buf;
+		ppr_init(pprptr, bw);
+		pprptr->hdr |= PPR_HDR_FLAG_PREALLOC;
+	} else {
+		PPR_ERROR(("%s: Insufficient mem(%d), need %d\n", __FUNCTION__, len,
+				(int)ppr_size(bw)));
+		ASSERT(0);
+	}
+	return pprptr;
+}
+
+/**
+ * Init flags in the memory block for serialization, the serializer will check
+ * the flag to decide which ppr to be copied
+ */
+int ppr_init_ser_mem_by_bw(uint8* pbuf, wl_tx_bw_t bw, uint32 len)
+{
+	ppr_ser_mem_flag_t *pmflag;
+
+	if (pbuf == NULL || ppr_ser_size_by_bw(bw) > len)
+		return BCME_BADARG;
+
+	pmflag = (ppr_ser_mem_flag_t *)pbuf;
+	pmflag->magic_word = HTON32(PPR_SER_MEM_WORD);
+	pmflag->flag   = HTON32(ppr_get_flag());
+
+	/* init the memory */
+	memset(pbuf + sizeof(*pmflag), (uint8)WL_RATE_DISABLED, len-sizeof(*pmflag));
+	return BCME_OK;
+}
+
+
+int ppr_init_ser_mem(uint8* pbuf, ppr_t * ppr, uint32 len)
+{
+	return ppr_init_ser_mem_by_bw(pbuf, ppr->hdr, len);
+}
+
+/** Destructor routine for opaque PPR struct */
+void ppr_delete(osl_t *osh, ppr_t* pprptr)
+{
+	ASSERT(ppr_is_valid_bw(ppr_get_cur_bw(pprptr)));
+
+	if (pprptr->hdr & PPR_HDR_FLAG_PREALLOC)
+		return;
+
+#ifndef BCMDRIVER
+	BCM_REFERENCE(osh);
+	free(pprptr);
+#else
+	MFREE(osh, pprptr, (uint)ppr_size(ppr_get_alloc_bw(pprptr->hdr)));
+#endif
+}
+
+/* Update the bw for the given opaque PPR struct
+ * This function is used when an opaque PPR struct has been allocated
+ * with enough space for the given bandwidth.
+ * USE WITH CAUTION
+ */
+void ppr_set_ch_bw(ppr_t* pprptr, wl_tx_bw_t bw)
+{
+	ASSERT(ppr_size(ppr_get_alloc_bw(pprptr->hdr)) >= ppr_size(bw));
+	pprptr->hdr &= ~PPR_HDR_CUR_BW_MASK;
+	pprptr->hdr |= (bw & PPR_HDR_CUR_BW_MASK);
+}
+
+/** Type routine for inferring opaque structure size */
+wl_tx_bw_t ppr_get_ch_bw(const ppr_t* pprptr)
+{
+	return ppr_get_cur_bw(pprptr);
+}
+
+/** Type routine to get ppr supported maximum bw */
+wl_tx_bw_t ppr_get_max_bw(void)
+{
+	return PPR_BW_MAX;
+}
+
+
+/** Get the dsss values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_get_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains,
+	ppr_dsss_rateset_t* dsss)
+{
+	pprpbw_t* bw_pwrs;
+	const int8* powers;
+	int cnt = 0;
+
+	ASSERT(pprptr);
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = ppr_get_dsss_group(bw_pwrs, tx_chains);
+		if (powers != NULL) {
+			bcopy(powers, dsss->pwr, sizeof(*dsss));
+			cnt = sizeof(*dsss);
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d TX_Chain:%d rateset:%p\n",
+			__FUNCTION__, pprptr, bw, tx_chains, dsss));
+		memset(dsss->pwr, (int8)WL_RATE_DISABLED, sizeof(*dsss));
+	}
+	return cnt;
+}
+
+
+/** Get the ofdm values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_get_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	ppr_ofdm_rateset_t* ofdm)
+{
+	pprpbw_t* bw_pwrs;
+	const int8* powers;
+	int cnt = 0;
+
+	ASSERT(pprptr);
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = ppr_get_ofdm_group(bw_pwrs, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(powers, ofdm->pwr, sizeof(*ofdm));
+			cnt = sizeof(*ofdm);
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d mode:%d TX_Chain:%d rateset:%p\n",
+			__FUNCTION__, pprptr, bw, mode, tx_chains, ofdm));
+		memset(ofdm->pwr, (int8)WL_RATE_DISABLED, sizeof(*ofdm));
+	}
+	return cnt;
+}
+
+
+/**
+ * Get the HT MCS values for the group specified by Nss, with the given bw and tx chains. Function
+ * is not called by ACPHY code, but even in case of ACPHY, function is called by wlc_channel.c.
+ */
+int ppr_get_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, ppr_ht_mcs_rateset_t* mcs)
+{
+	pprpbw_t* bw_pwrs;
+	const int8* powers;
+	int cnt = 0;
+
+	ASSERT(pprptr);
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(powers, mcs->pwr, sizeof(*mcs));
+			cnt = sizeof(*mcs);
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d Nss:%d mode:%d TX_Chain:%d rateset:%p\n",
+			__FUNCTION__, pprptr, bw, Nss, mode, tx_chains, mcs));
+		memset(mcs->pwr, (int8)WL_RATE_DISABLED, sizeof(*mcs));
+	}
+
+	return cnt;
+}
+
+
+/** Get the VHT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_get_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, ppr_vht_mcs_rateset_t* mcs)
+{
+	pprpbw_t* bw_pwrs;
+	const int8* powers;
+	int cnt = 0;
+
+	ASSERT(pprptr);
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(powers, mcs->pwr, sizeof(*mcs));
+			cnt = sizeof(*mcs);
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d Nss:%d mode:%d TX_Chain:%d rateset:%p\n",
+			__FUNCTION__, pprptr, bw, Nss, mode, tx_chains, mcs));
+		memset(mcs->pwr, (int8)WL_RATE_DISABLED, sizeof(*mcs));
+	}
+	return cnt;
+}
+
+
+#define TXPPR_TXPWR_MAX 0x7f             /* WLC_TXPWR_MAX */
+
+/**
+ * Get the minimum power for a VHT MCS rate specified by Nss, with the given bw and tx chains.
+ * Disabled rates are ignored
+ */
+int ppr_get_vht_mcs_min(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+ wl_tx_chains_t tx_chains, int8* mcs_min)
+{
+	pprpbw_t* bw_pwrs;
+	const int8* powers;
+	int result = BCME_ERROR;
+	uint i = 0;
+
+	*mcs_min = TXPPR_TXPWR_MAX;
+
+	ASSERT(pprptr);
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (powers != NULL) {
+			for (i = 0; i < sizeof(ppr_vht_mcs_rateset_t); i++) {
+				/* ignore disabled rates! */
+				if (powers[i] != WL_RATE_DISABLED)
+					*mcs_min = MIN(*mcs_min, powers[i]);
+			}
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+
+/* Routines to set target powers per rate in a group */
+
+/** Set the dsss values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains,
+	const ppr_dsss_rateset_t* dsss)
+{
+	pprpbw_t* bw_pwrs;
+	int8* powers;
+	int cnt = 0;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = (int8*)ppr_get_dsss_group(bw_pwrs, tx_chains);
+		if (powers != NULL) {
+			bcopy(dsss->pwr, powers, sizeof(*dsss));
+			cnt = sizeof(*dsss);
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d TX_Chain:%d rateset:%p\n",
+			__FUNCTION__, pprptr, bw, tx_chains, dsss));
+	}
+	return cnt;
+}
+
+
+/** Set the ofdm values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	const ppr_ofdm_rateset_t* ofdm)
+{
+	pprpbw_t* bw_pwrs;
+	int8* powers;
+	int cnt = 0;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = (int8*)ppr_get_ofdm_group(bw_pwrs, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(ofdm->pwr, powers, sizeof(*ofdm));
+			cnt = sizeof(*ofdm);
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d mode:%d TX_Chain:%d rateset:%p\n",
+			__FUNCTION__, pprptr, bw, mode, tx_chains, ofdm));
+	}
+	return cnt;
+}
+
+/**
+ * Set the HT MCS values for the group specified by Nss, with the given bw and tx chains. Function
+ * is not called by ACPHY code, but even in case of ACPHY, function is called by wlc_channel.c.
+ */
+int ppr_set_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const ppr_ht_mcs_rateset_t* mcs)
+{
+	pprpbw_t* bw_pwrs;
+	int8* powers;
+	int cnt = 0;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = (int8*)ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(mcs->pwr, powers, sizeof(*mcs));
+			cnt = sizeof(*mcs);
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d Nss:%d mode:%d TX_Chain:%d rateset:%p\n",
+			__FUNCTION__, pprptr, bw, Nss, mode, tx_chains, mcs));
+	}
+	return cnt;
+}
+
+
+/** Set the VHT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const ppr_vht_mcs_rateset_t* mcs)
+{
+	pprpbw_t* bw_pwrs;
+	int8* powers;
+	int cnt = 0;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		powers = (int8*)ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (powers != NULL) {
+			bcopy(mcs->pwr, powers, sizeof(*mcs));
+			cnt = sizeof(*mcs);
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d Nss:%d mode:%d TX_Chain:%d rateset:%p\n",
+			__FUNCTION__, pprptr, bw, Nss, mode, tx_chains, mcs));
+	}
+	return cnt;
+}
+
+
+/* Routines to set rate groups to a single target value */
+
+/** Set the dsss values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_same_dsss(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains, const int8 power)
+{
+	pprpbw_t* bw_pwrs;
+	int8* dest_group;
+	int cnt = 0;
+	int i;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		dest_group = (int8*)ppr_get_dsss_group(bw_pwrs, tx_chains);
+		if (dest_group != NULL) {
+			cnt = sizeof(ppr_dsss_rateset_t);
+			for (i = 0; i < cnt; i++)
+				*dest_group++ = power;
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d TX_Chain:%d power:%d\n",
+			__FUNCTION__, pprptr, bw, tx_chains, power));
+	}
+	return cnt;
+}
+
+
+/** Set the ofdm values for the given number of tx_chains and 20, 20in40, etc. */
+int ppr_set_same_ofdm(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains,
+	const int8 power)
+{
+	pprpbw_t* bw_pwrs;
+	int8* dest_group;
+	int cnt = 0;
+	int i;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		dest_group = (int8*)ppr_get_ofdm_group(bw_pwrs, mode, tx_chains);
+		if (dest_group != NULL) {
+			cnt = sizeof(ppr_ofdm_rateset_t);
+			for (i = 0; i < cnt; i++)
+				*dest_group++ = power;
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d mode:%d TX_Chain:%d power:%d\n",
+			__FUNCTION__, pprptr, bw, mode, tx_chains, power));
+	}
+	return cnt;
+}
+
+
+/** Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_same_ht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const int8 power)
+{
+	pprpbw_t* bw_pwrs;
+	int8* dest_group;
+	int cnt = 0;
+	int i;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		dest_group = (int8*)ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (dest_group != NULL) {
+			cnt = sizeof(ppr_ht_mcs_rateset_t);
+			for (i = 0; i < cnt; i++)
+				*dest_group++ = power;
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d Nss:%d mode:%d TX_Chain:%d power:%d\n",
+			__FUNCTION__, pprptr, bw, Nss, mode, tx_chains, power));
+	}
+	return cnt;
+}
+
+
+/** Set the HT MCS values for the group specified by Nss, with the given bw and tx chains */
+int ppr_set_same_vht_mcs(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains, const int8 power)
+{
+	pprpbw_t* bw_pwrs;
+	int8* dest_group;
+	int cnt = 0;
+	int i;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		dest_group = (int8*)ppr_get_mcs_group(bw_pwrs, Nss, mode, tx_chains);
+		if (dest_group != NULL) {
+			cnt = sizeof(ppr_vht_mcs_rateset_t);
+			for (i = 0; i < cnt; i++)
+				*dest_group++ = power;
+		}
+	}
+	if (cnt == 0) {
+		PPR_ERROR(("%s: Failed ppr_t:%p BW:%d Nss:%d mode:%d TX_Chain:%d power:%d\n",
+			__FUNCTION__, pprptr, bw, Nss, mode, tx_chains, power));
+	}
+	return cnt;
+}
+
+
+/* Helper routines to operate on the entire ppr set */
+
+/** Ensure no rate limit is greater than the cap */
+uint ppr_apply_max(ppr_t* pprptr, int8 maxval)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->hdr); i++, rptr++) {
+		*rptr = MIN(*rptr, maxval);
+	}
+	return i;
+}
+
+/** number of non proprietary 802.11n single stream MCS'es excluding MCS32 */
+#define N_HT_SS_MCS	8
+
+/**
+ * Before the OLPC calibration (needs to send out some training frames to converge TX Power control)
+ * rates need to be disabled that cannot be controlled to with the accuracy needed to avoid
+ * regulatory violations. Once the calibration completes a newer reduced threshold is set to enable
+ * all valid rates.
+ *
+ * Check for any power in the rate group at or below the threshold. If any is found, set the entire
+ * group to WL_RATE_DISABLED. An exception is made for HT 87 and 88 and VHT 8 and 9 which will not
+ * cause the entire group to be disabled if they are disabled or below the threshold.
+ */
+static void ppr_force_disabled_group(int8* powers, int8 threshold, uint len)
+{
+	uint i;
+
+	for (i = 0; (i < len) && (i < N_HT_SS_MCS); i++) {
+		/* if we find a below-threshold rate in the set... */
+		if (powers[i] < threshold) {
+			/* disable the entire rate set and return */
+			for (i = 0; i < len; i++) {
+				powers[i] = WL_RATE_DISABLED;
+			}
+			return;
+		}
+	}
+	/* VHT 8 and 11 can be disabled separately */
+	for (; i < len; i++) {
+		if (powers[i] < threshold) {
+			powers[i] = WL_RATE_DISABLED;
+		}
+	}
+}
+
+
+/**
+ * Before the OLPC calibration (needs to send out some training frames to converge TX Power control)
+ * rates need to be disabled that cannot be controlled to with the accuracy needed to avoid
+ * regulatory violations. Once the calibration completes a newer reduced threshold is set to enable
+ * all valid rates.
+ *
+ * Make low power rates (below the threshold) explicitly disabled. If one rate in a group is
+ * disabled, disable the whole group.
+ */
+int ppr_force_disabled(ppr_t* pprptr, int8 threshold)
+{
+	wl_tx_bw_t bw;
+
+	for (bw = WL_TX_BW_20; bw <= WL_TX_BW_80; bw++) {
+		pprpbw_t* bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+
+		if (bw_pwrs != NULL) {
+			int8* powers;
+#if (PPR_MAX_TX_CHAINS > 1)
+			int8* mcs_powers;
+#endif
+			powers = (int8*)ppr_get_dsss_group(bw_pwrs, WL_TX_CHAINS_1);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_DSSS);
+
+			powers = (int8*)ppr_get_ofdm_group(bw_pwrs,
+				WL_TX_MODE_NONE, WL_TX_CHAINS_1);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+			powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1, WL_TX_MODE_NONE,
+				WL_TX_CHAINS_1);
+			ASSERT(powers);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_VHT_MCS_P);
+
+#if (PPR_MAX_TX_CHAINS > 1)
+			powers = (int8*)ppr_get_dsss_group(bw_pwrs, WL_TX_CHAINS_2);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_DSSS);
+
+			powers = (int8*)ppr_get_ofdm_group(bw_pwrs, WL_TX_MODE_CDD, WL_TX_CHAINS_2);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+			mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1, WL_TX_MODE_CDD,
+				WL_TX_CHAINS_2);
+			ASSERT(mcs_powers);
+			for (powers = mcs_powers; powers < &mcs_powers[PPR_CHAIN2_MCS_SIZE];
+				powers += WL_RATESET_SZ_VHT_MCS_P) {
+				ppr_force_disabled_group(powers, threshold,
+					WL_RATESET_SZ_VHT_MCS_P);
+			}
+
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				powers = (int8*)ppr_get_ofdm_group(bw_pwrs, WL_TX_MODE_TXBF,
+					WL_TX_CHAINS_2);
+				ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+				mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1,
+					WL_TX_MODE_TXBF, WL_TX_CHAINS_2);
+				ASSERT(mcs_powers);
+				for (powers = mcs_powers;
+					powers < &mcs_powers[PPR_BF_CHAIN2_MCS_SIZE];
+					powers += WL_RATESET_SZ_VHT_MCS_P) {
+					ppr_force_disabled_group(powers, threshold,
+						WL_RATESET_SZ_VHT_MCS_P);
+				}
+			}
+#endif /* WL_BEAMFORMING */
+
+#if (PPR_MAX_TX_CHAINS > 2)
+			powers = (int8*)ppr_get_dsss_group(bw_pwrs, WL_TX_CHAINS_3);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_DSSS);
+
+			powers = (int8*)ppr_get_ofdm_group(bw_pwrs, WL_TX_MODE_CDD, WL_TX_CHAINS_3);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+			mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1, WL_TX_MODE_CDD,
+				WL_TX_CHAINS_3);
+			ASSERT(mcs_powers);
+			for (powers = mcs_powers; powers < &mcs_powers[PPR_CHAIN3_MCS_SIZE];
+				powers += WL_RATESET_SZ_VHT_MCS_P) {
+				ppr_force_disabled_group(powers, threshold,
+					WL_RATESET_SZ_VHT_MCS_P);
+			}
+
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				powers = (int8*)ppr_get_ofdm_group(bw_pwrs, WL_TX_MODE_TXBF,
+					WL_TX_CHAINS_3);
+				ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+				mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1,
+					WL_TX_MODE_TXBF, WL_TX_CHAINS_3);
+				ASSERT(mcs_powers);
+				for (powers = mcs_powers;
+					powers < &mcs_powers[PPR_BF_CHAIN3_MCS_SIZE];
+					powers += WL_RATESET_SZ_VHT_MCS_P) {
+					ppr_force_disabled_group(powers, threshold,
+						WL_RATESET_SZ_VHT_MCS_P);
+				}
+			}
+#endif /* WL_BEAMFORMING */
+#if (PPR_MAX_TX_CHAINS > 3)
+			powers = (int8*)ppr_get_dsss_group(bw_pwrs, WL_TX_CHAINS_4);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_DSSS);
+
+			powers = (int8*)ppr_get_ofdm_group(bw_pwrs, WL_TX_MODE_CDD, WL_TX_CHAINS_4);
+			ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+			mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1, WL_TX_MODE_CDD,
+				WL_TX_CHAINS_4);
+			ASSERT(mcs_powers);
+			for (powers = mcs_powers; powers < &mcs_powers[PPR_CHAIN4_MCS_SIZE];
+				powers += WL_RATESET_SZ_VHT_MCS_P) {
+				ppr_force_disabled_group(powers, threshold,
+					WL_RATESET_SZ_VHT_MCS_P);
+			}
+
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				powers = (int8*)ppr_get_ofdm_group(bw_pwrs, WL_TX_MODE_TXBF,
+					WL_TX_CHAINS_4);
+				ppr_force_disabled_group(powers, threshold, WL_RATESET_SZ_OFDM);
+
+				mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1,
+					WL_TX_MODE_TXBF, WL_TX_CHAINS_4);
+				ASSERT(mcs_powers);
+				for (powers = mcs_powers;
+					powers < &mcs_powers[PPR_BF_CHAIN4_MCS_SIZE];
+					powers += WL_RATESET_SZ_VHT_MCS_P) {
+					ppr_force_disabled_group(powers, threshold,
+						WL_RATESET_SZ_VHT_MCS_P);
+				}
+			}
+#endif /* WL_BEAMFORMING */
+#endif /* (PPR_MAX_TX_CHAINS > 3) */
+#endif /* (PPR_MAX_TX_CHAINS > 2) */
+#endif /* (PPR_MAX_TX_CHAINS > 1) */
+		}
+	}
+	return BCME_OK;
+}
+
+
+#if (PPR_MAX_TX_CHAINS > 1)
+/**
+ * LCN20 PHY doesn't support VHT rates, but it seems some of its regulatory data does. We need
+ * to explicitly disable the VHT rates so there's no temptation to use them.
+ */
+static void ppr_force_disabled_vht_in_group(int8* powers, uint len)
+{
+	uint i;
+
+	for (i = N_HT_SS_MCS; (i < len); i++) {
+		powers[i] = WL_RATE_DISABLED;
+	}
+}
+#endif /* (PPR_MAX_TX_CHAINS > 1) */
+
+
+/**
+ * LCN20 PHY doesn't support VHT MIMO rates, but it seems some of its regulatory data does. We need
+ * to explicitly disable the VHT MIMO rates so there's no temptation to use them.
+ */
+int
+ppr_disable_vht_mimo_rates(ppr_t* pprptr)
+{
+#if (PPR_MAX_TX_CHAINS > 1)
+	wl_tx_bw_t bw;
+
+	for (bw = WL_TX_BW_20; bw <= WL_TX_BW_80; bw++) {
+		pprpbw_t* bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+
+		if (bw_pwrs != NULL) {
+			int8* mcs_powers;
+			int8* powers;
+
+			mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1, WL_TX_MODE_CDD,
+				WL_TX_CHAINS_2);
+			ASSERT(mcs_powers);
+			/* skip CDD */
+			/* mcs_powers += WL_RATESET_SZ_VHT_MCS; */
+			for (powers = mcs_powers; powers < &mcs_powers[PPR_CHAIN2_MCS_SIZE];
+				powers += WL_RATESET_SZ_VHT_MCS) {
+				ppr_force_disabled_vht_in_group(powers, WL_RATESET_SZ_VHT_MCS);
+			}
+
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1,
+					WL_TX_MODE_TXBF, WL_TX_CHAINS_2);
+				ASSERT(mcs_powers);
+				for (powers = mcs_powers;
+					powers < &mcs_powers[PPR_BF_CHAIN2_MCS_SIZE];
+					powers += WL_RATESET_SZ_VHT_MCS) {
+					ppr_force_disabled_vht_in_group(powers,
+						WL_RATESET_SZ_VHT_MCS);
+				}
+			}
+#endif /* WL_BEAMFORMING */
+
+#if (PPR_MAX_TX_CHAINS > 2)
+			mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1, WL_TX_MODE_CDD,
+				WL_TX_CHAINS_3);
+			ASSERT(mcs_powers);
+			/* skip CDD */
+			/* mcs_powers += WL_RATESET_SZ_VHT_MCS; */
+			for (powers = mcs_powers; powers < &mcs_powers[PPR_CHAIN3_MCS_SIZE];
+				powers += WL_RATESET_SZ_VHT_MCS) {
+				ppr_force_disabled_vht_in_group(powers, WL_RATESET_SZ_VHT_MCS);
+			}
+
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1,
+					WL_TX_MODE_TXBF, WL_TX_CHAINS_3);
+				ASSERT(mcs_powers);
+				for (powers = mcs_powers;
+					powers < &mcs_powers[PPR_BF_CHAIN3_MCS_SIZE];
+					powers += WL_RATESET_SZ_VHT_MCS) {
+					ppr_force_disabled_vht_in_group(powers,
+						WL_RATESET_SZ_VHT_MCS);
+				}
+			}
+#endif /* WL_BEAMFORMING */
+
+#if (PPR_MAX_TX_CHAINS > 3)
+			mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1, WL_TX_MODE_CDD,
+				WL_TX_CHAINS_4);
+			ASSERT(mcs_powers);
+			/* skip CDD */
+			/* mcs_powers += WL_RATESET_SZ_VHT_MCS; */
+			for (powers = mcs_powers; powers < &mcs_powers[PPR_CHAIN4_MCS_SIZE];
+				powers += WL_RATESET_SZ_VHT_MCS) {
+				ppr_force_disabled_vht_in_group(powers, WL_RATESET_SZ_VHT_MCS);
+			}
+
+#ifdef WL_BEAMFORMING
+			if (PPR_TXBF_ENAB()) {
+				mcs_powers = (int8*)ppr_get_mcs_group(bw_pwrs, WL_TX_NSS_1,
+					WL_TX_MODE_TXBF, WL_TX_CHAINS_4);
+				ASSERT(mcs_powers);
+				for (powers = mcs_powers;
+					powers < &mcs_powers[PPR_BF_CHAIN4_MCS_SIZE];
+					powers += WL_RATESET_SZ_VHT_MCS) {
+					ppr_force_disabled_vht_in_group(powers,
+						WL_RATESET_SZ_VHT_MCS);
+				}
+			}
+#endif /* WL_BEAMFORMING */
+#endif /* (PPR_MAX_TX_CHAINS > 3) */
+#endif /* (PPR_MAX_TX_CHAINS > 2) */
+		}
+	}
+#endif /* (PPR_MAX_TX_CHAINS > 1) */
+	return BCME_OK;
+}
+
+
+#if (PPR_MAX_TX_CHAINS > 1)
+#define APPLY_CONSTRAINT(x, y, max) do {		\
+		ret += (y - x);							\
+		for (i = x; i < y; i++)					\
+			pprbuf[i] = MIN(pprbuf[i], max);	\
+	} while (0);
+
+
+/** Apply appropriate single-, two- and three-chain constraints across the appropriate ppr block */
+static uint ppr_apply_constraint_to_block(int8* pprbuf, int8 constraint)
+{
+	uint ret = 0;
+	uint i = 0;
+	int8 constraint_2chain = constraint - QDB(3);
+#if (PPR_MAX_TX_CHAINS > 2)
+	int8 constraint_3chain = constraint - (QDB(4) + 3); /* - 4.75dBm */
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+
+	APPLY_CONSTRAINT(PPR_CHAIN1_FIRST, PPR_CHAIN1_END, constraint);
+	APPLY_CONSTRAINT(PPR_CHAIN2_FIRST, PPR_CHAIN2_END, constraint_2chain);
+#if (PPR_MAX_TX_CHAINS > 2)
+	APPLY_CONSTRAINT(PPR_CHAIN3_FIRST, PPR_CHAIN3_END, constraint_3chain);
+#endif /* PPR_MAX_TX_CHAINS > 2 */
+	return ret;
+}
+#endif /* (PPR_MAX_TX_CHAINS > 1) */
+
+
+/**
+ * Reduce total transmitted power to level of constraint.
+ * For two chain rates, the per-antenna power must be halved.
+ * For three chain rates, it must be a third of the constraint.
+ */
+uint ppr_apply_constraint_total_tx(ppr_t* pprptr, int8 constraint)
+{
+	uint ret = 0;
+
+#if (PPR_MAX_TX_CHAINS > 1)
+	int8* pprbuf;
+	ASSERT(pprptr);
+
+	/**
+	 * TXPPR_TXPWR_MAX implies no constrains applied
+	 * so skip applying constrains for multiple chains
+	 */
+	if (constraint == TXPPR_TXPWR_MAX)
+		return ret;
+
+	switch (ppr_get_cur_bw(pprptr)) {
+	case WL_TX_BW_20:
+		{
+			pprbuf = (int8*)&pprptr->ppr_bw.ch20.b20;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+		}
+		break;
+	case WL_TX_BW_40:
+		{
+			pprbuf = (int8*)&pprptr->ppr_bw.ch40.b40;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch40.b20in40;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+		}
+		break;
+	case WL_TX_BW_80:
+		{
+			pprbuf = (int8*)&pprptr->ppr_bw.ch80.b80;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch80.b20in80;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch80.b40in80;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+		}
+		break;
+#ifdef WL11AC_160
+	case WL_TX_BW_160:
+		{
+			pprbuf = (int8*)&pprptr->ppr_bw.ch160.b160;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch160.b20in160;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch160.b40in160;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch160.b80in160;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+		}
+		break;
+#endif /* WL11AC_160 */
+#ifdef WL11AC_80P80
+	case WL_TX_BW_8080:
+		{
+			pprbuf = (int8*)&pprptr->ppr_bw.ch8080.b80ch1;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch8080.b80ch2;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch8080.b80in8080;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch8080.b20in8080;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+			pprbuf = (int8*)&pprptr->ppr_bw.ch8080.b40in8080;
+			ret += ppr_apply_constraint_to_block(pprbuf, constraint);
+		}
+		break;
+#endif /* WL11AC_80P80 */
+	default:
+		ASSERT(0);
+	}
+
+#else
+	ASSERT(pprptr);
+	ret = ppr_apply_max(pprptr, constraint);
+#endif /* PPR_MAX_TX_CHAINS > 1 */
+	return ret;
+}
+
+
+/** Ensure no rate limit is lower than the specified minimum */
+uint ppr_apply_min(ppr_t* pprptr, int8 minval)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->hdr); i++, rptr++) {
+		*rptr = MAX(*rptr, minval);
+	}
+	return i;
+}
+
+
+/** Ensure no rate limit in this ppr set is greater than the corresponding limit in ppr_cap */
+uint ppr_apply_vector_ceiling(ppr_t* pprptr, const ppr_t* ppr_cap)
+{
+	uint i = 0;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+	const int8* capptr = (const int8*)&ppr_cap->ppr_bw;
+
+	if (ppr_get_cur_bw(pprptr) == ppr_get_cur_bw(ppr_cap)) {
+		for (i = 0; i < ppr_pwrs_size(pprptr->hdr); i++, rptr++, capptr++) {
+			*rptr = MIN(*rptr, *capptr);
+		}
+	}
+	return i;
+}
+
+
+/** Ensure no rate limit in this ppr set is lower than the corresponding limit in ppr_min */
+uint ppr_apply_vector_floor(ppr_t* pprptr, const ppr_t* ppr_min)
+{
+	uint i = 0;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+	const int8* minptr = (const int8*)&ppr_min->ppr_bw;
+
+	if (ppr_get_cur_bw(pprptr) == ppr_get_cur_bw(ppr_min)) {
+		for (i = 0; i < ppr_pwrs_size(pprptr->hdr); i++, rptr++, minptr++) {
+			*rptr = MAX((uint8)*rptr, (uint8)*minptr);
+		}
+	}
+	return i;
+}
+
+
+/** Get the maximum power in the ppr set */
+int8 ppr_get_max(ppr_t* pprptr)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+	int8 maxval = *rptr++;
+
+	for (i = 1; i < ppr_pwrs_size(pprptr->hdr); i++, rptr++) {
+		maxval = MAX(maxval, *rptr);
+	}
+	return maxval;
+}
+
+/* Get the maximum power in the dsss ppr set */
+int8 ppr_get_dsss_max(ppr_t* pprptr, wl_tx_bw_t bw, wl_tx_chains_t tx_chains)
+{
+	ppr_dsss_rateset_t dsss;
+	uint8 rate;
+	int8 maxval = 0;
+	ppr_get_dsss(pprptr, bw, tx_chains, &dsss);
+	maxval = dsss.pwr[0];
+	for (rate = 1; rate < WL_RATESET_SZ_DSSS; rate++) {
+		maxval = MAX(maxval, dsss.pwr[rate]);
+	}
+	return maxval;
+}
+/**
+ * Get the minimum power in the ppr set, excluding disallowed
+ * rates and (possibly) powers set to the minimum for the phy
+ */
+int8 ppr_get_min(ppr_t* pprptr, int8 floor)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+	int8 minval = WL_RATE_DISABLED;
+
+	for (i = 0; (i < ppr_pwrs_size(pprptr->hdr)) && ((minval == WL_RATE_DISABLED) ||
+		(minval == floor)); i++, rptr++) {
+		minval = *rptr;
+	}
+	for (; i < ppr_pwrs_size(pprptr->hdr); i++, rptr++) {
+		if ((*rptr != WL_RATE_DISABLED) && (*rptr != floor))
+			minval = MIN(minval, *rptr);
+	}
+	return minval;
+}
+
+
+/** Get the maximum power for a given bandwidth in the ppr set */
+int8 ppr_get_max_for_bw(ppr_t* pprptr, wl_tx_bw_t bw)
+{
+	uint i;
+	const pprpbw_t* bw_pwrs;
+	const int8* rptr;
+	int8 maxval;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		rptr = (const int8*)bw_pwrs;
+		maxval = *rptr++;
+
+		for (i = 1; i < sizeof(*bw_pwrs); i++, rptr++) {
+			maxval = MAX(maxval, *rptr);
+		}
+	} else {
+		maxval = WL_RATE_DISABLED;
+	}
+	return maxval;
+}
+
+
+/** Get the minimum power for a given bandwidth  in the ppr set */
+int8 ppr_get_min_for_bw(ppr_t* pprptr, wl_tx_bw_t bw)
+{
+	uint i;
+	const pprpbw_t* bw_pwrs;
+	const int8* rptr;
+	int8 minval;
+
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	if (bw_pwrs != NULL) {
+		rptr = (const int8*)bw_pwrs;
+		minval = *rptr++;
+
+		for (i = 1; i < sizeof(*bw_pwrs); i++, rptr++) {
+			minval = MIN(minval, *rptr);
+		}
+	} else
+		minval = WL_RATE_DISABLED;
+	return minval;
+}
+
+
+/** Map the given function with its context value over the two power vectors */
+void
+ppr_map_vec_dsss(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2,
+	wl_tx_bw_t bw, wl_tx_chains_t tx_chains)
+{
+	pprpbw_t* bw_pwrs1;
+	pprpbw_t* bw_pwrs2;
+	int8* powers1;
+	int8* powers2;
+	uint i;
+
+	ASSERT(pprptr1);
+	ASSERT(pprptr2);
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, bw);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, bw);
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		powers1 = (int8*)ppr_get_dsss_group(bw_pwrs1, tx_chains);
+		powers2 = (int8*)ppr_get_dsss_group(bw_pwrs2, tx_chains);
+		if ((powers1 != NULL) && (powers2 != NULL)) {
+			for (i = 0; i < WL_RATESET_SZ_DSSS; i++)
+				(fn)(context, (uint8*)powers1++, (uint8*)powers2++);
+		}
+	}
+}
+
+
+/** Map the given function with its context value over the two power vectors */
+void
+ppr_map_vec_ofdm(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2,
+	wl_tx_bw_t bw, wl_tx_mode_t mode, wl_tx_chains_t tx_chains)
+{
+	pprpbw_t* bw_pwrs1;
+	pprpbw_t* bw_pwrs2;
+	int8* powers1;
+	int8* powers2;
+	uint i;
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, bw);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, bw);
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		powers1 = (int8*)ppr_get_ofdm_group(bw_pwrs1, mode, tx_chains);
+		powers2 = (int8*)ppr_get_ofdm_group(bw_pwrs2, mode, tx_chains);
+		if ((powers1 != NULL) && (powers2 != NULL)) {
+			for (i = 0; i < WL_RATESET_SZ_OFDM; i++)
+				(fn)(context, (uint8*)powers1++, (uint8*)powers2++);
+		}
+	}
+}
+
+
+/** Map the given function with its context value over the two power vectors */
+void
+ppr_map_vec_ht_mcs(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode,
+	wl_tx_chains_t tx_chains)
+{
+	pprpbw_t* bw_pwrs1;
+	pprpbw_t* bw_pwrs2;
+	int8* powers1;
+	int8* powers2;
+	uint i;
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, bw);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, bw);
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		powers1 = (int8*)ppr_get_mcs_group(bw_pwrs1, Nss, mode, tx_chains);
+		powers2 = (int8*)ppr_get_mcs_group(bw_pwrs2, Nss, mode, tx_chains);
+		if ((powers1 != NULL) && (powers2 != NULL)) {
+			for (i = 0; i < WL_RATESET_SZ_HT_MCS; i++)
+				(fn)(context, (uint8*)powers1++, (uint8*)powers2++);
+		}
+	}
+}
+
+
+/** Map the given function with its context value over the two power vectors */
+void
+ppr_map_vec_vht_mcs(ppr_mapfn_t fn, void* context, ppr_t* pprptr1,
+	ppr_t* pprptr2, wl_tx_bw_t bw, wl_tx_nss_t Nss, wl_tx_mode_t mode, wl_tx_chains_t
+	tx_chains)
+{
+	pprpbw_t* bw_pwrs1;
+	pprpbw_t* bw_pwrs2;
+	int8* powers1;
+	int8* powers2;
+	uint i;
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, bw);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, bw);
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		powers1 = (int8*)ppr_get_mcs_group(bw_pwrs1, Nss, mode, tx_chains);
+		powers2 = (int8*)ppr_get_mcs_group(bw_pwrs2, Nss, mode, tx_chains);
+		if ((powers1 != NULL) && (powers2 != NULL)) {
+			for (i = 0; i < WL_RATESET_SZ_VHT_MCS; i++)
+				(fn)(context, (uint8*)powers1++, (uint8*)powers2++);
+		}
+	}
+}
+
+static bool
+ppr_map_vec_per_bw(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2, wl_tx_bw_t bw)
+{
+	uint i;
+	pprpbw_t* bw_pwrs1;
+	pprpbw_t* bw_pwrs2;
+	int8* rptr1 = (int8*)&pprptr1->ppr_bw;
+	int8* rptr2 = (int8*)&pprptr2->ppr_bw;
+	bool ret = TRUE;
+
+	bw_pwrs1 = ppr_get_bw_powers(pprptr1, bw);
+	bw_pwrs2 = ppr_get_bw_powers(pprptr2, bw);
+
+	if ((bw_pwrs1 != NULL) && (bw_pwrs2 != NULL)) {
+		rptr1 = (int8*)bw_pwrs1;
+		rptr2 = (int8*)bw_pwrs2;
+		for (i = 0; i < sizeof(pprpbw_t); i++, rptr1++, rptr2++) {
+			(fn)(context, (uint8*)rptr1, (uint8*)rptr2);
+		}
+	} else {
+		ret = FALSE;
+	}
+	return ret;
+}
+
+/** Map the given function with its context value over the two power vectors */
+
+void
+ppr_map_vec_all(ppr_mapfn_t fn, void* context, ppr_t* pprptr1, ppr_t* pprptr2)
+{
+	(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_20);
+
+	if (ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_40)) {
+		(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_20IN40);
+	}
+
+	if (ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_80)) {
+		(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_20IN80);
+		(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_40IN80);
+	}
+
+	if (ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_160)) {
+		(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_20IN160);
+		(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_40IN160);
+		(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_80IN160);
+	}
+
+	if (ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_8080)) {
+		(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_20IN8080);
+		(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_40IN8080);
+		(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_80IN8080);
+		(void)ppr_map_vec_per_bw(fn, context, pprptr1, pprptr2, WL_TX_BW_8080CHAN2);
+	}
+}
+
+
+/** Set PPR struct to a certain power level */
+void
+ppr_set_cmn_val(ppr_t* pprptr, int8 val)
+{
+	memset((uchar*)&pprptr->ppr_bw, val, ppr_pwrs_size(pprptr->hdr));
+}
+
+
+/** Make an identical copy of a ppr structure (for ppr_bw==all case) */
+void
+ppr_copy_struct(ppr_t* pprptr_s, ppr_t* pprptr_d)
+{
+	int8* rptr_s = (int8*)&pprptr_s->ppr_bw;
+	int8* rptr_d = (int8*)&pprptr_d->ppr_bw;
+	/* ASSERT(ppr_pwrs_size(pprptr_d->hdr) >= ppr_pwrs_size(pprptr_s->hdr)); */
+
+	if (ppr_get_cur_bw(pprptr_s) ==
+		ppr_get_cur_bw(pprptr_d))
+		memcpy(rptr_d, rptr_s, ppr_pwrs_size(pprptr_s->hdr));
+	else {
+		const pprpbw_t* src_bw_pwrs;
+		pprpbw_t* dest_bw_pwrs;
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_20);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_20);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_40);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_40);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_20IN40);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_20IN40);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_80);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_80);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_20IN80);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_20IN80);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_40IN80);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_40IN80);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_160);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_160);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_20IN160);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_20IN160);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_40IN160);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_40IN160);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_80IN160);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_80IN160);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_8080);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_8080);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_8080CHAN2);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_8080CHAN2);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_20IN8080);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_20IN8080);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_40IN8080);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_40IN8080);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+
+		src_bw_pwrs = ppr_get_bw_powers(pprptr_s, WL_TX_BW_80IN8080);
+		dest_bw_pwrs = ppr_get_bw_powers(pprptr_d, WL_TX_BW_80IN8080);
+		if (src_bw_pwrs && dest_bw_pwrs)
+			bcopy((const uint8*)src_bw_pwrs, (uint8*)dest_bw_pwrs,
+				sizeof(*src_bw_pwrs));
+	}
+}
+
+
+/** Subtract each power from a common value and re-store */
+void
+ppr_cmn_val_minus(ppr_t* pprptr, int8 val)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->hdr); i++, rptr++) {
+		if (*rptr != (int8)WL_RATE_DISABLED)
+			*rptr = val - *rptr;
+	}
+
+}
+
+
+/** Subtract a common value from each power and re-store */
+void
+ppr_minus_cmn_val(ppr_t* pprptr, int8 val)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->hdr); i++, rptr++) {
+		if (*rptr != (int8)WL_RATE_DISABLED)
+			*rptr = *rptr - val;
+	}
+
+}
+
+
+/** Add a common value to each power and re-store */
+void
+ppr_plus_cmn_val(ppr_t* pprptr, int8 val)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->hdr); i++, rptr++) {
+		if (*rptr != (int8)WL_RATE_DISABLED)
+			*rptr += val;
+	}
+
+}
+
+
+/** Multiply by a percentage */
+void
+ppr_multiply_percentage(ppr_t* pprptr, uint8 val)
+{
+	uint i;
+	int8* rptr = (int8*)&pprptr->ppr_bw;
+
+	for (i = 0; i < ppr_pwrs_size(pprptr->hdr); i++, rptr++) {
+		if (*rptr != (int8)WL_RATE_DISABLED)
+			*rptr = (*rptr * val) / 100;
+	}
+
+}
+
+
+/**
+ * Compare two ppr variables p1 and p2, save the min value of each
+ * contents to variable p1
+ */
+void
+ppr_compare_min(ppr_t* p1, ppr_t* p2)
+{
+	uint i;
+	int8* rptr1 = NULL;
+	int8* rptr2 = NULL;
+	uint32 pprsize = 0;
+
+	if (ppr_get_cur_bw(p1) == ppr_get_cur_bw(p2)) {
+		rptr1 = (int8*)&p1->ppr_bw;
+		rptr2 = (int8*)&p2->ppr_bw;
+		pprsize = ppr_pwrs_size(p1->hdr);
+	}
+
+	for (i = 0; i < pprsize; i++, rptr1++, rptr2++) {
+		*rptr1 = MIN(*rptr1, *rptr2);
+	}
+}
+
+
+/**
+ * Compare two ppr variables p1 and p2, save the max. value of each
+ * contents to variable p1
+ */
+void
+ppr_compare_max(ppr_t* p1, ppr_t* p2)
+{
+	uint i;
+	int8* rptr1 = NULL;
+	int8* rptr2 = NULL;
+	uint32 pprsize = 0;
+
+	if (ppr_get_cur_bw(p1) == ppr_get_cur_bw(p2)) {
+		rptr1 = (int8*)&p1->ppr_bw;
+		rptr2 = (int8*)&p2->ppr_bw;
+		pprsize = ppr_pwrs_size(p1->hdr);
+	}
+
+	for (i = 0; i < pprsize; i++, rptr1++, rptr2++) {
+		*rptr1 = MAX(*rptr1, *rptr2);
+	}
+}
+
+
+/**
+ * Serialize the contents of the opaque ppr struct.
+ * Writes number of bytes copied, zero on error.
+ * Returns error code, BCME_OK if successful.
+ */
+int
+ppr_serialize(const ppr_t* pprptr, uint8* buf, uint buflen, uint* bytes_copied)
+{
+	int err = BCME_OK;
+	if (buflen <= sizeof(ppr_ser_mem_flag_t)) {
+		err = BCME_BUFTOOSHORT;
+	} else {
+		ppr_ser_mem_flag_t *smem_flag = (ppr_ser_mem_flag_t *)buf;
+		uint32 flag = NTOH32(smem_flag->flag);
+
+		/* check if memory contains a valid flag, if not, use current
+		 * condition (num of chains, txbf etc.) to serialize data.
+		 */
+		if (NTOH32(smem_flag->magic_word) != PPR_SER_MEM_WORD) {
+			flag = ppr_get_flag();
+		}
+
+		if (buflen >= ppr_ser_size_by_flag(flag, ppr_get_cur_bw(pprptr))) {
+			*bytes_copied = ppr_serialize_data(pprptr, buf, flag);
+		} else {
+			err = BCME_BUFTOOSHORT;
+		}
+	}
+	return err;
+}
+
+
+/**
+ * Deserialize the contents of a buffer into an opaque ppr struct.
+ * Creates an opaque structure referenced by *pptrptr, NULL on error.
+ * Returns error code, BCME_OK if successful.
+ */
+int
+ppr_deserialize_create(osl_t *osh, const uint8* buf, uint buflen, ppr_t** pprptr)
+{
+	const uint8* bptr = buf;
+	int err = BCME_OK;
+	ppr_t* lpprptr = NULL;
+
+	if ((buflen > SER_HDR_LEN) && (bptr != NULL) && (*bptr == PPR_SERIALIZATION_VER)) {
+		const ppr_deser_header_t * ser_head = (const ppr_deser_header_t *)bptr;
+		wl_tx_bw_t ch_bw = ser_head->bw;
+		/* struct size plus header */
+		uint32 ser_size = ppr_pwrs_size((ch_bw)) + SER_HDR_LEN;
+
+		if ((lpprptr = ppr_create(osh, ch_bw)) != NULL) {
+			uint32 flags = NTOH32(ser_head->flags);
+			uint16 per_band_size = NTOH16(ser_head->per_band_size);
+			/* set the data with default value before deserialize */
+			ppr_set_cmn_val(lpprptr, WL_RATE_DISABLED);
+
+			ppr_deser_cpy(lpprptr, bptr + sizeof(*ser_head), flags, ch_bw,
+				per_band_size);
+		} else if (buflen < ser_size) {
+			err = BCME_BUFTOOSHORT;
+		} else {
+			err = BCME_NOMEM;
+		}
+	} else if (buflen <= SER_HDR_LEN) {
+		err = BCME_BUFTOOSHORT;
+	} else if (bptr == NULL) {
+		err = BCME_BADARG;
+	} else {
+		err = BCME_VERSION;
+	}
+	*pprptr = lpprptr;
+	return err;
+}
+
+
+/**
+ * Deserialize the contents of a buffer into an opaque ppr struct.
+ * Creates an opaque structure referenced by *pptrptr, NULL on error.
+ * Returns error code, BCME_OK if successful.
+ */
+int
+ppr_deserialize(ppr_t* pprptr, const uint8* buf, uint buflen)
+{
+	const uint8* bptr = buf;
+	int err = BCME_OK;
+	ASSERT(pprptr);
+	if ((buflen > SER_HDR_LEN) && (bptr != NULL) && (*bptr == PPR_SERIALIZATION_VER)) {
+		const ppr_deser_header_t * ser_head = (const ppr_deser_header_t *)bptr;
+		wl_tx_bw_t ch_bw = ser_head->bw;
+
+		if (ch_bw == ppr_get_cur_bw(pprptr)) {
+			uint32 flags = NTOH32(ser_head->flags);
+			uint16 per_band_size = NTOH16(ser_head->per_band_size);
+			ppr_set_cmn_val(pprptr, WL_RATE_DISABLED);
+			ppr_deser_cpy(pprptr, bptr + sizeof(*ser_head), flags, ch_bw,
+				per_band_size);
+		} else {
+			err = BCME_BADARG;
+		}
+	} else if (buflen <= SER_HDR_LEN) {
+		err = BCME_BUFTOOSHORT;
+	} else if (bptr == NULL) {
+		err = BCME_BADARG;
+	} else {
+		err = BCME_VERSION;
+	}
+	return err;
+}
+
+/* Get transmit channel bandwidths from chanspec */
+wl_tx_bw_t ppr_chanspec_bw(chanspec_t chspec)
+{
+	uint chspec_bw = CHSPEC_BW(chspec);
+	wl_tx_bw_t ret = WL_TX_BW_20;
+	switch (chspec_bw) {
+	case WL_CHANSPEC_BW_2P5:
+	case WL_CHANSPEC_BW_5:
+	case WL_CHANSPEC_BW_10:
+	case WL_CHANSPEC_BW_20:
+		ret = WL_TX_BW_20;
+		break;
+	case WL_CHANSPEC_BW_40:
+		ret = WL_TX_BW_40;
+		break;
+	case WL_CHANSPEC_BW_80:
+		ret = WL_TX_BW_80;
+		break;
+	case WL_CHANSPEC_BW_160:
+		ret = WL_TX_BW_160;
+		break;
+	case WL_CHANSPEC_BW_8080:
+		ret = WL_TX_BW_8080;
+		break;
+	default :
+		ASSERT(0);
+	}
+	return ret;
+}
+
+#if defined(WL_EXPORT_CURPOWER) || !defined(BCMDRIVER)
+
+#define DSSS_TLV_LEN (sizeof(ppr_dsss_tlv_t) + sizeof(ppr_dsss_rateset_t))
+#define OFDM_TLV_LEN (sizeof(ppr_ofdm_tlv_t) + sizeof(ppr_ofdm_rateset_t))
+#define MCS_TLV_LEN (sizeof(ppr_mcs_tlv_t) + sizeof(ppr_vht_mcs_rateset_t))
+#define PPR_TLV_VER_SIZE (sizeof(int8))
+
+/* Fill DSSS TLV data into the given buffer */
+static uint32
+ppr_to_dssstlv_per_band(ppr_t* pprptr, wl_tx_bw_t bw, uint8 **to_tlv_buf, uint32 tlv_buf_len,
+	wl_tx_chains_t max_chain)
+{
+	uint32 len = 0;
+	wl_tx_chains_t chain;
+
+	pprpbw_t* bw_pwrs;
+	bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	for (chain = WL_TX_CHAINS_1; chain <= max_chain; chain++) {
+		bcm_tlv_t *tlv_hdr = (bcm_tlv_t *)(*to_tlv_buf);
+		ppr_dsss_tlv_t *dsss_tlv = (ppr_dsss_tlv_t *)tlv_hdr->data;
+		if (len + DSSS_TLV_LEN + BCM_TLV_HDR_SIZE <= tlv_buf_len) {
+			const int8* powers;
+			bool found = FALSE;
+
+			if (bw_pwrs != NULL) {
+				powers = ppr_get_dsss_group(bw_pwrs, chain);
+				if (powers) {
+					memcpy(dsss_tlv->pwr, powers, sizeof(ppr_dsss_rateset_t));
+					found = TRUE;
+				}
+			}
+
+			if (found) {
+				tlv_hdr->id = PPR_RGRP_DSSS_ID;
+				tlv_hdr->len = DSSS_TLV_LEN;
+				dsss_tlv->bw = bw;
+				dsss_tlv->chains = (uint8)chain;
+				len += (DSSS_TLV_LEN + BCM_TLV_HDR_SIZE);
+				*to_tlv_buf += (DSSS_TLV_LEN + BCM_TLV_HDR_SIZE);
+			}
+		} else {
+			break;
+		}
+	}
+	return len;
+}
+
+/* Fill OFDM TLV data into the given buffer */
+static uint32
+ppr_to_ofdmtlv_per_band(ppr_t* pprptr, wl_tx_bw_t bw, uint8 **to_tlv_buf, uint32 tlv_buf_len,
+	wl_tx_chains_t max_chain)
+{
+	uint32 len = 0;
+	wl_tx_chains_t chain;
+	wl_tx_mode_t mode;
+	pprpbw_t* bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	for (chain = WL_TX_CHAINS_1; chain <= max_chain; chain++) {
+		for (mode = WL_TX_MODE_NONE; mode < WL_NUM_TX_MODES; mode ++) {
+			bcm_tlv_t *tlv_hdr = (bcm_tlv_t *)(*to_tlv_buf);
+			ppr_ofdm_tlv_t *ofdm_tlv = (ppr_ofdm_tlv_t *)tlv_hdr->data;
+			const int8* powers;
+			bool found = FALSE;
+			if (len + OFDM_TLV_LEN + BCM_TLV_HDR_SIZE <= tlv_buf_len) {
+				if (bw_pwrs != NULL) {
+					powers = ppr_get_ofdm_group(bw_pwrs, mode, chain);
+					if (powers != NULL) {
+						memcpy(ofdm_tlv->pwr, powers,
+							sizeof(ppr_ofdm_rateset_t));
+						found = TRUE;
+					}
+				}
+				if (found) {
+					tlv_hdr->id = PPR_RGRP_OFDM_ID;
+					tlv_hdr->len = OFDM_TLV_LEN;
+					ofdm_tlv->bw = bw;
+					ofdm_tlv->chains = (uint8)chain;
+					ofdm_tlv->mode = mode;
+
+					len += (OFDM_TLV_LEN + BCM_TLV_HDR_SIZE);
+					*to_tlv_buf += (OFDM_TLV_LEN + BCM_TLV_HDR_SIZE);
+				}
+			} else {
+				return len;
+			}
+		}
+
+	}
+	return len;
+}
+
+/* Fill MCS TLV data into the given buffer */
+static uint32
+ppr_to_mcstlv_per_band(ppr_t* pprptr, wl_tx_bw_t bw, uint8 **to_tlv_buf, uint32 tlv_buf_len,
+	wl_tx_chains_t max_chain)
+{
+	uint32 len = 0;
+	wl_tx_chains_t chain;
+	wl_tx_mode_t mode;
+	uint8 nss;
+	pprpbw_t* bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	for (chain = WL_TX_CHAINS_1; chain <= max_chain; chain++) {
+		for (nss = WL_TX_NSS_1; nss <= chain; nss++) {
+			for (mode = WL_TX_MODE_NONE; mode < WL_NUM_TX_MODES; mode ++) {
+				bcm_tlv_t *tlv_hdr = (bcm_tlv_t *)(*to_tlv_buf);
+				ppr_mcs_tlv_t *mcs_tlv = (ppr_mcs_tlv_t *)tlv_hdr->data;
+				if (len + MCS_TLV_LEN + BCM_TLV_HDR_SIZE <= tlv_buf_len) {
+					const int8* powers;
+					bool found = FALSE;
+					if (bw_pwrs != NULL) {
+						powers = ppr_get_mcs_group(bw_pwrs, nss, mode,
+							chain);
+						if (powers != NULL) {
+							memcpy(mcs_tlv->pwr, powers,
+								sizeof(ppr_vht_mcs_rateset_t));
+							found = TRUE;
+						}
+					}
+
+					if (found) {
+						tlv_hdr->id = PPR_RGRP_MCS_ID;
+						tlv_hdr->len = MCS_TLV_LEN;
+						mcs_tlv->bw = bw;
+						mcs_tlv->chains = (uint8)chain;
+						mcs_tlv->mode = mode;
+						mcs_tlv->nss = nss;
+						len += (MCS_TLV_LEN + BCM_TLV_HDR_SIZE);
+						*to_tlv_buf += (MCS_TLV_LEN + BCM_TLV_HDR_SIZE);
+					}
+				} else {
+					return len;
+				}
+			}
+		}
+	}
+	return len;
+}
+
+/* Convert ppr structure to TLV data */
+void ppr_convert_to_tlv(ppr_t* pprptr, wl_tx_bw_t bw, uint8 *to_tlv_buf, uint32 tlv_buf_len,
+	wl_tx_chains_t max_chain)
+{
+	uint32 len = tlv_buf_len;
+	wl_tx_bw_t check_bw;
+	ASSERT(pprptr && to_tlv_buf);
+	to_tlv_buf[0] = PPR_TLV_VER;
+	to_tlv_buf++;
+	switch (bw) {
+	case WL_TX_BW_2P5:
+	case WL_TX_BW_5:
+	case WL_TX_BW_10:
+	case WL_TX_BW_20:
+		len -= ppr_to_dssstlv_per_band(pprptr, bw, &to_tlv_buf, len, max_chain);
+		len -= ppr_to_ofdmtlv_per_band(pprptr, bw, &to_tlv_buf, len, max_chain);
+		ppr_to_mcstlv_per_band(pprptr, bw, &to_tlv_buf, len, max_chain);
+		break;
+	case WL_TX_BW_40:
+		len -= ppr_to_dssstlv_per_band(pprptr, WL_TX_BW_20IN40, &to_tlv_buf, len,
+			max_chain);
+		len -= ppr_to_ofdmtlv_per_band(pprptr, WL_TX_BW_20IN40, &to_tlv_buf, len,
+			max_chain);
+		len -= ppr_to_mcstlv_per_band(pprptr, WL_TX_BW_20IN40, &to_tlv_buf, len,
+			max_chain);
+		len -= ppr_to_ofdmtlv_per_band(pprptr, WL_TX_BW_40, &to_tlv_buf, len, max_chain);
+		len -= ppr_to_mcstlv_per_band(pprptr, WL_TX_BW_40, &to_tlv_buf, len, max_chain);
+		break;
+	case WL_TX_BW_80:
+		for (check_bw = WL_TX_BW_80; check_bw <= WL_TX_BW_40IN80; check_bw++) {
+			if (check_bw == WL_TX_BW_20IN40)
+				continue;
+			if (check_bw == WL_TX_BW_20IN80) {
+				len -= ppr_to_dssstlv_per_band(pprptr, check_bw, &to_tlv_buf, len,
+					max_chain);
+			}
+			len -= ppr_to_ofdmtlv_per_band(pprptr, check_bw, &to_tlv_buf, len,
+				max_chain);
+			len -= ppr_to_mcstlv_per_band(pprptr, check_bw, &to_tlv_buf, len,
+				max_chain);
+		}
+		break;
+	case WL_TX_BW_160:
+		for (check_bw = WL_TX_BW_160; check_bw <= WL_TX_BW_80IN160; check_bw++) {
+			if (check_bw == WL_TX_BW_20IN160) {
+				len -= ppr_to_dssstlv_per_band(pprptr, check_bw, &to_tlv_buf, len,
+					max_chain);
+			}
+			len -= ppr_to_ofdmtlv_per_band(pprptr, check_bw, &to_tlv_buf, len,
+				max_chain);
+			len -= ppr_to_mcstlv_per_band(pprptr, check_bw, &to_tlv_buf, len,
+				max_chain);
+		}
+		break;
+	case WL_TX_BW_8080:
+		for (check_bw = WL_TX_BW_8080; check_bw <= WL_TX_BW_80IN8080; check_bw++) {
+			if (check_bw == WL_TX_BW_20IN8080) {
+				len -= ppr_to_dssstlv_per_band(pprptr, WL_TX_BW_8080, &to_tlv_buf,
+					len, max_chain);
+			}
+			len -= ppr_to_ofdmtlv_per_band(pprptr, check_bw, &to_tlv_buf, len,
+				max_chain);
+			len -= ppr_to_mcstlv_per_band(pprptr, check_bw, &to_tlv_buf, len,
+				max_chain);
+		}
+		break;
+	default:
+		break;
+	};
+}
+
+/* Convert TLV data to ppr structure */
+int ppr_convert_from_tlv(ppr_t* pprptr, uint8 *from_tlv_buf, uint32 tlv_buf_len)
+{
+	uint8 ser_ver = from_tlv_buf[0];
+	bcm_tlv_t *elt = (bcm_tlv_t *)(&from_tlv_buf[1]);
+	int ret = BCME_OK;
+	if (ser_ver != PPR_TLV_VER) {
+		ret = BCME_VERSION;
+	} else {
+		do {
+			switch (elt->id) {
+			case PPR_RGRP_DSSS_ID:
+				{
+					ppr_dsss_tlv_t *dsss_tlv = (ppr_dsss_tlv_t *)elt->data;
+					ppr_set_dsss(pprptr, dsss_tlv->bw, dsss_tlv->chains,
+						(ppr_dsss_rateset_t*)dsss_tlv->pwr);
+				}
+				break;
+			case PPR_RGRP_OFDM_ID:
+				{
+					ppr_ofdm_tlv_t *ofdm_tlv = (ppr_ofdm_tlv_t *)elt->data;
+					ppr_set_ofdm(pprptr, ofdm_tlv->bw, ofdm_tlv->mode,
+						ofdm_tlv->chains,
+						(ppr_ofdm_rateset_t*)(ofdm_tlv->pwr));
+				}
+				break;
+			case PPR_RGRP_MCS_ID:
+				{
+					ppr_mcs_tlv_t *mcs_tlv = (ppr_mcs_tlv_t *)elt->data;
+					ppr_set_vht_mcs(pprptr, mcs_tlv->bw, mcs_tlv->nss,
+						mcs_tlv->mode, mcs_tlv->chains,
+						(ppr_vht_mcs_rateset_t*)mcs_tlv->pwr);
+				}
+				break;
+			default:
+				ASSERT(0);
+				break;
+			}
+
+		} while ((elt = bcm_next_tlv(elt, (int *)&tlv_buf_len)) != NULL);
+	}
+	return ret;
+}
+
+/* Get the required buffer size for DSSS TLV data */
+static uint32 ppr_get_tlv_size_dsss(uint32 max_chain)
+{
+	uint32 size = 0;
+	uint32 chain;
+	for (chain = 1; chain <= max_chain; chain++) {
+		size += (DSSS_TLV_LEN + BCM_TLV_HDR_SIZE);
+	}
+	return size;
+}
+
+/* Get the required buffer size for MCS/OFDM TLV data */
+static uint32 ppr_get_ofdmmcs_size(ppr_t* pprptr, uint32 max_chain, wl_tx_bw_t bw)
+{
+	uint32 size = 0;
+	uint32 chain;
+	wl_tx_mode_t mode;
+	uint32 nss;
+	const int8* powers;
+	pprpbw_t* bw_pwrs = ppr_get_bw_powers(pprptr, bw);
+	for (chain = 1; chain <= max_chain; chain++) {
+		for (mode = WL_TX_MODE_NONE; mode < WL_NUM_TX_MODES; mode ++) {
+			if (bw_pwrs != NULL) {
+				powers = ppr_get_ofdm_group(bw_pwrs, mode, chain);
+				if (powers != NULL) {
+					size += (OFDM_TLV_LEN + BCM_TLV_HDR_SIZE);
+				}
+				for (nss = WL_TX_NSS_1; nss <= chain; nss++) {
+					powers = ppr_get_mcs_group(bw_pwrs, nss, mode,
+						chain);
+					if (powers != NULL) {
+						size += (MCS_TLV_LEN + BCM_TLV_HDR_SIZE);
+					}
+				}
+			}
+		}
+	}
+	return size;
+}
+
+/* Get the total TLV buffer size for the given ppr data of bandwidth and max chains */
+uint32 ppr_get_tlv_size(ppr_t* pprptr, wl_tx_bw_t bw, uint32 max_chain)
+{
+	uint32 dsss_size = ppr_get_tlv_size_dsss(max_chain);
+	uint32 mcs_ofdm_size = ppr_get_ofdmmcs_size(pprptr, max_chain, bw);
+	uint32 ret = PPR_TLV_VER_SIZE;
+	switch (bw) {
+	case WL_TX_BW_2P5:
+	case WL_TX_BW_5:
+	case WL_TX_BW_10:
+	case WL_TX_BW_20:
+		ret += (dsss_size + mcs_ofdm_size);
+		break;
+	case WL_TX_BW_40:
+		/* 20IN40 and 40 */
+		ret += (dsss_size + 2*mcs_ofdm_size);
+		break;
+	case WL_TX_BW_80:
+		/* 20IN80, 40IN80,80 */
+		ret += (dsss_size + 3*mcs_ofdm_size);
+		break;
+	case WL_TX_BW_160:
+		/* 20IN160, 40IN160, 80IN160, 160 */
+		ret += (dsss_size + 4*mcs_ofdm_size);
+		break;
+	case WL_TX_BW_8080:
+		/* 20IN8080, 40IN8080, 80IN8080, 8080, 8080CHAN2 */
+		ret += (dsss_size + 5*mcs_ofdm_size);
+		break;
+	default:
+		ret = 0;
+		ASSERT(0);
+		break;
+	};
+
+	return ret;
+}
+
+/* Get current PPR TLV version */
+uint32 ppr_get_tlv_ver(void)
+{
+	return PPR_TLV_VER;
+}
+
+#endif /* WL_EXPORT_CURPOWER || !BCMDRIVER */
+
+#ifdef WLTXPWR_CACHE
+
+#define MAX_TXPWR_CACHE_ENTRIES 2
+#define TXPWR_ALL_INVALID	 0xff
+#define TXPWR_CACHE_TXPWR_MAX 0x7f             /* WLC_TXPWR_MAX; */
+#define TXPWR_CACHE_SARLIMS_MAX ((TXPWR_CACHE_TXPWR_MAX << 24) \
+	| (TXPWR_CACHE_TXPWR_MAX << 16) | (TXPWR_CACHE_TXPWR_MAX << 8) \
+	| TXPWR_CACHE_TXPWR_MAX)
+
+/** transmit power cache */
+struct tx_pwr_cache_entry {
+	chanspec_t chanspec;
+	ppr_t* cache_pwrs[TXPWR_CACHE_NUM_TYPES];
+	uint8 tx_pwr_max[PPR_MAX_TX_CHAINS];
+	uint8 tx_pwr_min[PPR_MAX_TX_CHAINS];
+	int8 txchain_offsets[PPR_MAX_TX_CHAINS];
+	uint8 data_invalid_flags;
+	uint8 stf_tx_max_offset;
+#ifdef WL_SARLIMIT
+	uint32 sar_lims;
+#endif
+	int8 tx_pwr_max_boardlim[PPR_MAX_TX_CHAINS];
+};
+
+#ifdef TXPWR_CACHE_IN_ROM
+uint8 txpwr_cache[MAX_TXPWR_CACHE_ENTRIES*16] = {0};
+#endif
+
+#ifndef WLTXPWR_CACHE_PHY_ONLY
+static int stf_tx_pwr_min = TXPWR_CACHE_TXPWR_MAX;
+#endif
+
+static tx_pwr_cache_entry_t* wlc_phy_txpwr_cache_get_entry(tx_pwr_cache_entry_t* cacheptr,
+	chanspec_t chanspec);
+static tx_pwr_cache_entry_t* wlc_phy_txpwr_cache_get_diff_entry(tx_pwr_cache_entry_t* cacheptr,
+	chanspec_t chanspec);
+static void wlc_phy_txpwr_cache_clear_entry(osl_t *osh, tx_pwr_cache_entry_t* entryptr);
+static tx_pwr_cache_entry_t* tx_pwr_cache_get(tx_pwr_cache_entry_t* cacheptr, uint32 idx);
+
+static tx_pwr_cache_entry_t*
+BCMRAMFN(tx_pwr_cache_get)(tx_pwr_cache_entry_t* tx_pwr_cache, uint32 idx)
+{
+	return (&tx_pwr_cache[idx]);
+}
+
+/** Find a cache entry for the specified chanspec. */
+static tx_pwr_cache_entry_t* wlc_phy_txpwr_cache_get_entry(tx_pwr_cache_entry_t* cacheptr,
+	chanspec_t chanspec)
+{
+	uint i;
+	tx_pwr_cache_entry_t* entryptr = NULL;
+
+	for (i = 0; i < (MAX_TXPWR_CACHE_ENTRIES); i++) {
+		entryptr = tx_pwr_cache_get(cacheptr, i);
+		if (entryptr->chanspec == chanspec) {
+			return entryptr;
+		}
+	}
+	return NULL;
+}
+
+
+/** Find a cache entry that's NOT for the specified chanspec. */
+static tx_pwr_cache_entry_t* wlc_phy_txpwr_cache_get_diff_entry(tx_pwr_cache_entry_t* cacheptr,
+	chanspec_t chanspec)
+{
+	uint i;
+	tx_pwr_cache_entry_t* entryptr = NULL;
+
+	for (i = 0; i < (MAX_TXPWR_CACHE_ENTRIES) && (entryptr == NULL); i++) {
+		if (tx_pwr_cache_get(cacheptr, i)->chanspec != chanspec) {
+			entryptr = tx_pwr_cache_get(cacheptr, i);
+		}
+	}
+	return entryptr;
+}
+
+
+/** Clear a specific cache entry. Delete any ppr_t structs and clear the pointers. */
+static void wlc_phy_txpwr_cache_clear_entry(osl_t *osh, tx_pwr_cache_entry_t* entryptr)
+{
+	uint i;
+
+	entryptr->chanspec = 0;
+
+	ASSERT(entryptr != NULL);
+	for (i = 0; i < TXPWR_CACHE_NUM_TYPES; i++) {
+		if (entryptr->cache_pwrs[i] != NULL) {
+			ppr_delete(osh, entryptr->cache_pwrs[i]);
+			entryptr->cache_pwrs[i] = NULL;
+		}
+	}
+	/*
+	 * Don't bother with max, min and txchain_offsets, as they need to be
+	 * initialised when the entry is setup for a new chanspec
+	 */
+}
+
+
+/**
+ * Get a ppr_t struct of a given type from the cache for the specified chanspec.
+ * Don't return the pointer if the cached data is invalid.
+ */
+bool wlc_phy_get_cached_pwr(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec, uint pwr_type,
+	ppr_t* pprptr)
+{
+	bool ret = FALSE;
+	if (pwr_type < TXPWR_CACHE_NUM_TYPES) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if ((entryptr != NULL) &&
+			((entryptr->data_invalid_flags & (0x01 << pwr_type)) == 0)) {
+			ppr_copy_struct(entryptr->cache_pwrs[pwr_type], pprptr);
+			ret = TRUE;
+		}
+	}
+
+	return ret;
+}
+
+
+int wlc_phy_set_cached_pwr(osl_t* osh, tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint pwr_type, ppr_t* pwrptr)
+{
+	int result = BCME_NOTFOUND;
+
+	if (pwr_type < TXPWR_CACHE_NUM_TYPES) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if (entryptr != NULL) {
+			ppr_copy_struct(pwrptr, entryptr->cache_pwrs[pwr_type]);
+			entryptr->data_invalid_flags &= ~(0x01 << pwr_type); /* now valid */
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+
+void wlc_phy_txpwr_cache_clear(osl_t* osh, tx_pwr_cache_entry_t* cacheptr,
+	chanspec_t chanspec)
+{
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+	if (entryptr != NULL) {
+		entryptr->chanspec = 0;
+		entryptr->data_invalid_flags = TXPWR_ALL_INVALID;
+	}
+}
+
+
+void wlc_phy_txpwr_cache_close(osl_t* osh, tx_pwr_cache_entry_t* cacheptr)
+{
+	uint i;
+
+	for (i = 0; i < MAX_TXPWR_CACHE_ENTRIES; i++) {
+		tx_pwr_cache_entry_t* entryptr = tx_pwr_cache_get(cacheptr, i);
+		wlc_phy_txpwr_cache_clear_entry(osh, entryptr);
+	}
+	MFREE(osh, cacheptr, (uint)sizeof(*cacheptr) * MAX_TXPWR_CACHE_ENTRIES);
+}
+
+
+tx_pwr_cache_entry_t* wlc_phy_txpwr_cache_create(osl_t* osh)
+{
+	int i, j;
+	tx_pwr_cache_entry_t* cacheptr =
+		(tx_pwr_cache_entry_t*)MALLOC(osh,
+		(uint)sizeof(tx_pwr_cache_entry_t) * MAX_TXPWR_CACHE_ENTRIES);
+	if (cacheptr != NULL) {
+		memset(cacheptr, 0, (uint)sizeof(tx_pwr_cache_entry_t) * MAX_TXPWR_CACHE_ENTRIES);
+		/* Allocate memory for each entry */
+		for (i = 0; i < MAX_TXPWR_CACHE_ENTRIES; i++) {
+			tx_pwr_cache_entry_t* entryptr = tx_pwr_cache_get(cacheptr, i);
+			entryptr->data_invalid_flags = TXPWR_ALL_INVALID;
+			for (j = 0; j < TXPWR_CACHE_NUM_TYPES; j++) {
+				entryptr->cache_pwrs[j] = ppr_create(osh, ppr_get_max_bw());
+				if (!entryptr->cache_pwrs[j]) {
+					wlc_phy_txpwr_cache_close(osh, cacheptr);
+					return NULL;
+				}
+			}
+		}
+	}
+	return cacheptr;
+}
+
+
+/*
+ * Get a ppr_t struct of a given type from the cache for the specified chanspec.
+ * Return the pointer even if the cached data is invalid.
+ */
+ppr_t* wlc_phy_get_cached_ppr_ptr(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint pwr_type)
+{
+	ppr_t* pwrptr = NULL;
+
+	if (pwr_type < TXPWR_CACHE_NUM_TYPES) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if (entryptr != NULL)
+			pwrptr = entryptr->cache_pwrs[pwr_type];
+	}
+
+	return pwrptr;
+}
+
+
+/** Indicate if we have cached a particular ppr_t struct for any chanspec. */
+bool wlc_phy_is_pwr_cached(tx_pwr_cache_entry_t* cacheptr, uint pwr_type, ppr_t* pwrptr)
+{
+	bool result = FALSE;
+	uint i;
+
+	if (pwr_type < TXPWR_CACHE_NUM_TYPES) {
+		for (i = 0; (i < MAX_TXPWR_CACHE_ENTRIES) && (result == FALSE); i++) {
+			if (tx_pwr_cache_get(cacheptr, i)->cache_pwrs[pwr_type] == pwrptr) {
+				result = TRUE;
+			}
+		}
+	}
+	return result;
+}
+
+
+/* Get the maximum boardlim for the specified core and chanspec. */
+int8 wlc_phy_get_cached_boardlim(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec, uint core)
+{
+	uint8 board_lim = WL_RATE_DISABLED;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if (entryptr != NULL)
+			board_lim = entryptr->tx_pwr_max_boardlim[core];
+	}
+
+	return board_lim;
+}
+
+
+/* Set the maximum boardlim for the specified core and chanspec. */
+int wlc_phy_set_cached_boardlim(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec, uint core,
+	int8 board_lim)
+{
+	int result = BCME_NOTFOUND;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if (entryptr != NULL) {
+			entryptr->tx_pwr_max_boardlim[core] = board_lim;
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+/** Get the maximum power for the specified core and chanspec. */
+uint8 wlc_phy_get_cached_pwr_max(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec, uint core)
+{
+	uint8 max_pwr = WL_RATE_DISABLED;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if (entryptr != NULL)
+			max_pwr = entryptr->tx_pwr_max[core];
+	}
+
+	return max_pwr;
+}
+
+
+/** Set the maximum power for the specified core and chanspec. */
+int wlc_phy_set_cached_pwr_max(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec, uint core,
+	uint8 max_pwr)
+{
+	int result = BCME_NOTFOUND;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if (entryptr != NULL) {
+			entryptr->tx_pwr_max[core] = max_pwr;
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+
+/** Get the minimum power for the specified core and chanspec. */
+uint8 wlc_phy_get_cached_pwr_min(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec, uint core)
+{
+	uint8 min_pwr = WL_RATE_DISABLED;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if (entryptr != NULL)
+			min_pwr = entryptr->tx_pwr_min[core];
+	}
+
+	return min_pwr;
+}
+
+
+/** Set the minimum power for the specified core and chanspec. */
+int wlc_phy_set_cached_pwr_min(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec, uint core,
+	uint8 min_pwr)
+{
+	int result = BCME_NOTFOUND;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if (entryptr != NULL) {
+			entryptr->tx_pwr_min[core] = min_pwr;
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+
+/** Get the txchain offsets for the specified chanspec. */
+int8 wlc_phy_get_cached_txchain_offsets(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint core)
+{
+	uint8 offset = WL_RATE_DISABLED;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if (entryptr != NULL)
+			offset = entryptr->txchain_offsets[core];
+	}
+
+	return offset;
+}
+
+
+/** Set the txchain offsets for the specified chanspec. */
+int wlc_phy_set_cached_txchain_offsets(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint core, int8 offset)
+{
+	int result = BCME_NOTFOUND;
+
+	if (core < PPR_MAX_TX_CHAINS) {
+		tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+		if (entryptr != NULL) {
+			entryptr->txchain_offsets[core] = offset;
+			result = BCME_OK;
+		}
+	}
+	return result;
+}
+
+
+/** Indicate if we have a cache entry for the specified chanspec. */
+bool wlc_phy_txpwr_cache_is_cached(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec)
+{
+	bool result = FALSE;
+
+	if (wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec)) {
+		result = TRUE;
+	}
+	return result;
+}
+
+
+/** Find a cache entry that's NOT for the specified chanspec. Return the chanspec. */
+chanspec_t wlc_phy_txpwr_cache_find_other_cached_chanspec(tx_pwr_cache_entry_t* cacheptr,
+	chanspec_t chanspec)
+{
+	chanspec_t chan = 0;
+
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_diff_entry(cacheptr, chanspec);
+	if (entryptr != NULL) {
+		chan = entryptr->chanspec;
+	}
+	return chan;
+}
+
+
+/** Invalidate all cached data. */
+void wlc_phy_txpwr_cache_invalidate(tx_pwr_cache_entry_t* cacheptr)
+{
+	uint j;
+
+	for (j = 0; j < MAX_TXPWR_CACHE_ENTRIES; j++) {
+		tx_pwr_cache_entry_t* entryptr = tx_pwr_cache_get(cacheptr, j);
+		if (entryptr->chanspec != 0) {
+			uint i;
+			entryptr->data_invalid_flags = TXPWR_ALL_INVALID;
+			for (i = 0; i < PPR_MAX_TX_CHAINS; i++) {
+				entryptr->tx_pwr_min[i] = TXPWR_CACHE_TXPWR_MAX;
+				entryptr->tx_pwr_max[i] = WL_RATE_DISABLED;
+				entryptr->txchain_offsets[i] = WL_RATE_DISABLED;
+			}
+			entryptr->stf_tx_max_offset = TXPWR_CACHE_TXPWR_MAX;
+#ifdef WL_SARLIMIT
+			entryptr->sar_lims = TXPWR_CACHE_SARLIMS_MAX;
+#endif
+		}
+	}
+}
+
+
+/** Find an empty cache entry and initialise it. */
+int wlc_phy_txpwr_setup_entry(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec)
+{
+	int result = BCME_NOTFOUND;
+
+	/* find an empty entry */
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, 0);
+	if (entryptr != NULL) {
+		uint i;
+
+		entryptr->chanspec = chanspec;
+		for (i = 0; i < PPR_MAX_TX_CHAINS; i++) {
+			entryptr->tx_pwr_min[i] = TXPWR_CACHE_TXPWR_MAX; /* WLC_TXPWR_MAX; */
+			entryptr->tx_pwr_max[i] = WL_RATE_DISABLED;
+			entryptr->txchain_offsets[i] = WL_RATE_DISABLED;
+		}
+		entryptr->stf_tx_max_offset = TXPWR_CACHE_TXPWR_MAX;
+#ifdef WL_SARLIMIT
+		entryptr->sar_lims = TXPWR_CACHE_SARLIMS_MAX;
+#endif
+		result = BCME_OK;
+	}
+	return result;
+}
+
+#ifdef WL_SARLIMIT
+void wlc_phy_set_cached_sar_lims(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint32 sar_lims)
+{
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+	if (entryptr != NULL) {
+		entryptr->sar_lims = sar_lims;
+	}
+}
+
+
+uint32 wlc_phy_get_cached_sar_lims(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec)
+{
+	uint32 sar_lims = TXPWR_CACHE_SARLIMS_MAX;
+
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+	if (entryptr != NULL)
+		sar_lims = entryptr->sar_lims;
+
+	return sar_lims;
+}
+#endif /* WL_SARLIMIT */
+
+
+#ifndef WLTXPWR_CACHE_PHY_ONLY
+
+/** Get the cached minimum Tx power */
+int wlc_phy_get_cached_stf_pwr_min_dbm(tx_pwr_cache_entry_t* cacheptr)
+{
+	return stf_tx_pwr_min;
+}
+
+/** set the cached minimum Tx power */
+void wlc_phy_set_cached_stf_pwr_min_dbm(tx_pwr_cache_entry_t* cacheptr, int min_pwr)
+{
+	stf_tx_pwr_min = min_pwr;
+}
+
+void wlc_phy_set_cached_stf_max_offset(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec,
+	uint8 max_offset)
+{
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+	if (entryptr != NULL) {
+		entryptr->stf_tx_max_offset = max_offset;
+	}
+}
+
+uint8 wlc_phy_get_cached_stf_max_offset(tx_pwr_cache_entry_t* cacheptr, chanspec_t chanspec)
+{
+	uint8 max_offset = TXPWR_CACHE_TXPWR_MAX;
+
+	tx_pwr_cache_entry_t* entryptr = wlc_phy_txpwr_cache_get_entry(cacheptr, chanspec);
+
+	if (entryptr != NULL)
+		max_offset = entryptr->stf_tx_max_offset;
+
+	return max_offset;
+
+}
+#endif /* WLTXPWR_CACHE_PHY_ONLY */
+#endif /* WLTXPWR_CACHE */
diff --git a/wl/src/wl/sys/wlc_rwl.c b/wl/src/wl/sys/wlc_rwl.c
new file mode 100644
index 0000000..d58b82a
--- /dev/null
+++ b/wl/src/wl/sys/wlc_rwl.c
@@ -0,0 +1,524 @@
+/*
+ * RWL module  of
+ * Broadcom 802.11bang Networking Device Driver
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlc_rwl.c 619400 2016-02-16 13:52:43Z $*
+ *
+ */
+
+/**
+ * @file
+ * @brief
+ * Remote WL utility support
+ */
+
+
+#include <wlc_cfg.h>
+
+#ifndef WLRWL
+#error "Cannot use this file without WLRWL defined"
+#endif
+
+#include <typedefs.h>
+#include <bcmdefs.h>
+#include <osl.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <wlioctl.h>
+#include <proto/802.11.h>
+#include <d11.h>
+#include <wlc_rate.h>
+#include <wlc_pub.h>
+#include <wlc_bsscfg.h>
+#include <wlc.h>
+#include <wlc_phy_hal.h>
+#include <wl_export.h>
+
+#include <wlc_rwl.h>
+
+enum {
+	IOV_RWLVS_ACTION_FRAME, /* RWL Vendor specific queue */
+	IOV_RWLDONGLE_DATA,
+	IOV_DONGLE_FLAG,
+	IOV_LAST
+};
+
+static const bcm_iovar_t rwl_iovars[] = {
+	{"rwlwifivsaction", IOV_RWLVS_ACTION_FRAME,
+	(0), 0, IOVT_BUFFER, RWL_WIFI_ACTION_FRAME_SIZE
+	},
+#ifdef RWL_DONGLE
+	{"remote", IOV_RWLDONGLE_DATA, 0, 0, IOVT_BUFFER, 1040},
+	{"dongleset", IOV_DONGLE_FLAG, 0, 0, IOVT_UINT32, 0},
+#endif /* RWL_DONGLE */
+	{NULL, 0, 0, 0, 0, 0 }
+};
+
+#ifdef RWL_DONGLE
+int g_rwl_dongle_flag = 0;
+#endif
+
+/* rwl function prototypes */
+
+static int wlc_rwl_doiovar(void *hdl, uint32 actionid,
+	void *params, uint p_len, void *arg, uint len,
+	uint val_size, struct wlc_if *wlcif);
+
+rwl_info_t *
+BCMATTACHFN(wlc_rwl_attach)(wlc_info_t *wlc)
+{
+	rwl_info_t *ri;
+	wlc_pub_t *pub = wlc->pub;
+
+	WL_TRACE(("wl: wlc_rwl_attach\n"));
+
+	if ((ri = (rwl_info_t *)MALLOCZ(pub->osh, sizeof(rwl_info_t))) == NULL) {
+		WL_ERROR(("wlc_rwl_attach: out of memory, malloced %d bytes", MALLOCED(pub->osh)));
+		goto fail;
+	}
+	ri->wlc = (void*) wlc;
+	ri->pub = pub;
+
+	/* register module */
+	if (wlc_module_register(pub, rwl_iovars, "rwl", ri, wlc_rwl_doiovar,
+	                        NULL, NULL, NULL)) {
+		WL_ERROR(("wl%d: rwl wlc_module_register() failed\n", pub->unit));
+		goto fail;
+	}
+
+	return ri;
+
+fail:
+	if (ri) {
+		MFREE(ri->pub->osh, ri, sizeof(rwl_info_t));
+	}
+	return NULL;
+}
+
+int
+BCMATTACHFN(wlc_rwl_detach)(rwl_info_t *ri)
+{
+	wlc_info_t *wlc;
+	rwl_request_t *cleanup_node = (rwl_request_t *)(NULL);
+
+	WL_TRACE(("wl: %s: ri = %p\n", __FUNCTION__, OSL_OBFUSCATE_BUF(ri)));
+
+	wlc = (wlc_info_t*) ri->wlc;
+	wlc_module_unregister(ri->pub, "rwl", ri);
+
+	/* Clean up the queue only during the driver cleanup */
+	while (ri->rwl_first_action_node != NULL) {
+		cleanup_node = ri->rwl_first_action_node->next_request;
+		MFREE(wlc->osh, ri->rwl_first_action_node,
+		sizeof(rwl_request_t));
+		ri->rwl_first_action_node = cleanup_node;
+	}
+
+	MFREE(ri->pub->osh, ri, sizeof(rwl_info_t));
+
+	return 0;
+}
+
+void
+BCMINITFN(wlc_rwl_init)(rwl_info_t *ri)
+{
+}
+
+void
+BCMUNINITFN(wlc_rwl_deinit)(rwl_info_t *ri)
+{
+}
+
+void
+wlc_rwl_up(wlc_info_t *wlc)
+{
+}
+
+uint
+wlc_rwl_down(wlc_info_t *wlc)
+{
+	return 0;
+}
+
+/* Handling RWL related iovars */
+static int
+wlc_rwl_doiovar(void *hdl, uint32 actionid,
+	void *params, uint p_len, void *arg, uint len, uint val_size, struct wlc_if *wlcif)
+{
+	rwl_info_t *ri = (rwl_info_t *)hdl;
+	int err = 0;
+	int32 int_val;
+
+	if (p_len >= (int)sizeof(int_val))
+		bcopy(params, &int_val, sizeof(int_val));
+
+	switch (actionid) {
+		case IOV_GVAL(IOV_RWLVS_ACTION_FRAME):
+		{
+			dot11_action_wifi_vendor_specific_t *list;
+			rwl_request_t *intermediate_node;
+			list = (dot11_action_wifi_vendor_specific_t*)arg;
+			if (ri->rwl_first_action_node != NULL) {
+				/* pop from the list and copy to user buffer
+				 * and move the node to next node
+				 */
+				bcopy((char*)&ri->rwl_first_action_node->action_frame,
+				(char*)list, RWL_WIFI_ACTION_FRAME_SIZE);
+				intermediate_node = ri->rwl_first_action_node->next_request;
+				MFREE(ri->wlc->osh, ri->rwl_first_action_node,
+				sizeof(rwl_request_t));
+				ri->rwl_first_action_node = intermediate_node;
+			}
+			break;
+		}
+
+#ifdef RWL_DONGLE
+	case IOV_GVAL(IOV_RWLDONGLE_DATA):
+		/* Wait for serial protocol layer to set the packet_status bit
+		  *  if bit set then copy the data in arg
+		  *  reset the packet_status bit
+		  * if not set send 0 to server application
+		  */
+		if (g_rwl_dongle_data.packet_status) {
+			if (g_rwl_dongle_data.packet_buf != NULL) {
+				bcopy(g_rwl_dongle_data.packet_buf, (char*)arg,
+				 g_rwl_dongle_data.packet_len);
+				MFREE(NULL, g_rwl_dongle_data.packet_buf,
+				 g_rwl_dongle_data.packet_len);
+			}
+			g_rwl_dongle_data.packet_status = 0;
+		} else {
+			uint status = 0;
+			bcopy(&status, arg, sizeof(status));
+		}
+		break;
+	case IOV_SVAL(IOV_RWLDONGLE_DATA):
+		/* Transmit the server response to client
+		 * Code jumps to hnd_cons.c at this point
+		 */
+		remote_uart_tx(arg);
+		break;
+	case IOV_GVAL(IOV_DONGLE_FLAG):
+		{
+			*ret_int_ptr = g_rwl_dongle_flag;
+			break;
+		}
+	case IOV_SVAL(IOV_DONGLE_FLAG):
+		{
+			g_rwl_dongle_flag = int_val;
+			break;
+		}
+#endif /* RWL_DONGLE */
+
+	default:
+		err = BCME_UNSUPPORTED;
+		break;
+	}
+
+	return err;
+}
+
+#ifdef WIFI_REFLECTOR
+/* Allocate and initialize an wifi action frame */
+static dot11_action_wifi_vendor_specific_t *
+allocate_action_frame(wlc_info_t *wlc)
+{
+	dot11_action_wifi_vendor_specific_t *frame;
+
+	if ((frame = (dot11_action_wifi_vendor_specific_t *)
+	     MALLOC(wlc->osh, RWL_WIFI_ACTION_FRAME_SIZE)) == NULL)
+		return NULL;
+
+	frame->category  = DOT11_ACTION_CAT_VS;
+	frame->OUI[0]    = RWL_WIFI_OUI_BYTE0;
+	frame->OUI[1]    = RWL_WIFI_OUI_BYTE1;
+	frame->OUI[2]    = RWL_WIFI_OUI_BYTE2;
+	frame->type      = RWL_WIFI_DEFAULT_TYPE;
+	frame->subtype   = RWL_WIFI_DEFAULT_SUBTYPE;
+
+	return frame;
+}
+
+/* Send out the action frame */
+static int
+rwl_send_wifi_response(wlc_info_t *wlc,
+                       dot11_action_wifi_vendor_specific_t *response,
+                       const struct ether_addr * dest_addr_ptr)
+{
+	uint32 err = 0;
+
+#ifdef WIFI_ACT_FRAME
+	wl_action_frame_t *action_frame;
+
+	if ((action_frame = (wl_action_frame_t *)
+	     MALLOC(wlc->osh, sizeof(wl_action_frame_t))) == NULL)
+		return BCME_NOMEM;
+
+	memcpy(&action_frame->data, response, RWL_WIFI_ACTION_FRAME_SIZE);
+
+	/* Set the dest addr */
+	memcpy(&action_frame->da, dest_addr_ptr, ETHER_ADDR_LEN);
+
+	/* set the length */
+	action_frame->len = RWL_WIFI_ACTION_FRAME_SIZE;
+
+	wlc_send_action_frame(wlc, wlc->cfg, NULL, (void *)action_frame);
+
+	MFREE(wlc->osh, action_frame, sizeof(wl_action_frame_t));
+#endif /* WIFI_ACT_FRAME */
+
+	return err;
+}
+
+/* Function to specify the client that an invalid wl command has been received
+ * This command cannot be processed by the In-dongle reflector.
+ */
+static int
+rwl_wifi_send_error(wlc_info_t *wlc, const struct ether_addr * dest_addr_ptr)
+{
+	int err;
+	dot11_action_wifi_vendor_specific_t *response;
+	rem_ioctl_t rem_cdc, *rem_ptr = &rem_cdc;
+	const char *errmsg = "In-dongle does not support shell/DHD/ASD\n";
+
+	if ((response = allocate_action_frame(wlc)) == NULL)
+		return BCME_NOMEM;
+
+	rem_ptr->msg.cmd = -1;
+	rem_ptr->msg.len = rem_ptr->data_len = strlen(errmsg) + 1;
+	rem_ptr->msg.flags = REMOTE_REPLY;
+
+	memcpy(&response->data[RWL_WIFI_CDC_HEADER_OFFSET], rem_ptr, REMOTE_SIZE);
+	memcpy(&response->data[REMOTE_SIZE], errmsg, rem_ptr->data_len);
+
+	err = rwl_send_wifi_response(wlc, response, dest_addr_ptr);
+
+	MFREE(wlc->osh, response, sizeof(dot11_action_wifi_vendor_specific_t));
+
+	return err;
+}
+
+/* Function which responds to the findserver command when sent by the client
+ * application. The client sends out packet in every channel available.
+ * we recieve the packet on a particular channel we respond back by sending
+ * our channel number
+ */
+static int
+rwl_wifi_findserver_response(wlc_info_t *wlc,
+                             dot11_action_wifi_vendor_specific_t *response,
+                             const struct ether_addr * dest_addr_ptr)
+{
+	int err;
+	channel_info_t ci;
+	uint32 tx_count;
+
+	/* Query the server channel */
+	response->type = RWL_WIFI_FOUND_PEER;
+
+	err = wlc_ioctl(wlc, WLC_GET_CHANNEL, &ci, sizeof(ci), NULL);
+	if (err)
+		return err;
+
+	/* Match the client channel with our channel */
+	if (response->data[RWL_WIFI_CLIENT_CHANNEL_OFFSET] == ci.hw_channel) {
+		response->data[RWL_WIFI_SERVER_CHANNEL_OFFSET] = ci.hw_channel;
+		for (tx_count = 0; tx_count < RWL_WIFI_SEND; ++tx_count) {
+			err = rwl_send_wifi_response(wlc, response, dest_addr_ptr);
+			if (err)
+				break;
+		}
+	}
+
+	return err;
+}
+
+/* Function which responds to the set command sent by the client.
+ * We call wlc_ioctl to set the specified value and send back the
+ * results of setting to the client
+ */
+static int
+rwl_wifi_set_cmd_response(wlc_info_t *wlc,
+                          rem_packet_t *rem_packet_ptr,
+                          const struct ether_addr * dest_addr_ptr)
+{
+	int err;
+	rem_ioctl_t rem_cdc, *rem_ptr = &rem_cdc;
+	rem_ioctl_t *rem_ioctl_ptr = (rem_ioctl_t *)&(rem_packet_ptr->rem_cdc);
+
+	dot11_action_wifi_vendor_specific_t *rem_wifi_send = allocate_action_frame(wlc);
+
+	if (rem_wifi_send == NULL)
+		return BCME_NOMEM;
+
+	/* Execute the command locally */
+
+	err = wlc_ioctl(wlc, rem_ioctl_ptr->msg.cmd, rem_packet_ptr->message,
+	                rem_ioctl_ptr->msg.len, NULL);
+
+	rem_ptr->msg.cmd = err;
+	rem_ptr->msg.len = 0;
+	rem_ptr->msg.flags = REMOTE_REPLY;
+	rem_ptr->data_len = 0;
+
+	memcpy(&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET], rem_ptr, REMOTE_SIZE);
+
+	err = rwl_send_wifi_response(wlc, rem_wifi_send, dest_addr_ptr);
+
+	MFREE(wlc->osh, rem_wifi_send, sizeof(*rem_wifi_send));
+
+	return err;
+}
+
+/* This function responds to the remote wl get command.
+ * On reception of packet we call wlc_ioctl() to get the results.
+ * If the result fits into a single packet we send it directly
+ * else we fragment the results and send it though multiple packets
+ */
+static int
+rwl_wifi_get_cmd_response(wlc_info_t *wlc,
+                          rem_packet_t *rem_packet_ptr,
+                          const struct ether_addr * dest_addr_ptr)
+{
+	int err;
+	uint32 tx_count;
+	uint32 totalframes;
+	uchar *buf;
+	rem_ioctl_t rem_cdc, *rem_ptr = &rem_cdc;
+	rem_ioctl_t *rem_ioctl_ptr = (rem_ioctl_t *)&(rem_packet_ptr->rem_cdc);
+	dot11_action_wifi_vendor_specific_t *rem_wifi_send = allocate_action_frame(wlc);
+
+	if (rem_wifi_send == NULL)
+		return BCME_NOMEM;
+
+	if ((buf = MALLOC(wlc->osh, rem_ioctl_ptr->msg.len)) == NULL) {
+		MFREE(wlc->osh, rem_wifi_send, sizeof(*rem_wifi_send));
+		return BCME_NOMEM;
+	}
+
+	/* Execute the command locally */
+	memcpy(buf, rem_packet_ptr->message, rem_ioctl_ptr->data_len);
+	err = wlc_ioctl(wlc, rem_ioctl_ptr->msg.cmd, (void*)buf,
+	                rem_ioctl_ptr->msg.len, NULL);
+
+	rem_ptr->msg.cmd = err;
+	rem_ptr->msg.len = rem_ioctl_ptr->msg.len;
+	rem_ptr->msg.flags = REMOTE_REPLY;
+	rem_ptr->data_len = rem_ioctl_ptr->msg.len;
+
+	if (rem_ioctl_ptr->msg.len > RWL_WIFI_FRAG_DATA_SIZE) {
+		totalframes = rem_ptr->msg.len / RWL_WIFI_FRAG_DATA_SIZE;
+		memcpy(&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET], rem_ptr, REMOTE_SIZE);
+		memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE], &buf[0], RWL_WIFI_FRAG_DATA_SIZE);
+		rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
+		rem_wifi_send->subtype = RWL_WIFI_DEFAULT_SUBTYPE;
+
+		if ((err = rwl_send_wifi_response (wlc, rem_wifi_send, dest_addr_ptr)) != 0)
+			goto exit;
+
+		/* Send remaining bytes in fragments */
+		for (tx_count = 1; tx_count < totalframes; tx_count++) {
+			rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
+			rem_wifi_send->subtype = tx_count;
+			/* First frame onwards , buf contains only data */
+			memcpy((char*)&rem_wifi_send->data,
+			       &buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE], RWL_WIFI_FRAG_DATA_SIZE);
+			if ((err = rwl_send_wifi_response (wlc,
+			                                   rem_wifi_send,
+			                                   dest_addr_ptr)) != 0) {
+				goto exit;
+			}
+
+		}
+		/* Check for remaining bytes to send */
+		if ((totalframes * RWL_WIFI_FRAG_DATA_SIZE) != rem_ptr->msg.len) {
+			rem_wifi_send->type = RWL_ACTION_WIFI_FRAG_TYPE;
+			rem_wifi_send->subtype = tx_count;
+			memcpy((char*)&rem_wifi_send->data,
+			       &buf[tx_count*RWL_WIFI_FRAG_DATA_SIZE],
+			       (rem_ptr->msg.len - (tx_count*RWL_WIFI_FRAG_DATA_SIZE)));
+			err = rwl_send_wifi_response(wlc, rem_wifi_send, dest_addr_ptr);
+		}
+	} else {
+		/* Packet fits into a single frame; send it off at one go */
+		memcpy(&rem_wifi_send->data[RWL_WIFI_CDC_HEADER_OFFSET], rem_ptr, REMOTE_SIZE);
+		memcpy((char*)&rem_wifi_send->data[REMOTE_SIZE],
+		       buf, rem_ioctl_ptr->msg.len);
+
+		err = rwl_send_wifi_response(wlc, rem_wifi_send, dest_addr_ptr);
+	}
+exit:
+	MFREE(wlc->osh, rem_wifi_send,
+		sizeof(dot11_action_wifi_vendor_specific_t));
+
+	MFREE(wlc->osh, buf, rem_ioctl_ptr->msg.len);
+
+	return err;
+}
+#endif /* WIFI_REFLECTOR */
+
+/* If the management frame is an RWL action frame then the action frame will be queued.
+ * This queued frame will be read by the application.
+ */
+void
+wlc_recv_wifi_mgmtact(rwl_info_t *rwlh, uint8 *body, const struct ether_addr *sa)
+{
+
+#ifdef WIFI_REFLECTOR
+	rem_packet_t *rem_packet_ptr;
+	rem_ioctl_t *rem_ioctl_ptr;
+#endif
+	rwl_request_t *rwl_new_action_node =
+	(rwl_request_t *)(NULL);
+	wlc_info_t *wlc = (wlc_info_t*) rwlh->wlc;
+
+	if ((rwl_new_action_node = (rwl_request_t*)MALLOC(wlc->osh,
+		sizeof(rwl_request_t))) == NULL) {
+		return;
+	}
+
+	bcopy((char*)body, (char*)&rwl_new_action_node->action_frame, RWL_WIFI_ACTION_FRAME_SIZE);
+#ifdef WIFI_REFLECTOR
+	rem_packet_ptr = (rem_packet_t *)&(rwl_new_action_node->action_frame.data[0]);
+	rem_ioctl_ptr = (rem_ioctl_t *)&(rem_packet_ptr->rem_cdc);
+
+	/* Do not queue the packets if it is an RWL command.
+	 * Just parse, process and send back the results depending
+	 * upon the query packet. Do not queue any packets, as
+	 * after a certain number of packets the dongle memory would
+	 * be exhausted.
+	 */
+	if (rem_ioctl_ptr->msg.flags & REMOTE_FINDSERVER_CMD)
+		rwl_wifi_findserver_response(wlc, &rwl_new_action_node->action_frame, sa);
+	else if (rem_ioctl_ptr->msg.flags & REMOTE_SET_CMD)
+		rwl_wifi_set_cmd_response(wlc, rem_packet_ptr, sa);
+	else if (rem_ioctl_ptr->msg.flags & REMOTE_GET_CMD)
+		rwl_wifi_get_cmd_response(wlc, rem_packet_ptr, sa);
+	else
+		rwl_wifi_send_error(wlc, sa);
+
+	MFREE(wlc->osh, rwl_new_action_node, sizeof(rwl_request_t));
+	return;
+
+#endif /* WIFI_REFLECTOR */
+	if (rwlh->rwl_first_action_node == NULL) {
+		 rwlh->rwl_first_action_node = rwl_new_action_node;
+		 rwlh->rwl_last_action_node = rwlh->rwl_first_action_node;
+		 rwlh->rwl_first_action_node->next_request = NULL;
+	} else {
+		/* insert the all incoming frame at the end of the queue */
+		rwlh->rwl_last_action_node->next_request = rwl_new_action_node;
+		rwlh->rwl_last_action_node = rwl_new_action_node;
+		rwlh->rwl_last_action_node->next_request = NULL;
+	}
+}
diff --git a/wl/src/wl/sys/wlc_rwl.h b/wl/src/wl/sys/wlc_rwl.h
new file mode 100644
index 0000000..279278c
--- /dev/null
+++ b/wl/src/wl/sys/wlc_rwl.h
@@ -0,0 +1,64 @@
+/*
+ * RWL module  of
+ * Broadcom 802.11bang Networking Device Driver
+ *
+ * Broadcom Proprietary and Confidential. Copyright (C) 2017,
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Proprietary:>>
+ *
+ * $Id: wlc_rwl.h 524641 2015-01-07 15:25:03Z $
+ *
+ */
+
+
+#ifndef _wlc_rwl_h_
+#define _wlc_rwl_h_
+
+#if defined(RWL_WIFI) || defined(WIFI_REFLECTOR)
+
+#include <rwl_wifi.h>
+
+typedef struct rwl_info {
+	wlc_info_t	*wlc;
+	wlc_pub_t	*pub;
+	rwl_request_t *rwl_first_action_node;
+	rwl_request_t *rwl_last_action_node;
+	struct ether_addr rwl_ea;
+} rwl_info_t;
+
+extern rwl_info_t* wlc_rwl_attach(wlc_info_t *wlc);
+extern int wlc_rwl_detach(rwl_info_t *rwlh);
+extern void wlc_rwl_init(rwl_info_t *rwlh);
+extern void wlc_rwl_deinit(rwl_info_t *rwlh);
+extern void wlc_rwl_up(wlc_info_t *wlc);
+extern uint wlc_rwl_down(wlc_info_t *wlc);
+extern void wlc_rwl_frameaction(rwl_info_t *rwlh, struct dot11_management_header *hdr,
+                                uint8 *body, int body_len);
+extern void wlc_recv_wifi_mgmtact(rwl_info_t *rwlh, uint8 *body, const struct ether_addr * sa);
+
+#else /* !defined(RWL_WIFI) && !defined(WIFI_REFLECTOR) && !defined(WLTEST) */
+
+typedef struct rwl_info {
+	wlc_info_t	*wlc;
+	wlc_pub_t	*pub;
+} rwl_info_t;
+
+#define wlc_rwl_attach(a)		(rwl_info_t *)0xdeadbeef
+#define wlc_rwl_detach(a)		0
+#define wlc_rwl_init(a)			do {} while (0)
+#define wlc_rwl_deinit(a)		do {} while (0)
+#define wlc_rwl_up(a)			do {} while (0)
+#define wlc_rwl_down(a)			0
+#define wlc_rwl_frameaction(a)		do {} while (0)
+#define wlc_recv_wifi_mgmtact(a, b, c)	do {} while (0)
+
+#endif 
+
+#endif	/* _wlc_rwl_h_ */